// File: dannye[P]jed/src/encoder.cpp
// Function: readBMP(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
BMPImage readBMP(const std::string& filename) {
    BMPImage image;

    // open file
    std::cout << "Reading " << filename << "...\n";
    std::ifstream inFile(filename, std::ios::in | std::ios::binary);
    if (!inFile.is_open()) {
        std::cout << "Error - Error opening input file\n";
        return image;
    }

    if (inFile.get() != 'B' || inFile.get() != 'M') {
        std::cout << "Error - Invalid BMP file\n";
        inFile.close();
        return image;
    }

    getInt(inFile); // size
    getInt(inFile); // nothing
    if (getInt(inFile) != 0x1A) {
        std::cout << "Error - Invalid offset\n";
        inFile.close();
        return image;
    }
    if (getInt(inFile) != 12) {
        std::cout << "Error - Invalid DIB size\n";
        inFile.close();
        return image;
    }
    image.width = getShort(inFile);
    image.height = getShort(inFile);
    if (getShort(inFile) != 1) {
        std::cout << "Error - Invalid number of planes\n";
        inFile.close();
        return image;
    }
    if (getShort(inFile) != 24) {
        std::cout << "Error - Invalid bit depth\n";
        inFile.close();
        return image;
    }

    if (image.height == 0 || image.width == 0) {
        std::cout << "Error - Invalid dimensions\n";
        inFile.close();
        return image;
    }

    image.blockHeight = (image.height + 7) / 8;
    image.blockWidth = (image.width + 7) / 8;

    image.blocks = new (std::nothrow) Block[image.blockHeight * image.blockWidth];
    if (image.blocks == nullptr) {
        std::cout << "Error - Memory error\n";
        inFile.close();
        return image;
    }

    const uint paddingSize = image.width % 4;

    for (uint y = image.height - 1; y < image.height; --y) {
        const uint blockRow = y / 8;
        const uint pixelRow = y % 8;
        for (uint x = 0; x < image.width; ++x) {
            const uint blockColumn = x / 8;
            const uint pixelColumn = x % 8;
            const uint blockIndex = blockRow * image.blockWidth + blockColumn;
            const uint pixelIndex = pixelRow * 8 + pixelColumn;
            image.blocks[blockIndex].b[pixelIndex] = inFile.get();
            image.blocks[blockIndex].g[pixelIndex] = inFile.get();
            image.blocks[blockIndex].r[pixelIndex] = inFile.get();
        }
        for (uint i = 0; i < paddingSize; ++i) {
            inFile.get();
        }
    }

    inFile.close();
    return image;
}

