// File: /workspace/github_cpp_makefile_star2_O2/OpenFirework[P]MyJPEG_Decoder/./bmp/bmp_code.cpp
// Function: MyBMP::BMP::encode(char const*, int, int, unsigned char*&)
void MyBMP::BMP::encode(const char *filename, int width, int height, byte *&bgrdata) {
    BITMAPFILEHEADER header;
    BITMAPINFOHEADER info;
    int bytes_per_row = 0;  
    int tmp = floor((24*width + 31)*1.0/32);
    bytes_per_row = tmp*4;    
    int datasize = bytes_per_row*height;
    header.bfType = 0x4d42;
    header.bfSize = datasize + 54;
    header.bfReserved1 = 0;
    header.bfReserved2 = 0;
    header.bfOffBits = 54;

    info.biSize = 40;
    info.biWidth = width;
    info.biHeight = height;
    info.biPlanes = 1;
    info.biBitCount = 24;
    info.biCompression = 0;
    info.biSizeImage = 0;
    info.biXPelsPerMeter = 0;
    info.biYPelsPerMeter = 0;
    info.biClrUsed = 0;
    info.biClrImportant = 0;

    byte *bmpdata = new byte[width*height*3];
    byte *copyptr = bmpdata;
   // bmp的数据存储顺序是从左下到右上，而一般的习惯是从左上到右下，因此做一个转置
    for(int h=0;h<height;h++) {
        for(int w=0;w<width;w++) {           
            int offset = h*width + w;
            int inflect = (height - 1 -h)*width + w;
            bmpdata[offset*3] = bgrdata[inflect*3];
            bmpdata[offset*3+1] = bgrdata[inflect*3+1];
            bmpdata[offset*3+2] = bgrdata[inflect*3+2];
        }
    }
    int zeros = bytes_per_row-width*3;
    //保存到文件
    std::ofstream outfile;
    outfile.open(filename, std::ios::out|std::ios::binary);
    outfile.write((char*)&header.bfType, sizeof(header.bfType));
    outfile.write((char*)&header.bfSize, sizeof(header.bfSize));
    outfile.write((char*)&header.bfReserved1, sizeof(header.bfReserved1));
    outfile.write((char*)&header.bfReserved2, sizeof(header.bfReserved2));
    outfile.write((char*)&header.bfOffBits, sizeof(header.bfOffBits));

    outfile.write((char*)&info, sizeof(info));
    byte zero = 0;
    for(int h=0;h<height;h++) { 
        outfile.write((char*)bmpdata, width*3);
        bmpdata = bmpdata + width*3;
        for(int i=0;i<zeros; i++) {
            outfile.write((char*)&zero, 1);
        }
    }

    outfile.close();
    if(copyptr != nullptr) {
        delete[] copyptr;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x268, %rsp            # imm = 0x268
movq %r8, %r13
movl %ecx, %r15d
movl %edx, %r12d
movq %rsi, %r14
imull $0x18, %edx, %eax
addl $0x1f, %eax
cvtsi2sd %eax, %xmm0
mulsd 0xc4c(%rip), %xmm0      # 0x4308
callq 0x21f0
cvttsd2si %xmm0, %eax
shll $0x2, %eax
movl %eax, -0x2c(%rbp)
imull %r15d, %eax
leaq -0x40(%rbp), %rcx
movw $0x4d42, -0x4(%rcx)     # imm = 0x4D42
addl $0x36, %eax
movl %eax, (%rcx)
leaq -0x3c(%rbp), %rcx
movabsq $0x3600000000, %rax     # imm = 0x3600000000
movq %rax, (%rcx)
movl $0x28, -0x88(%rbp)
movl %r12d, -0x84(%rbp)
movl %r15d, -0x80(%rbp)
movl $0x180001, -0x7c(%rbp)  # imm = 0x180001
leal (%r12,%r12,2), %eax
movl %eax, -0x30(%rbp)
imull %r15d, %eax
movslq %eax, %rdi
xorpd %xmm0, %xmm0
movupd %xmm0, -0x78(%rbp)
andq $0x0, -0x68(%rbp)
callq 0x2030
movq %rax, %rsi
movq (%r13), %rax
xorl %ecx, %ecx
testl %r12d, %r12d
movl $0x0, %edx
cmovgl %r12d, %edx
testl %r15d, %r15d
movl $0x0, %r11d
cmovgl %r15d, %r11d
movslq %r12d, %rdi
leaq (%rdx,%rdx,2), %rdx
movq %rsi, -0x50(%rbp)
addq $0x2, %rsi
leaq (%rdi,%rdi,2), %rdi
addq $0x2, %rax
decl %r15d
imull %r12d, %r15d
cmpq %r11, %rcx
je 0x37b0
movslq %r15d, %r8
leaq (%r8,%r8,2), %r8
addq %rax, %r8
xorl %r9d, %r9d
cmpq %r9, %rdx
je 0x37a5
movb -0x2(%r8,%r9), %r10b
movb %r10b, -0x2(%rsi,%r9)
movb -0x1(%r8,%r9), %r10b
movb %r10b, -0x1(%rsi,%r9)
movb (%r8,%r9), %r10b
movb %r10b, (%rsi,%r9)
addq $0x3, %r9
jmp 0x377e
incq %rcx
addq %rdi, %rsi
subl %r12d, %r15d
jmp 0x376c
movq %r11, -0x60(%rbp)
leaq -0x288(%rbp), %rbx
movq %rbx, %rdi
callq 0x2200
pushq $0x14
popq %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2050
leaq -0x288(%rbp), %rdi
leaq -0x44(%rbp), %rsi
pushq $0x2
popq %rdx
callq 0x2170
leaq -0x288(%rbp), %rdi
pushq $0x4
popq %rdx
leaq -0x40(%rbp), %rsi
callq 0x2170
leaq -0x288(%rbp), %rdi
pushq $0x2
popq %rdx
leaq -0x3c(%rbp), %rsi
callq 0x2170
leaq -0x288(%rbp), %rdi
pushq $0x2
popq %rdx
leaq -0x3a(%rbp), %rsi
callq 0x2170
leaq -0x288(%rbp), %rdi
pushq $0x4
popq %rdx
leaq -0x38(%rbp), %rsi
callq 0x2170
leaq -0x288(%rbp), %rdi
leaq -0x88(%rbp), %rsi
pushq $0x28
popq %rdx
callq 0x2170
movl -0x2c(%rbp), %eax
movl -0x30(%rbp), %ecx
subl %ecx, %eax
leaq -0x31(%rbp), %r14
movb $0x0, (%r14)
xorl %edx, %edx
testl %eax, %eax
cmovlel %edx, %eax
movl %eax, -0x2c(%rbp)
movslq %ecx, %rax
movq %rax, -0x58(%rbp)
leaq -0x288(%rbp), %r12
pushq $0x1
popq %r13
movq -0x50(%rbp), %rbx
movl %edx, -0x30(%rbp)
cmpl -0x60(%rbp), %edx
je 0x38b4
movq %r12, %rdi
movq %rbx, %rsi
movq -0x58(%rbp), %r15
movq %r15, %rdx
callq 0x2170
addq %r15, %rbx
movl -0x2c(%rbp), %r15d
subl $0x1, %r15d
jb 0x38ad
movq %r12, %rdi
movq %r14, %rsi
movq %r13, %rdx
callq 0x2170
jmp 0x3897
movl -0x30(%rbp), %edx
incl %edx
jmp 0x3876
leaq -0x288(%rbp), %rdi
callq 0x2190
movq -0x50(%rbp), %rdi
callq 0x2160
leaq -0x288(%rbp), %rdi
callq 0x21a0
addq $0x268, %rsp            # imm = 0x268
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x38ed
jmp 0x38ed
jmp 0x38ed
movq %rax, %rbx
leaq -0x288(%rbp), %rdi
callq 0x21a0
movq %rbx, %rdi
callq 0x2230