// File: /workspace/github_cpp_makefile_star2_O3/misohena[P]drawstars/./image_jpeg.h
// Function: bool writeJpegFile<Image<ColorRGB<double>>>(char const*, Image<ColorRGB<double>> const&, int)
bool writeJpegFile(const char *filename, const ImageT &image, int quality)
{
    File file(filename, "wb");
    if(!file){
        return false;
    }

    ///@todo handle errors

    jpeg_compress_struct cinfo;
    jpeg_error_mgr jerr;

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);

    jpeg_stdio_dest(&cinfo, file);

    cinfo.image_width = image.width();
    cinfo.image_height = image.height();
    cinfo.input_components = 3; // number of components per pixel.
    cinfo.in_color_space = JCS_RGB;
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, quality, TRUE);


    jpeg_start_compress(&cinfo, TRUE);

    std::unique_ptr<unsigned char[]> lineBytes(new unsigned char[image.width() * 3]);

    while(cinfo.next_scanline < cinfo.image_height){
        // copy scanline bytes
        unsigned char *dst = lineBytes.get();
        const typename ImageT::PixelType *src = image.at(0, cinfo.next_scanline);
        for(unsigned int x = 0; x < image.width(); ++x, ++src, dst += 3){
            using VT = typename ImageT::PixelType::ValueType;
            dst[0] = static_cast<std::uint8_t>(clamp(255*src->r, VT(0), VT(255)));
            dst[1] = static_cast<std::uint8_t>(clamp(255*src->g, VT(0), VT(255)));
            dst[2] = static_cast<std::uint8_t>(clamp(255*src->b, VT(0), VT(255)));
        }

        // write
        JSAMPROW row_pointer[1] = {lineBytes.get()};
        jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    jpeg_finish_compress(&cinfo);

    jpeg_destroy_compress(&cinfo);

    return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2f8, %rsp            # imm = 0x2F8
movl %edx, %ebp
movq %rsi, %r14
leaq 0x3e3f(%rip), %rsi      # 0xd548
callq 0x4350
movq %rax, %rbx
testq %rax, %rax
je 0x98a0
leaq 0x250(%rsp), %rdi
callq 0x4070
leaq 0x8(%rsp), %rdi
movq %rax, (%rdi)
movl $0x248, %edx            # imm = 0x248
movl $0x50, %esi
callq 0x4060
leaq 0x8(%rsp), %rdi
movq %rbx, %rsi
callq 0x44e0
movq (%r14), %rax
leaq 0x8(%rsp), %rdi
movq %rax, 0x30(%rdi)
movabsq $0x200000003, %rax      # imm = 0x200000003
movq %rax, 0x38(%rdi)
callq 0x4440
leaq 0x8(%rsp), %rdi
movl %ebp, %esi
movl $0x1, %edx
callq 0x40d0
leaq 0x8(%rsp), %rdi
movl $0x1, %esi
callq 0x4450
movl (%r14), %eax
leal (%rax,%rax,2), %edi
callq 0x4030
movq %rax, %r15
movl 0x15c(%rsp), %ecx
cmpl 0x3c(%rsp), %ecx
jae 0x987c
leaq 0x8(%rsp), %r12
movq %rsp, %r13
movsd 0x38af(%rip), %xmm2     # 0xd068
xorpd %xmm3, %xmm3
movl (%r14), %eax
testl %eax, %eax
je 0x984b
imull %eax, %ecx
leaq (%rcx,%rcx,2), %rcx
shlq $0x3, %rcx
addq 0x8(%r14), %rcx
xorl %edx, %edx
movsd (%rcx,%rdx,8), %xmm0
mulsd %xmm2, %xmm0
movapd %xmm2, %xmm1
minsd %xmm0, %xmm1
cmpltsd %xmm3, %xmm0
andnpd %xmm1, %xmm0
cvttsd2si %xmm0, %esi
movb %sil, (%r15,%rdx)
movsd 0x8(%rcx,%rdx,8), %xmm0
mulsd %xmm2, %xmm0
movapd %xmm2, %xmm1
minsd %xmm0, %xmm1
cmpltsd %xmm3, %xmm0
andnpd %xmm1, %xmm0
cvttsd2si %xmm0, %esi
movb %sil, 0x1(%r15,%rdx)
movsd 0x10(%rcx,%rdx,8), %xmm0
mulsd %xmm2, %xmm0
movapd %xmm2, %xmm1
minsd %xmm0, %xmm1
cmpltsd %xmm3, %xmm0
andnpd %xmm1, %xmm0
cvttsd2si %xmm0, %esi
movb %sil, 0x2(%r15,%rdx)
addq $0x3, %rdx
decl %eax
jne 0x97d9
movq %r15, (%rsp)
movq %r12, %rdi
movq %r13, %rsi
movl $0x1, %edx
callq 0x4340
movl 0x15c(%rsp), %ecx
cmpl 0x3c(%rsp), %ecx
movsd 0x37f6(%rip), %xmm2     # 0xd068
xorpd %xmm3, %xmm3
jb 0x97bd
leaq 0x8(%rsp), %rdi
callq 0x4320
leaq 0x8(%rsp), %rdi
callq 0x43a0
movq %r15, %rdi
callq 0x4370
movq %rbx, %rdi
callq 0x42c0
testq %rbx, %rbx
setne %al
addq $0x2f8, %rsp            # imm = 0x2F8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x98bc
jmp 0x98c1
movq %rax, %r14
jmp 0x98cc
movq %rax, %r14
movq %r15, %rdi
callq 0x4370
movq %rbx, %rdi
callq 0x42c0
movq %r14, %rdi
callq 0x4510