// File: /workspace/github_cpp_makefile_star2_O1/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 %r12
pushq %rbx
subq $0x80, %rsp
movl %edi, %r15d
leal -0x4(%r15), %eax
cmpl $-0x3, %eax
jbe 0x6503
movq %rsi, %r14
cmpl $0x3, %r15d
jne 0x5e7b
movq 0x10(%r14), %rdi
leaq 0x2a9f(%rip), %rsi      # 0x8909
callq 0x5170
movq %rax, %rbx
testq %rax, %rax
je 0x6519
cmpl $0x2, %r15d
jne 0x5ea0
leaq 0x2a97(%rip), %rdi      # 0x891f
leaq 0x2a7a(%rip), %rsi      # 0x8909
callq 0x5170
movq %rax, %rbx
testq %rax, %rax
je 0x652d
movq 0x8(%r14), %rsi
leaq 0x10(%rsp), %rdi
leaq 0xe(%rsp), %rdx
callq 0x65b2
leaq 0x30(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x65f0
leaq 0x20(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x5edd
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x5150
movq 0x70(%rsp), %rax
cmpq 0x68(%rsp), %rax
je 0x6513
movl 0x50(%rsp), %eax
testl %eax, %eax
je 0x6513
movl 0x54(%rsp), %ecx
testl %ecx, %ecx
je 0x6513
cmpl $0x0, 0x58(%rsp)
je 0x6513
movl %ecx, 0x630e(%rip)      # 0xc224
movl %eax, 0x630c(%rip)      # 0xc228
leaq 0x638d(%rip), %rdi      # 0xc2b0
leaq 0x30(%rsp), %rsi
callq 0x6674
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
movq %rbx, %rsi
callq 0x5190
movl $0xffffffd8, %edi       # imm = 0xFFFFFFD8
movq %rbx, %rsi
callq 0x5190
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
movq %rbx, %rsi
callq 0x5190
movl $0xffffffe0, %edi       # imm = 0xFFFFFFE0
movq %rbx, %rsi
callq 0x5190
leaq 0x10(%rsp), %r14
movw $0x1000, (%r14)         # imm = 0x1000
movl $0x1, %esi
movl $0x2, %edx
movq %r14, %rdi
movq %rbx, %rcx
callq 0x5250
movb $0x0, 0x4(%r14)
movl $0x4649464a, (%r14)     # imm = 0x4649464A
leaq 0x10(%rsp), %rdi
movl $0x1, %esi
movl $0x5, %edx
movq %rbx, %rcx
callq 0x5250
movl $0x1, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x1, %edi
movq %rbx, %rsi
callq 0x5190
xorl %r14d, %r14d
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x1, %edi
movq %rbx, %rsi
callq 0x5190
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x1, %edi
movq %rbx, %rsi
callq 0x5190
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
movq %rbx, %rsi
callq 0x5190
movl $0xffffffdb, %edi       # imm = 0xFFFFFFDB
movq %rbx, %rsi
callq 0x5190
leaq 0xe(%rsp), %rdi
movw $0x8400, (%rdi)         # imm = 0x8400
movl $0x1, %esi
movl $0x2, %edx
movq %rbx, %rcx
callq 0x5250
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
leaq 0x2b9c(%rip), %rax      # 0x8bf0
leaq 0x2b55(%rip), %rcx      # 0x8bb0
leaq 0x61ce(%rip), %r15      # 0xc230
xorl %edx, %edx
movslq (%rax,%rdx,4), %rsi
movb -0x40(%rcx,%rdx), %dil
movb (%rcx,%rdx), %r8b
movb %dil, (%rsi,%r15)
movb %r8b, 0x40(%rsi,%r15)
incq %rdx
cmpq $0x8, %rdx
jne 0x6064
incq %r14
addq $0x20, %rax
addq $0x8, %rcx
cmpq $0x8, %r14
jne 0x6062
xorl %r14d, %r14d
xorl %r12d, %r12d
movsbl (%r15,%r12), %edi
movq %rbx, %rsi
callq 0x5190
incq %r12
cmpq $0x8, %r12
jne 0x609a
incq %r14
addq $0x8, %r15
cmpq $0x8, %r14
jne 0x6097
movl $0x1, %edi
movq %rbx, %rsi
callq 0x5190
leaq 0x619f(%rip), %r14      # 0xc270
xorl %r15d, %r15d
xorl %r12d, %r12d
movsbl (%r14,%r12), %edi
movq %rbx, %rsi
callq 0x5190
incq %r12
cmpq $0x8, %r12
jne 0x60d7
incq %r15
addq $0x8, %r14
cmpq $0x8, %r15
jne 0x60d4
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
movq %rbx, %rsi
callq 0x5190
movl $0xffffffc0, %edi       # imm = 0xFFFFFFC0
movq %rbx, %rsi
callq 0x5190
leaq 0xe(%rsp), %r14
movw $0x1100, (%r14)         # imm = 0x1100
movl $0x1, %esi
movl $0x2, %edx
movq %r14, %rdi
movq %rbx, %rcx
callq 0x5250
movl $0x8, %edi
movq %rbx, %rsi
callq 0x5190
movzwl 0x60dc(%rip), %eax      # 0xc224
rolw $0x8, %ax
movw %ax, (%r14)
leaq 0xe(%rsp), %r14
movl $0x1, %esi
movl $0x2, %edx
movq %r14, %rdi
movq %rbx, %rcx
callq 0x5250
movzwl 0x60b7(%rip), %eax      # 0xc228
rolw $0x8, %ax
movw %ax, (%r14)
leaq 0xe(%rsp), %r14
movl $0x1, %esi
movl $0x2, %edx
movq %r14, %rdi
movq %rbx, %rcx
callq 0x5250
movl $0x3, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x1, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x11, %edi
movq %rbx, %rsi
callq 0x5190
xorl %r15d, %r15d
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x2, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x11, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x1, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x3, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x11, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x1, %edi
movq %rbx, %rsi
callq 0x5190
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
movq %rbx, %rsi
callq 0x5190
movl $0xffffffc4, %edi       # imm = 0xFFFFFFC4
movq %rbx, %rsi
callq 0x5190
movw $0xa201, (%r14)         # imm = 0xA201
leaq 0xe(%rsp), %r14
movl $0x1, %esi
movl $0x2, %edx
movq %r14, %rdi
movq %rbx, %rcx
callq 0x5250
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
leaq 0x2a90(%rip), %rdi      # 0x8cf0
movl $0x1, %esi
movl $0x10, %edx
movq %rbx, %rcx
callq 0x5250
leaq 0x2a97(%rip), %rdi      # 0x8d10
movl $0x1, %esi
movl $0xc, %edx
movq %rbx, %rcx
callq 0x5250
movl $0x1, %edi
movq %rbx, %rsi
callq 0x5190
leaq 0x2a61(%rip), %rdi      # 0x8d00
movl $0x1, %esi
movl $0x10, %edx
movq %rbx, %rcx
callq 0x5250
leaq 0x2a64(%rip), %rdi      # 0x8d1c
movl $0x1, %esi
movl $0xc, %edx
movq %rbx, %rcx
callq 0x5250
movl $0x10, %edi
movq %rbx, %rsi
callq 0x5190
leaq 0x2a52(%rip), %rdi      # 0x8d30
movl $0x1, %esi
movl $0x10, %edx
movq %rbx, %rcx
callq 0x5250
leaq 0x2a59(%rip), %rdi      # 0x8d50
movl $0x1, %esi
movl $0xa2, %edx
movq %rbx, %rcx
callq 0x5250
movl $0x11, %edi
movq %rbx, %rsi
callq 0x5190
leaq 0x2a23(%rip), %rdi      # 0x8d40
movl $0x1, %esi
movl $0x10, %edx
movq %rbx, %rcx
callq 0x5250
leaq 0x2abc(%rip), %rdi      # 0x8df2
movl $0x1, %esi
movl $0xa2, %edx
movq %rbx, %rcx
callq 0x5250
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
movq %rbx, %rsi
callq 0x5190
movl $0xffffffda, %edi       # imm = 0xFFFFFFDA
movq %rbx, %rsi
callq 0x5190
movw $0xc00, (%r14)          # imm = 0xC00
leaq 0xe(%rsp), %rdi
movl $0x1, %esi
movl $0x2, %edx
movq %rbx, %rcx
callq 0x5250
movl $0x3, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x1, %edi
movq %rbx, %rsi
callq 0x5190
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x2, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x11, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x3, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x11, %edi
movq %rbx, %rsi
callq 0x5190
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
movl $0x3f, %edi
movq %rbx, %rsi
callq 0x5190
xorl %edi, %edi
movq %rbx, %rsi
callq 0x5190
leaq 0x5f01(%rip), %r14      # 0xc300
xorps %xmm0, %xmm0
cvtsi2sd %r15d, %xmm0
mulsd 0x1bf9(%rip), %xmm0     # 0x8008
mulsd 0x1bf9(%rip), %xmm0     # 0x8010
callq 0x5240
movsd %xmm0, (%r14)
incq %r15
addq $0x8, %r14
cmpq $0xc8, %r15
jne 0x63ff
cmpl $0x0, 0x5dec(%rip)      # 0xc224
jle 0x646d
xorl %ebp, %ebp
cmpl $0x0, 0x5de5(%rip)      # 0xc228
jle 0x6462
xorl %r14d, %r14d
movq %rbx, %rdi
movl %r14d, %esi
movl %ebp, %edx
callq 0x5b87
addl $0x8, %r14d
cmpl 0x5dc8(%rip), %r14d     # 0xc228
jl 0x6448
addl $0x8, %ebp
cmpl 0x5db9(%rip), %ebp      # 0xc224
jl 0x643c
movzbl 0x64cd(%rip), %eax      # 0xc941
cmpl $0x6, %eax
ja 0x648e
movb 0x64c1(%rip), %cl       # 0xc940
addl $-0x7, %eax
addb %cl, %cl
incl %eax
jne 0x6482
movb %cl, 0x64b2(%rip)       # 0xc940
movsbl 0x64ab(%rip), %edi      # 0xc940
movq %rbx, %rsi
callq 0x5190
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
movq %rbx, %rsi
callq 0x5190
movl $0xffffffd9, %edi       # imm = 0xFFFFFFD9
movq %rbx, %rsi
callq 0x5190
movq %rbx, %rdi
callq 0x5130
movq 0x68(%rsp), %rdi
testq %rdi, %rdi
je 0x64d6
movq 0x78(%rsp), %rsi
subq %rdi, %rsi
callq 0x5150
leaq 0x40(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x64f1
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x5150
xorl %eax, %eax
addq $0x80, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x23c3(%rip), %rdi      # 0x88cd
xorl %eax, %eax
callq 0x5040
jmp 0x6539
movq 0x8(%r14), %rsi
jmp 0x651d
movq 0x10(%r14), %rsi
leaq 0x23e7(%rip), %rdi      # 0x890b
xorl %eax, %eax
callq 0x5040
jmp 0x6539
leaq 0x2618(%rip), %rdi      # 0x8b4c
callq 0x51e0
movl $0x1, %edi
callq 0x5180
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
callq 0x657e
jmp 0x6575
movq %rax, %rbx
leaq 0x20(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x6575
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x5150
jmp 0x6575
movq %rax, %rbx
movq %rbx, %rdi
callq 0x5210
nop