// File: /workspace/github_cpp_makefile_star2_O1/shirat74[P]resample/PNGImage.cc
// Function: PNGImage::save(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>) const
int
PNGImage::save (const std::string filename) const
{
  FILE       *fp;
  png_structp png_ptr;
  png_infop   png_info_ptr;
  png_byte    color_type = PNG_COLOR_TYPE_RGB;

  fp = fopen(filename.c_str(), FOPEN_WBIN_MODE);
  if(!fp)
    return -1;

  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL ||
      (png_info_ptr = png_create_info_struct(png_ptr)) == NULL) {
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
    return -1;
  }

#if PNG_LIBPNG_VER >= 10603
  // ignore possibly incorrect CMF bytes
  png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON);
#endif

  switch (getNComps()) {
  case 1:
    color_type = PNG_COLOR_TYPE_GRAY;
    break;
  case 2:
    color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
    break;
  case 3:
    color_type = PNG_COLOR_TYPE_RGB;
    break;
  case 4:
    color_type = PNG_COLOR_TYPE_RGB_ALPHA;
    break;
  }
  // Inititializing file IO.
  png_init_io(png_ptr, fp);
  // Write header (8 bit colour depth)
  png_set_IHDR(png_ptr, png_info_ptr, getWidth(), getHeight(),
               getBPC(), // BPC of original image data
               color_type,
               PNG_INTERLACE_NONE,
               PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

  // Write colorspace related information.
  switch (colorSpaceType) {
  case png_colorspace_gamma_only:
   png_set_gAMA(png_ptr, png_info_ptr, 1.0 / colorSpace.gamma);
   break;
  case png_colorspace_calibrated:
    if (colorSpace.hasGamma)
      png_set_gAMA(png_ptr, png_info_ptr, 1.0 / colorSpace.gamma);
    png_set_cHRM(png_ptr, png_info_ptr,
                 colorSpace.calRGB.xw, colorSpace.calRGB.yw,
                 colorSpace.calRGB.xr, colorSpace.calRGB.yr,
                 colorSpace.calRGB.xg, colorSpace.calRGB.yg,
                 colorSpace.calRGB.xb, colorSpace.calRGB.yb);
    break;
  case png_colorspace_srgb:
    png_set_sRGB(png_ptr, png_info_ptr, colorSpace.sRGB);
    break;
  case png_colorspace_iccp:
    if (colorSpace.ICCP.profile.size() > 0) {
      png_set_iCCP(png_ptr, png_info_ptr,
                   colorSpace.ICCP.name.c_str(),
                   PNG_COMPRESSION_TYPE_DEFAULT,
                   colorSpace.ICCP.profile.data(),
                   colorSpace.ICCP.profile.size());
    }
    break;
  default:
    assert(colorSpaceType == png_colorspace_device);
    break;
  }
  // Resolution convert ppi to pix-per-meter
  png_set_pHYs(png_ptr, png_info_ptr,
               (dpi_x * 10000 + 127) / 254, // add 127 to round to nearest int.
               (dpi_y * 10000 + 127) / 254,
               PNG_RESOLUTION_METER);

  png_write_info(png_ptr, png_info_ptr);

  // Write raster image body.
  png_bytep row = new png_byte[getWidth() * (getBPC() / 8) * getNComps()];
  if (getBPC() == 8) {
    for (int32_t j = 0; j < getHeight(); j++) {
      for (int32_t i = 0; i < getWidth(); i++) {
        Color pixel = getPixel(i, j);
        for (int c = 0; c < getNComps(); c++) {
          row[getNComps() * i + c] = 255 * ((float) pixel.v[c] / 65535.) + .5;
        }
      }
      png_write_row(png_ptr, row);
    }
  } else {
    for (int32_t j = 0; j < getHeight(); j++) {
      for (int32_t i = 0; i < getWidth(); i++) {
        Color   pixel = getPixel(i, j);
        int32_t pos   = 2 * getNComps() * i;
        for (int c = 0; c < getNComps(); c++) {
          uint16_t val = pixel.v[c];
          row[pos + 2 * c] = (val >> 8) & 0xff;
          row[pos + 2 * c + 1] =  val & 0xff;
        }
      }
      png_write_row(png_ptr, row);
    }
  }
  delete row;

  png_write_end(png_ptr, NULL);
  if (png_info_ptr)
    png_free_data(png_ptr, png_info_ptr, PNG_FREE_ALL, -1);
  if (png_ptr)
    png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
  fclose(fp);

  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rdi, %r14
movq (%rsi), %rdi
leaq 0x2e76(%rip), %rsi      # 0x60bf
callq 0x2330
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
testq %rax, %rax
je 0x3624
movq %rax, %rbx
leaq 0x2e51(%rip), %rdi      # 0x60b8
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x20e0
movq %rax, (%rsp)
testq %rax, %rax
je 0x3342
movq %rax, %rdi
callq 0x23f0
testq %rax, %rax
je 0x3342
movq %rax, %r15
movq (%rsp), %rdi
movl $0x2, %ebp
movl $0x2, %esi
movl $0x3, %edx
callq 0x23a0
movb 0x8(%r14), %al
decb %al
cmpb $0x3, %al
ja 0x32c2
movzbl %al, %eax
leaq 0x2e7d(%rip), %rcx      # 0x613c
movl (%rcx,%rax,4), %ebp
movq (%rsp), %rdi
movq %rbx, %rsi
callq 0x2470
movq (%rsp), %rdi
movl (%r14), %edx
movl 0x4(%r14), %ecx
movsbl 0x9(%r14), %r8d
subq $0x8, %rsp
xorl %eax, %eax
movq %r15, %rsi
movl %ebp, %r9d
pushq %rax
pushq %rax
pushq %rax
callq 0x23e0
addq $0x20, %rsp
movl 0x88(%r14), %eax
cmpq $0x4, %rax
ja 0x3636
leaq 0x2d96(%rip), %rcx      # 0x60a4
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x48(%r14), %r8
movq 0x50(%r14), %r9
cmpq %r8, %r9
je 0x3401
subl %r8d, %r9d
movq (%rsp), %rdi
movq 0x28(%r14), %rdx
movq %r15, %rsi
xorl %ecx, %ecx
callq 0x2220
jmp 0x3401
cmpq $0x0, (%rsp)
je 0x3624
movq %rsp, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21b0
jmp 0x3624
movq (%rsp), %rdi
cvtss2sd 0x60(%r14), %xmm1
movsd 0x2d18(%rip), %xmm0     # 0x6088
divsd %xmm1, %xmm0
movq %r15, %rsi
callq 0x2410
jmp 0x3401
movq (%rsp), %rdi
movsbl 0x20(%r14), %edx
movq %r15, %rsi
callq 0x2130
jmp 0x3401
cmpb $0x1, 0x84(%r14)
jne 0x33bc
movq (%rsp), %rdi
cvtss2sd 0x60(%r14), %xmm1
movsd 0x2cd8(%rip), %xmm0     # 0x6088
divsd %xmm1, %xmm0
movq %r15, %rsi
callq 0x2410
movq (%rsp), %rdi
xorps %xmm0, %xmm0
cvtss2sd 0x64(%r14), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0x68(%r14), %xmm1
cvtss2sd 0x6c(%r14), %xmm2
cvtss2sd 0x70(%r14), %xmm3
cvtss2sd 0x74(%r14), %xmm4
cvtss2sd 0x78(%r14), %xmm5
cvtss2sd 0x7c(%r14), %xmm6
cvtss2sd 0x80(%r14), %xmm7
movq %r15, %rsi
callq 0x2460
movq %rbx, 0x20(%rsp)
movq (%rsp), %rdi
movss 0x2c86(%rip), %xmm0     # 0x6098
movss 0x8c(%r14), %xmm1
mulss %xmm0, %xmm1
movss 0x2c75(%rip), %xmm2     # 0x609c
addss %xmm2, %xmm1
movss 0x2c6d(%rip), %xmm3     # 0x60a0
divss %xmm3, %xmm1
cvttss2si %xmm1, %rdx
mulss 0x90(%r14), %xmm0
addss %xmm2, %xmm0
divss %xmm3, %xmm0
cvttss2si %xmm0, %rcx
movq %r15, %rsi
movl $0x1, %r8d
callq 0x2450
movq (%rsp), %rdi
movq %r15, 0x18(%rsp)
movq %r15, %rsi
callq 0x21c0
movslq (%r14), %rax
movb 0x9(%r14), %bl
movl %ebx, %ecx
sarb $0x7, %cl
shrb $0x5, %cl
addb %bl, %cl
sarb $0x3, %cl
movsbq %cl, %rcx
movsbq 0x8(%r14), %rdi
imulq %rax, %rdi
imulq %rcx, %rdi
callq 0x2040
movq %rax, %r15
movl 0x4(%r14), %eax
cmpb $0x8, %bl
jne 0x3555
testl %eax, %eax
jle 0x35d6
xorl %r13d, %r13d
cmpl $0x0, (%r14)
jle 0x3537
xorl %ebp, %ebp
movq %r14, %rdi
movl %ebp, %esi
movl %r13d, %edx
callq 0x2a1e
movq %rax, 0x8(%rsp)
movw %dx, 0x10(%rsp)
shrl $0x10, %edx
movb %dl, 0x12(%rsp)
movsbl 0x8(%r14), %eax
testl %eax, %eax
movsd 0x2b25(%rip), %xmm1     # 0x6010
movsd 0x2b15(%rip), %xmm2     # 0x6008
movsd 0x2b95(%rip), %xmm3     # 0x6090
jle 0x3530
movslq %eax, %rcx
imull %ebp, %eax
addq %r15, %rax
xorl %edx, %edx
movzwl 0x8(%rsp,%rdx,2), %esi
xorps %xmm0, %xmm0
cvtsi2sd %esi, %xmm0
divsd %xmm1, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm3, %xmm0
cvttsd2si %xmm0, %esi
movb %sil, (%rax,%rdx)
incq %rdx
cmpq %rdx, %rcx
jne 0x3508
incl %ebp
cmpl (%r14), %ebp
jl 0x34be
movq (%rsp), %rdi
movq %r15, %rsi
callq 0x2150
incl %r13d
cmpl 0x4(%r14), %r13d
jl 0x34b6
jmp 0x35d6
testl %eax, %eax
jle 0x35d6
movq %r15, %r12
incq %r12
xorl %r13d, %r13d
cmpl $0x0, (%r14)
jle 0x35c1
xorl %ebx, %ebx
xorl %ebp, %ebp
movq %r14, %rdi
movl %ebp, %esi
movl %r13d, %edx
callq 0x2a1e
movq %rax, 0x8(%rsp)
movw %dx, 0x10(%rsp)
shrl $0x10, %edx
movb %dl, 0x12(%rsp)
movsbl 0x8(%r14), %ecx
testl %ecx, %ecx
jle 0x35b7
movslq %ecx, %rax
imull %ebx, %ecx
movslq %ecx, %rcx
addq %r12, %rcx
xorl %edx, %edx
movzwl 0x8(%rsp,%rdx,2), %esi
rolw $0x8, %si
movw %si, -0x1(%rcx,%rdx,2)
incq %rdx
cmpq %rdx, %rax
jne 0x35a1
incl %ebp
addl $0x2, %ebx
cmpl (%r14), %ebp
jl 0x356c
movq (%rsp), %rdi
movq %r15, %rsi
callq 0x2150
incl %r13d
cmpl 0x4(%r14), %r13d
jl 0x3562
movl $0x1, %esi
movq %r15, %rdi
callq 0x22d0
movq (%rsp), %rdi
xorl %r12d, %r12d
xorl %esi, %esi
callq 0x22e0
movq (%rsp), %rdi
movq 0x18(%rsp), %rsi
movl $0xffff, %edx           # imm = 0xFFFF
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
callq 0x2300
cmpq $0x0, (%rsp)
je 0x361a
movq %rsp, %rdi
xorl %esi, %esi
callq 0x2210
movq 0x20(%rsp), %rdi
callq 0x22b0
movl %r12d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x2a84(%rip), %rdi      # 0x60c1
leaq 0x2aa5(%rip), %rsi      # 0x60e9
leaq 0x2aaa(%rip), %rcx      # 0x60f5
movl $0xe4, %edx
callq 0x21d0
nop