// File: dannye[P]jed/src/encoder.cpp
// Function: encodeHuffmanData(BMPImage const&)
std::vector<byte> encodeHuffmanData(const BMPImage& image) {
    std::vector<byte> huffmanData;
    BitWriter bitWriter(huffmanData);

    int previousDCs[3] = { 0 };

    for (uint i = 0; i < 3; ++i) {
        if (!dcTables[i]->set) {
            generateCodes(*dcTables[i]);
            dcTables[i]->set = true;
        }
        if (!acTables[i]->set) {
            generateCodes(*acTables[i]);
            acTables[i]->set = true;
        }
    }

    for (uint y = 0; y < image.blockHeight; ++y) {
        for (uint x = 0; x < image.blockWidth; ++x) {
            for (uint i = 0; i < 3; ++i) {
                if (!encodeBlockComponent(
                        bitWriter,
                        image.blocks[y * image.blockWidth + x][i],
                        previousDCs[i],
                        *dcTables[i],
                        *acTables[i])) {
                    return std::vector<byte>();
                }
            }
        }
    }

    return huffmanData;
}

// Assembly:
subq $0x98, %rsp
movq %rdi, 0x18(%rsp)
movq %rdi, %rax
movq %rax, 0x20(%rsp)
movq %rdi, 0x90(%rsp)
movq %rsi, 0x88(%rsp)
leaq 0x70(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x53d0
movq 0x28(%rsp), %rsi
leaq 0x60(%rsp), %rdi
callq 0x53e0
jmp 0x4504
leaq 0x48(%rsp), %rdi
xorl %esi, %esi
movl $0xc, %edx
callq 0x20b0
movl $0x0, 0x44(%rsp)
cmpl $0x3, 0x44(%rsp)
jae 0x45e9
movl 0x44(%rsp), %eax
movl %eax, %ecx
leaq 0x583b(%rip), %rax      # 0x9d70
movq (%rax,%rcx,8), %rax
testb $0x1, 0x384(%rax)
jne 0x458f
movl 0x44(%rsp), %eax
movl %eax, %ecx
leaq 0x5821(%rip), %rax      # 0x9d70
movq (%rax,%rcx,8), %rdi
callq 0x4000
movl 0x44(%rsp), %eax
movl %eax, %ecx
leaq 0x580b(%rip), %rax      # 0x9d70
movq (%rax,%rcx,8), %rax
movb $0x1, 0x384(%rax)
jmp 0x458f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x58(%rsp)
movl %eax, 0x54(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x5430
jmp 0x4736
movl 0x44(%rsp), %eax
movl %eax, %ecx
leaq 0x57f4(%rip), %rax      # 0x9d90
movq (%rax,%rcx,8), %rax
testb $0x1, 0x384(%rax)
jne 0x45d7
movl 0x44(%rsp), %eax
movl %eax, %ecx
leaq 0x57da(%rip), %rax      # 0x9d90
movq (%rax,%rcx,8), %rdi
callq 0x4000
movl 0x44(%rsp), %eax
movl %eax, %ecx
leaq 0x57c4(%rip), %rax      # 0x9d90
movq (%rax,%rcx,8), %rax
movb $0x1, 0x384(%rax)
jmp 0x45d9
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x451d
movl $0x0, 0x40(%rsp)
movl 0x40(%rsp), %eax
movq 0x88(%rsp), %rcx
cmpl 0x10(%rcx), %eax
jae 0x4708
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
movq 0x88(%rsp), %rcx
cmpl 0x14(%rcx), %eax
jae 0x46f6
movl $0x0, 0x38(%rsp)
cmpl $0x3, 0x38(%rsp)
jae 0x46e4
movq 0x88(%rsp), %rcx
movq 0x8(%rcx), %rdi
movl 0x40(%rsp), %eax
movl 0x14(%rcx), %ecx
imull %ecx, %eax
movl 0x3c(%rsp), %ecx
addl %ecx, %eax
leaq (%rax,%rax,2), %rax
shlq $0x8, %rax
addq %rax, %rdi
movl 0x38(%rsp), %esi
callq 0x52f0
movq %rax, 0x10(%rsp)
jmp 0x466d
movq 0x10(%rsp), %rsi
movl 0x38(%rsp), %eax
movl %eax, %edi
leaq 0x48(%rsp,%rdi,4), %rdx
leaq 0x56ec(%rip), %rax      # 0x9d70
movq (%rax,%rdi,8), %rcx
leaq 0x5701(%rip), %rax      # 0x9d90
movq (%rax,%rdi,8), %r8
leaq 0x60(%rsp), %rdi
callq 0x4190
movb %al, 0xf(%rsp)
jmp 0x46a3
movb 0xf(%rsp), %al
testb $0x1, %al
jne 0x46d2
jmp 0x46ad
movq 0x18(%rsp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x20b0
movq 0x18(%rsp), %rdi
callq 0x53d0
movl $0x1, 0x34(%rsp)
jmp 0x471f
jmp 0x46d4
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0x462b
jmp 0x46e6
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x460e
jmp 0x46f8
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
jmp 0x45f1
movq 0x18(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x5400
movl $0x1, 0x34(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x5430
movq 0x20(%rsp), %rax
addq $0x98, %rsp
retq
movq 0x58(%rsp), %rdi
callq 0x2230