// Assembly:
subq $0x2e8, %rsp            # imm = 0x2E8
movq %rdi, 0x68(%rsp)
movq %rdi, %rax
movq %rax, 0x70(%rsp)
movq %rsi, 0x2e0(%rsp)
callq 0x51b0
movq 0x7858(%rip), %rdi      # 0x9fd0
leaq 0x4911(%rip), %rsi      # 0x7090
callq 0x2130
movq %rax, %rdi
movq 0x2e0(%rsp), %rsi
callq 0x2120
movq %rax, %rdi
leaq 0x48fb(%rip), %rsi      # 0x7099
callq 0x2130
movq 0x2e0(%rsp), %rax
movq %rax, 0x78(%rsp)
movl $0x8, %edi
movl $0x4, %esi
callq 0x51e0
movq 0x78(%rsp), %rsi
movl %eax, %edx
leaq 0xd8(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x2200
movq 0x80(%rsp), %rdi
callq 0x21f0
movb %al, 0x8b(%rsp)
jmp 0x27f1
movb 0x8b(%rsp), %al
testb $0x1, %al
jne 0x2849
jmp 0x27fe
movq 0x77cb(%rip), %rdi      # 0x9fd0
leaq 0x4892(%rip), %rsi      # 0x709e
callq 0x2130
jmp 0x2813
movl $0x1, 0xc8(%rsp)
jmp 0x2df3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xd0(%rsp)
movl %eax, 0xcc(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x2050
jmp 0x2e0d
leaq 0xd8(%rsp), %rdi
callq 0x2180
movl %eax, 0x64(%rsp)
jmp 0x285c
movl 0x64(%rsp), %eax
cmpl $0x42, %eax
jne 0x2881
leaq 0xd8(%rsp), %rdi
callq 0x2180
movl %eax, 0x60(%rsp)
jmp 0x2878
movl 0x60(%rsp), %eax
cmpl $0x4d, %eax
je 0x28b5
movq 0x7748(%rip), %rdi      # 0x9fd0
leaq 0x4831(%rip), %rsi      # 0x70c0
callq 0x2130
jmp 0x2896
leaq 0xd8(%rsp), %rdi
callq 0x2040
jmp 0x28a5
movl $0x1, 0xc8(%rsp)
jmp 0x2df3
leaq 0xd8(%rsp), %rdi
callq 0x26a0
jmp 0x28c4
leaq 0xd8(%rsp), %rdi
callq 0x26a0
jmp 0x28d3
leaq 0xd8(%rsp), %rdi
callq 0x26a0
movl %eax, 0x5c(%rsp)
jmp 0x28e6
movl 0x5c(%rsp), %eax
cmpl $0x1a, %eax
je 0x2923
movq 0x76da(%rip), %rdi      # 0x9fd0
leaq 0x47dd(%rip), %rsi      # 0x70da
callq 0x2130
jmp 0x2904
leaq 0xd8(%rsp), %rdi
callq 0x2040
jmp 0x2913
movl $0x1, 0xc8(%rsp)
jmp 0x2df3
leaq 0xd8(%rsp), %rdi
callq 0x26a0
movl %eax, 0x58(%rsp)
jmp 0x2936
movl 0x58(%rsp), %eax
cmpl $0xc, %eax
je 0x2973
movq 0x768a(%rip), %rdi      # 0x9fd0
leaq 0x47a5(%rip), %rsi      # 0x70f2
callq 0x2130
jmp 0x2954
leaq 0xd8(%rsp), %rdi
callq 0x2040
jmp 0x2963
movl $0x1, 0xc8(%rsp)
jmp 0x2df3
leaq 0xd8(%rsp), %rdi
callq 0x2710
movl %eax, 0x54(%rsp)
jmp 0x2986
movq 0x68(%rsp), %rax
movl 0x54(%rsp), %ecx
movl %ecx, 0x4(%rax)
leaq 0xd8(%rsp), %rdi
callq 0x2710
movl %eax, 0x50(%rsp)
jmp 0x29a5
movq 0x68(%rsp), %rax
movl 0x50(%rsp), %ecx
movl %ecx, (%rax)
leaq 0xd8(%rsp), %rdi
callq 0x2710
movl %eax, 0x4c(%rsp)
jmp 0x29c3
movl 0x4c(%rsp), %eax
cmpl $0x1, %eax
je 0x2a00
movq 0x75fd(%rip), %rdi      # 0x9fd0
leaq 0x4732(%rip), %rsi      # 0x710c
callq 0x2130
jmp 0x29e1
leaq 0xd8(%rsp), %rdi
callq 0x2040
jmp 0x29f0
movl $0x1, 0xc8(%rsp)
jmp 0x2df3
leaq 0xd8(%rsp), %rdi
callq 0x2710
movl %eax, 0x48(%rsp)
jmp 0x2a13
movl 0x48(%rsp), %eax
cmpl $0x18, %eax
je 0x2a50
movq 0x75ad(%rip), %rdi      # 0x9fd0
leaq 0x4704(%rip), %rsi      # 0x712e
callq 0x2130
jmp 0x2a31
leaq 0xd8(%rsp), %rdi
callq 0x2040
jmp 0x2a40
movl $0x1, 0xc8(%rsp)
jmp 0x2df3
movq 0x68(%rsp), %rax
cmpl $0x0, (%rax)
je 0x2a65
movq 0x68(%rsp), %rax
cmpl $0x0, 0x4(%rax)
jne 0x2a99
movq 0x7564(%rip), %rdi      # 0x9fd0
leaq 0x46d6(%rip), %rsi      # 0x7149
callq 0x2130
jmp 0x2a7a
leaq 0xd8(%rsp), %rdi
callq 0x2040
jmp 0x2a89
movl $0x1, 0xc8(%rsp)
jmp 0x2df3
movq 0x68(%rsp), %rcx
movl (%rcx), %eax
addl $0x7, %eax
shrl $0x3, %eax
movl %eax, 0x10(%rcx)
movl 0x4(%rcx), %eax
addl $0x7, %eax
shrl $0x3, %eax
movl %eax, 0x14(%rcx)
movl 0x10(%rcx), %eax
imull 0x14(%rcx), %eax
movl %eax, %eax
movq %rax, 0x28(%rsp)
movl $0x300, %ecx            # imm = 0x300
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0x30(%rsp)
movq 0x74cd(%rip), %rsi      # 0x9fb8
callq 0x2220
movq %rax, %rcx
movq %rcx, 0x38(%rsp)
movb $0x0, 0xb7(%rsp)
xorl %eax, %eax
cmpq $0x0, %rcx
movq %rax, 0x40(%rsp)
je 0x2b94
movq 0x28(%rsp), %rax
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rdx
movq %rdx, 0xc0(%rsp)
movq %rcx, 0xb8(%rsp)
movb $0x1, 0xb7(%rsp)
cmpq $0x0, %rax
je 0x2b88
movq 0x38(%rsp), %rax
movq 0x28(%rsp), %rcx
imulq $0x300, %rcx, %rdx      # imm = 0x300
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x18(%rsp)
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x5200
movq 0x10(%rsp), %rax
movq 0x18(%rsp), %rcx
addq $0x300, %rax            # imm = 0x300
cmpq %rcx, %rax
movq %rax, 0x20(%rsp)
jne 0x2b5f
movq 0x38(%rsp), %rax
movq %rax, 0x40(%rsp)
jmp 0x2b94
movq 0x68(%rsp), %rax
movq 0x40(%rsp), %rcx
movq %rcx, 0x8(%rax)
cmpq $0x0, 0x8(%rax)
jne 0x2bdd
movq 0x7420(%rip), %rdi      # 0x9fd0
leaq 0x45ae(%rip), %rsi      # 0x7165
callq 0x2130
jmp 0x2bbe
leaq 0xd8(%rsp), %rdi
callq 0x2040
jmp 0x2bcd
movl $0x1, 0xc8(%rsp)
jmp 0x2df3
movq 0x68(%rsp), %rax
movl 0x4(%rax), %ecx
andl $0x3, %ecx
movl %ecx, 0xb0(%rsp)
movl (%rax), %eax
subl $0x1, %eax
movl %eax, 0xac(%rsp)
movq 0x68(%rsp), %rcx
movl 0xac(%rsp), %eax
cmpl (%rcx), %eax
jae 0x2dd9
movl 0xac(%rsp), %eax
shrl $0x3, %eax
movl %eax, 0xa8(%rsp)
movl 0xac(%rsp), %eax
andl $0x7, %eax
movl %eax, 0xa4(%rsp)
movl $0x0, 0xa0(%rsp)
movq 0x68(%rsp), %rcx
movl 0xa0(%rsp), %eax
cmpl 0x4(%rcx), %eax
jae 0x2d82
movq 0x68(%rsp), %rcx
movl 0xa0(%rsp), %eax
shrl $0x3, %eax
movl %eax, 0x9c(%rsp)
movl 0xa0(%rsp), %eax
andl $0x7, %eax
movl %eax, 0x98(%rsp)
movl 0xa8(%rsp), %eax
movl 0x14(%rcx), %ecx
imull %ecx, %eax
movl 0x9c(%rsp), %ecx
addl %ecx, %eax
movl %eax, 0x94(%rsp)
movl 0xa4(%rsp), %eax
movl 0x98(%rsp), %edx
movl %eax, %ecx
movl %edx, %eax
leal (%rax,%rcx,8), %eax
movl %eax, 0x90(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x2180
movl %eax, 0xc(%rsp)
jmp 0x2cc4
movl 0xc(%rsp), %edx
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rax
movl 0x94(%rsp), %ecx
leaq (%rcx,%rcx,2), %rcx
shlq $0x8, %rcx
addq %rcx, %rax
movl 0x90(%rsp), %ecx
movl %edx, 0x200(%rax,%rcx,4)
leaq 0xd8(%rsp), %rdi
callq 0x2180
movl %eax, 0x8(%rsp)
jmp 0x2d04
movl 0x8(%rsp), %edx
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rax
movl 0x94(%rsp), %ecx
leaq (%rcx,%rcx,2), %rcx
shlq $0x8, %rcx
addq %rcx, %rax
movl 0x90(%rsp), %ecx
movl %edx, 0x100(%rax,%rcx,4)
leaq 0xd8(%rsp), %rdi
callq 0x2180
movl %eax, 0x4(%rsp)
jmp 0x2d44
movl 0x4(%rsp), %edx
movq 0x68(%rsp), %rax
movq 0x8(%rax), %rax
movl 0x94(%rsp), %ecx
imulq $0x300, %rcx, %rcx      # imm = 0x300
addq %rcx, %rax
movl 0x90(%rsp), %ecx
movl %edx, (%rax,%rcx,4)
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x2c3c
movl $0x0, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
cmpl 0xb0(%rsp), %eax
jae 0x2dc1
leaq 0xd8(%rsp), %rdi
callq 0x2180
jmp 0x2dac
jmp 0x2dae
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8c(%rsp)
jmp 0x2d8d
jmp 0x2dc3
movl 0xac(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x2bfb
leaq 0xd8(%rsp), %rdi
callq 0x2040
jmp 0x2de8
movl $0x1, 0xc8(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x2050
movq 0x70(%rsp), %rax
addq $0x2e8, %rsp            # imm = 0x2E8
retq
movq 0xd0(%rsp), %rdi
callq 0x2230
nopw (%rax,%rax)