// File: /workspace/github_cpp_makefile_star2_O2/rapirent[P]JPEG/encoder.c
// Function: main
int main(int argc, char* argv[])
{
    if (argc != 2  && argc != 3) {
        printf("[ERROR]:\nusage: ./encoder <input_file> [<output_file_name>]");
        exit(1);
    }


    FILE* fp;
    if (argc==3 && (fp = fopen(argv[2], "w")) == NULL) {
        printf("%s can't be opened\n", argv[2]);
        exit(1);
    } else if (argc==2 && (fp = fopen("image.jpg", "w")) == NULL) {
        printf("image.jpeg can't be opened\n");
        exit(1);
    }

    bitmap_image image(argv[1]);
    if (!image) {
        printf("%s can't be opened\n", argv[1]);
        exit(1);
    }

    image_height = image.height();
    image_width  = image.width();
    rgb_image = image;

    byte c;
    c = 0xff;
    fwrite(&c, 1, 1, fp);
    c = SOI;
    fwrite(&c, 1, 1, fp);
    c = 0xff;
    fwrite(&c, 1, 1, fp);
    c = APP0;
    fwrite(&c, 1, 1, fp);
    write_word_to_littleendian(fp, 16);
    char comment[5] = "JFIF";
    fwrite(comment, 1, 5, fp);
    c = 0x01;
    fwrite(&c, 1, 1, fp);
    c = 0x01;
    fwrite(&c, 1, 1, fp);
    c = 0x00;
    fwrite(&c, 1, 1, fp);
    c = 0x00;
    fwrite(&c, 1, 1, fp);
    c = 0x01;
    fwrite(&c, 1, 1, fp);
    c = 0x00;
    fwrite(&c, 1, 1, fp);
    c = 0x01;
    fwrite(&c, 1, 1, fp);
    c = 0x00;
    fwrite(&c, 1, 1, fp);
    c = 0x00;
    fwrite(&c, 1, 1, fp);

    c = 0xff;
    fwrite(&c, 1, 1, fp);
    c = DQT;
    fwrite(&c, 1, 1, fp);
    write_word_to_littleendian(fp, 132);
    c = 0x00;
    fwrite(&c, 1, 1, fp);
    for (int i = 0; i<8; i++) {
        for (int j = 0; j<8; j++) {
            zigzag_quantize_table[0][zigzag_index[i][j]] = quantize_table[0][i*8+j];
            zigzag_quantize_table[1][zigzag_index[i][j]] = quantize_table[1][i*8+j];
        }
    }
    for (int i = 0; i<8; i++) {
        for (int j = 0; j<8; j++) {
            fwrite(&(zigzag_quantize_table[0][i*8+j]),1,1,fp);
        }
    }
    c = 0x01;
    fwrite(&c, 1, 1, fp);
    for (int i = 0; i<8; i++) {
        for (int j = 0; j<8; j++) {
            fwrite(&(zigzag_quantize_table[1][i*8+j]),1,1,fp);
        }
    }
    c = 0xff;
    fwrite(&c, 1, 1, fp);
    c = SOF0;
    fwrite(&c, 1, 1, fp);
    write_word_to_littleendian(fp, 17);
    c = 8;
    fwrite(&c, 1, 1, fp);
    write_word_to_littleendian(fp,(word)image_height);
    write_word_to_littleendian(fp,(word)image_width);
    c = 3;
    fwrite(&c, 1, 1, fp);
    c = 1;
    fwrite(&c, 1, 1, fp);
    c = 0x11;
    fwrite(&c, 1, 1, fp);
    c = 0x00;
    fwrite(&c, 1, 1, fp);
    c = 2;
    fwrite(&c, 1, 1, fp);
    c = 0x11;
    fwrite(&c, 1, 1, fp);
    c = 1;
    fwrite(&c, 1, 1, fp);
    c = 3;
    fwrite(&c, 1, 1, fp);
    c = 0x11;
    fwrite(&c, 1, 1, fp);
    c = 1;
    fwrite(&c, 1, 1, fp);

    c = 0xff;
    fwrite(&c, 1, 1, fp);
    c = DHT;
    fwrite(&c, 1, 1, fp);
    write_word_to_littleendian(fp, 0x01a2);
    c = 0x00;
    fwrite(&c, 1, 1, fp);
    fwrite(dc_cof_code_length[0], 1, 16, fp);
    fwrite(dc_cof_value[0], 1, 12, fp);
    c = 0x01;
    fwrite(&c, 1, 1, fp);
    fwrite(dc_cof_code_length[1], 1, 16, fp);
    fwrite(dc_cof_value[1], 1, 12, fp);
    c = 0x10;
    fwrite(&c, 1, 1, fp);
    fwrite(ac_cof_code_length[0], 1, 16, fp);
    fwrite(ac_cof_value[0], 1, 162, fp);
    c = 0x11;
    fwrite(&c, 1, 1, fp);
    fwrite(ac_cof_code_length[1], 1, 16, fp);
    fwrite(ac_cof_value[1], 1, 162, fp);

    c = 0xff;
    fwrite(&c, 1, 1, fp);
    c = SOS;
    fwrite(&c, 1, 1, fp);
    write_word_to_littleendian(fp, 12);
    c = 3;
    fwrite(&c, 1, 1, fp);
    c = 1;
    fwrite(&c, 1, 1, fp);
    c = 0x00;
    fwrite(&c, 1, 1, fp);
    c = 2;
    fwrite(&c, 1, 1, fp);
    c = 0x11;
    fwrite(&c, 1, 1, fp);
    c = 3;
    fwrite(&c, 1, 1, fp);
    c = 0x11;
    fwrite(&c, 1, 1, fp);
    c = 0x00;
    fwrite(&c, 1, 1, fp);
    c = 0x3f;
    fwrite(&c, 1, 1, fp);
    c = 0x00;
    fwrite(&c, 1, 1, fp);

    init_cos_cache();
    for (int y = 0; y<image_height; y+=8) {
        for (int x = 0; x<image_width; x+=8) {
            calculate_mcu(fp,x,y);
        }
    }
    write_one_bit(fp,0,true);
    c = 0xff;
    fwrite(&c, 1, 1, fp);
    c = EOI;
    fwrite(&c, 1, 1, fp);
    fclose(fp);
    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
leal -0x4(%rdi), %eax
cmpl $-0x3, %eax
jbe 0x6174
movq %rsi, %r14
cmpl $0x3, %edi
jne 0x5c5f
movq 0x10(%r14), %rdi
leaq 0x1cc5(%rip), %rsi      # 0x7911
callq 0x5190
testq %rax, %rax
jne 0x5c7b
movq 0x10(%r14), %rsi
jmp 0x6188
leaq 0x1cc1(%rip), %rdi      # 0x7927
leaq 0x1ca4(%rip), %rsi      # 0x7911
callq 0x5190
testq %rax, %rax
je 0x6198
movq %rax, %rbx
movq 0x8(%r14), %rsi
leaq 0x8(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0x623a
leaq 0x28(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x6276
leaq 0x8(%rsp), %rdi
callq 0x50b0
movq 0x68(%rsp), %rax
cmpq 0x60(%rsp), %rax
je 0x6184
movl 0x48(%rsp), %eax
testl %eax, %eax
je 0x6184
movl 0x4c(%rsp), %ecx
testl %ecx, %ecx
je 0x6184
cmpl $0x0, 0x50(%rsp)
je 0x6184
movl %ecx, 0x5561(%rip)      # 0xb244
movl %eax, 0x555f(%rip)      # 0xb248
leaq 0x55e0(%rip), %rdi      # 0xb2d0
leaq 0x28(%rsp), %rsi
callq 0x62c8
pushq $-0x1
popq %rbp
movl %ebp, %edi
movq %rbx, %rsi
callq 0x51b0
pushq $-0x28
popq %rdi
movq %rbx, %rsi
callq 0x51b0
movl %ebp, %edi
movq %rbx, %rsi
callq 0x51b0
pushq $-0x20
popq %rdi
movq %rbx, %rsi
callq 0x51b0
pushq $0x10
popq %rsi
movq %rbx, %rdi
callq 0x5451
leaq 0x8(%rsp), %rdi
movb $0x0, 0x4(%rdi)
movl $0x4649464a, (%rdi)     # imm = 0x4649464A
pushq $0x1
popq %rsi
pushq $0x5
popq %rdx
movq %rbx, %rcx
callq 0x5290
pushq $0x1
popq %r14
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
xorl %r15d, %r15d
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
movl %ebp, %edi
movq %rbx, %rsi
callq 0x51b0
pushq $-0x25
popq %rdi
movq %rbx, %rsi
callq 0x51b0
movq %rbx, %rdi
movl $0x84, %esi
callq 0x5451
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
leaq 0x1dc9(%rip), %rax      # 0x7bb0
leaq 0x1e02(%rip), %rcx      # 0x7bf0
leaq 0x545b(%rip), %r14      # 0xb250
cmpq $0x8, %r15
je 0x5e2b
xorl %edx, %edx
cmpq $0x8, %rdx
je 0x5e1e
movslq (%rcx,%rdx,4), %rsi
movb -0x40(%rax,%rdx), %dil
movb (%rax,%rdx), %r8b
movb %dil, (%rsi,%r14)
movb %r8b, 0x40(%rsi,%r14)
incq %rdx
jmp 0x5dfd
incq %r15
addq $0x8, %rax
addq $0x20, %rcx
jmp 0x5df5
xorl %r15d, %r15d
cmpq $0x8, %r15
je 0x5e58
xorl %r12d, %r12d
cmpq $0x8, %r12
je 0x5e4f
movsbl (%r14,%r12), %edi
movq %rbx, %rsi
callq 0x51b0
incq %r12
jmp 0x5e37
incq %r15
addq $0x8, %r14
jmp 0x5e2e
pushq $0x1
popq %rdi
movq %rbx, %rsi
callq 0x51b0
leaq 0x5426(%rip), %r14      # 0xb290
xorl %r15d, %r15d
cmpq $0x8, %r15
je 0x5e97
xorl %r12d, %r12d
cmpq $0x8, %r12
je 0x5e8e
movsbl (%r14,%r12), %edi
movq %rbx, %rsi
callq 0x51b0
incq %r12
jmp 0x5e76
incq %r15
addq $0x8, %r14
jmp 0x5e6d
pushq $-0x1
popq %r15
movl %r15d, %edi
movq %rbx, %rsi
callq 0x51b0
pushq $-0x40
popq %rdi
movq %rbx, %rsi
callq 0x51b0
pushq $0x11
popq %r14
movq %rbx, %rdi
movl %r14d, %esi
callq 0x5451
pushq $0x8
popq %rdi
movq %rbx, %rsi
callq 0x51b0
movzwl 0x5372(%rip), %esi      # 0xb244
movq %rbx, %rdi
callq 0x5451
movzwl 0x5367(%rip), %esi      # 0xb248
movq %rbx, %rdi
callq 0x5451
pushq $0x3
popq %r12
movl %r12d, %edi
movq %rbx, %rsi
callq 0x51b0
pushq $0x1
popq %r13
movl %r13d, %edi
movq %rbx, %rsi
callq 0x51b0
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
xorl %ebp, %ebp
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
pushq $0x2
popq %rdi
movq %rbx, %rsi
callq 0x51b0
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
movl %r13d, %edi
movq %rbx, %rsi
callq 0x51b0
movl %r12d, %edi
movq %rbx, %rsi
callq 0x51b0
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
movl %r13d, %edi
movl %r13d, %r14d
movq %rbx, %rsi
callq 0x51b0
movl %r15d, %edi
movq %rbx, %rsi
callq 0x51b0
pushq $-0x3c
popq %rdi
movq %rbx, %rsi
callq 0x51b0
movq %rbx, %rdi
movl $0x1a2, %esi            # imm = 0x1A2
callq 0x5451
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
leaq 0x1d59(%rip), %rdi      # 0x7cf0
pushq $0x1
popq %r12
pushq $0x10
popq %r15
movq %r12, %rsi
movq %r15, %rdx
movq %rbx, %rcx
callq 0x5290
leaq 0x1d5c(%rip), %rdi      # 0x7d10
pushq $0xc
popq %r13
movq %r12, %rsi
movq %r13, %rdx
movq %rbx, %rcx
callq 0x5290
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
leaq 0x1d28(%rip), %rdi      # 0x7d00
movq %r12, %rsi
movq %r15, %rdx
movq %rbx, %rcx
callq 0x5290
leaq 0x1d2f(%rip), %rdi      # 0x7d1c
movq %r12, %rsi
movq %r13, %rdx
movq %rbx, %rcx
callq 0x5290
pushq $0x10
popq %rdi
movq %rbx, %rsi
callq 0x51b0
leaq 0x1d23(%rip), %rdi      # 0x7d30
movq %r12, %rsi
movq %r15, %rdx
movq %rbx, %rcx
callq 0x5290
leaq 0x1d2e(%rip), %rdi      # 0x7d50
movl $0xa2, %edx
movq %r12, %rsi
movq %rbx, %rcx
callq 0x5290
pushq $0x11
popq %r14
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
leaq 0x1cf8(%rip), %rdi      # 0x7d40
movq %r12, %rsi
movq %r15, %rdx
movq %rbx, %rcx
callq 0x5290
leaq 0x1d95(%rip), %rdi      # 0x7df2
movl $0xa2, %edx
movq %r12, %rsi
movq %rbx, %rcx
callq 0x5290
pushq $-0x1
popq %rdi
movq %rbx, %rsi
callq 0x51b0
pushq $-0x26
popq %rdi
movq %rbx, %rsi
callq 0x51b0
pushq $0xc
popq %rsi
movq %rbx, %rdi
callq 0x5451
pushq $0x3
popq %r15
movl %r15d, %edi
movq %rbx, %rsi
callq 0x51b0
pushq $0x1
popq %rdi
movq %rbx, %rsi
callq 0x51b0
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
pushq $0x2
popq %rdi
movq %rbx, %rsi
callq 0x51b0
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
movl %r15d, %edi
movq %rbx, %rsi
callq 0x51b0
movl %r14d, %edi
movq %rbx, %rsi
callq 0x51b0
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
pushq $0x3f
popq %rdi
movq %rbx, %rsi
callq 0x51b0
xorl %edi, %edi
movq %rbx, %rsi
callq 0x51b0
callq 0x546e
cmpl 0x513c(%rip), %ebp      # 0xb244
jge 0x612e
xorl %r14d, %r14d
cmpl 0x5134(%rip), %r14d     # 0xb248
jge 0x6129
movq %rbx, %rdi
movl %r14d, %esi
movl %ebp, %edx
callq 0x5a2e
addl $0x8, %r14d
jmp 0x610d
addl $0x8, %ebp
jmp 0x6102
pushq $0x1
popq %rdx
movq %rbx, %rdi
xorl %esi, %esi
callq 0x54c8
pushq $-0x1
popq %rdi
movq %rbx, %rsi
callq 0x51b0
pushq $-0x27
popq %rdi
movq %rbx, %rsi
callq 0x51b0
movq %rbx, %rdi
callq 0x5160
leaq 0x28(%rsp), %rdi
callq 0x6216
xorl %eax, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x175a(%rip), %rdi      # 0x78d5
xorl %eax, %eax
callq 0x5030
jmp 0x61a4
movq 0x8(%r14), %rsi
leaq 0x1784(%rip), %rdi      # 0x7913
xorl %eax, %eax
callq 0x5030
jmp 0x61a4
leaq 0x19b5(%rip), %rdi      # 0x7b54
callq 0x5210
pushq $0x1
popq %rdi
callq 0x51a0
jmp 0x61c2
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x50b0
jmp 0x61cf
movq %rax, %rbx
jmp 0x61cf
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x6216
movq %rbx, %rdi
callq 0x5250
nop