// File: /workspace/github_cpp_makefile_star2_O2/OpenFirework[P]MyJPEG_Decoder/./bmp/bmp_code.cpp
// Function: MyBMP::BMP::decode(char const*, int&, int&, unsigned char*&)
void MyBMP::BMP::decode(const char *filename, int &width, int &height, byte *&bgrdata) {
    std::ifstream infile;
    infile.open(filename, std::ios::in|std::ios::binary);
    infile.seekg(0, infile.end);
    int bmpdatalength = infile.tellg();
    infile.seekg(0, infile.beg);
    std::cout << "bmp data length is " << bmpdatalength<<"\n";
    //all data
    byte *bmpdata = new byte[bmpdatalength];
    byte *copyptr = bmpdata;  //保存首地址，便于以后释放
    infile.read((char*)bmpdata, bmpdatalength);  //读取编码的jpeg文件数据到内存中
    infile.close();

    //read file header
    memcpy(&fileHeader.bfType, bmpdata, sizeof(fileHeader.bfType));
    bmpdata = bmpdata + sizeof(fileHeader.bfType);
    memcpy(&fileHeader.bfSize, bmpdata, sizeof(fileHeader.bfSize));
    bmpdata = bmpdata + sizeof(fileHeader.bfSize);
    memcpy(&fileHeader.bfReserved1, bmpdata, sizeof(fileHeader.bfReserved1));
    bmpdata = bmpdata + sizeof(fileHeader.bfReserved1);
    memcpy(&fileHeader.bfReserved2, bmpdata, sizeof(fileHeader.bfReserved2));
    bmpdata = bmpdata + sizeof(fileHeader.bfReserved2);
    memcpy(&fileHeader.bfOffBits, bmpdata, sizeof(fileHeader.bfOffBits));
    bmpdata = bmpdata + sizeof(fileHeader.bfOffBits);
    showBmpHead(fileHeader);

    //read info header
    memcpy(&infoHeader, bmpdata, sizeof(BITMAPINFOHEADER));
    bmpdata = bmpdata + sizeof(BITMAPINFOHEADER);
    showBmpInfoHead(infoHeader);

    height = infoHeader.biHeight;
    width = infoHeader.biWidth;
   
    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;
    if((bmpdatalength - fileHeader.bfOffBits) != (infoHeader.biSizeImage)) {
        if((bmpdatalength - fileHeader.bfOffBits) != datasize) {
            std::cout<<"******BMP DATA is WRONG******\n";
        }
    }
    //给外部使用的，不能删除
    bgrdata = new byte[height*width*3];

    //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)*bytes_per_row + w*3;
            bgrdata[offset*3] = bmpdata[inflect];
            bgrdata[offset*3+1] = bmpdata[inflect+1];
            bgrdata[offset*3+2] = bmpdata[inflect+2];

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

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x278, %rsp            # imm = 0x278
movq %r8, %rbx
movq %rcx, %r14
movq %rdx, -0x38(%rbp)
movq %rsi, %r12
movq %rdi, %r15
leaq -0x278(%rbp), %r13
movq %r13, %rdi
callq 0x2140
pushq $0xc
popq %rdx
movq %r13, %rdi
movq %r12, %rsi
callq 0x20d0
leaq -0x278(%rbp), %rdi
pushq $0x2
popq %rdx
xorl %esi, %esi
callq 0x2180
leaq -0x278(%rbp), %rdi
callq 0x2220
movq %rax, %r12
leaq -0x278(%rbp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2180
movq 0x3cae(%rip), %rdi      # 0x6fd0
leaq 0xfe7(%rip), %rsi       # 0x4310
callq 0x2110
movq %rax, %rdi
movl %r12d, %esi
callq 0x2210
leaq 0x12ce(%rip), %rsi      # 0x460e
movq %rax, %rdi
callq 0x2110
movq %r12, -0x30(%rbp)
movslq %r12d, %r13
movq %r13, %rdi
callq 0x2030
movq %rax, %r12
leaq -0x278(%rbp), %rdi
movq %rax, %rsi
movq %r13, %rdx
callq 0x2150
leaq -0x278(%rbp), %rdi
callq 0x2060
movzwl (%r12), %eax
movw %ax, (%r15)
movl 0x2(%r12), %eax
movl %eax, 0x4(%r15)
movzwl 0x6(%r12), %eax
movw %ax, 0x8(%r15)
movzwl 0x8(%r12), %eax
movw %ax, 0xa(%r15)
movl 0xa(%r12), %eax
movl %eax, 0xc(%r15)
movq (%r15), %rsi
movq 0x8(%r15), %rdx
callq 0x3552
movq 0x2e(%r12), %rax
movq %rax, 0x30(%r15)
movups 0xe(%r12), %xmm0
movups 0x1e(%r12), %xmm1
movups %xmm1, 0x20(%r15)
movups %xmm0, 0x10(%r15)
movq 0x2e(%r12), %rax
movq %rax, -0x50(%rbp)
movups 0xe(%r12), %xmm0
movups 0x1e(%r12), %xmm1
movaps %xmm1, -0x60(%rbp)
movaps %xmm0, -0x70(%rbp)
movq -0x50(%rbp), %rax
movq %rax, 0x20(%rsp)
movaps -0x70(%rbp), %xmm0
movaps -0x60(%rbp), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
callq 0x35bc
movl 0x18(%r15), %eax
movl %eax, (%r14)
movq %r15, -0x40(%rbp)
movl 0x14(%r15), %r15d
movq -0x38(%rbp), %rax
movl %r15d, (%rax)
imull $0x18, %r15d, %eax
addl $0x1f, %eax
cvtsi2sd %eax, %xmm0
mulsd 0xecf(%rip), %xmm0      # 0x4308
callq 0x21f0
cvttsd2si %xmm0, %r13d
movq -0x40(%rbp), %rsi
movl 0xc(%rsi), %eax
movq -0x30(%rbp), %rcx
subl %eax, %ecx
movl (%r14), %edx
cmpl 0x24(%rsi), %ecx
je 0x3482
movl %r13d, %eax
imull %edx, %eax
shll $0x2, %eax
cmpl %eax, %ecx
je 0x3482
movq 0x3b64(%rip), %rdi      # 0x6fd0
leaq 0xeb1(%rip), %rsi       # 0x4324
callq 0x2110
movl (%r14), %edx
movq -0x38(%rbp), %rax
movl (%rax), %r15d
movl %edx, -0x30(%rbp)
movl %edx, %eax
imull %r15d, %eax
leal (%rax,%rax,2), %eax
movslq %eax, %rdi
callq 0x2030
movq %rax, (%rbx)
shll $0x2, %r13d
xorl %eax, %eax
pushq $-0x1
popq %rcx
movl -0x30(%rbp), %edx
cmpl %edx, %eax
jge 0x350b
xorl %edx, %edx
xorl %esi, %esi
cmpl %r15d, %esi
jge 0x3502
imull %eax, %r15d
addl %esi, %r15d
movl (%r14), %edi
addl %ecx, %edi
imull %r13d, %edi
addl %edx, %edi
movslq %edi, %rdi
movb 0x36(%r12,%rdi), %r8b
movq (%rbx), %r9
movslq %r15d, %r10
leaq (%r10,%r10,2), %r10
movb %r8b, (%r9,%r10)
movb 0x37(%r12,%rdi), %r8b
movq (%rbx), %r9
movb %r8b, 0x1(%r9,%r10)
movb 0x38(%r12,%rdi), %dil
movq (%rbx), %r8
movb %dil, 0x2(%r8,%r10)
incl %esi
movq -0x38(%rbp), %rdi
movl (%rdi), %r15d
addl $0x3, %edx
jmp 0x34ad
incl %eax
movl (%r14), %edx
decl %ecx
jmp 0x34a5
movq %r12, %rdi
callq 0x2160
leaq -0x278(%rbp), %rdi
callq 0x2070
addq $0x278, %rsp            # imm = 0x278
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x353b
jmp 0x353b
jmp 0x353b
jmp 0x353b
jmp 0x353b
movq %rax, %rbx
leaq -0x278(%rbp), %rdi
callq 0x2070
movq %rbx, %rdi
callq 0x2230