// File: /workspace/github_cpp_makefile_star2_O2/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 $0x38, %rsp
movq %rdi, %r14
movq (%rsi), %rdi
leaq 0x3006(%rip), %rsi      # 0x604f
callq 0x2320
pushq $-0x1
popq %r13
testq %rax, %rax
je 0x3409
movq %rax, %rbx
leaq 0x2fe3(%rip), %rdi      # 0x6048
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x20e0
movq %rax, 0x20(%rsp)
testq %rax, %rax
je 0x3409
movq %rax, %r15
movq %rax, %rdi
callq 0x2410
movq %rax, 0x8(%rsp)
testq %rax, %rax
je 0x3140
pushq $0x2
popq %rbp
pushq $0x3
popq %rdx
movq %r15, %rdi
movl %ebp, %esi
callq 0x23a0
movb 0x8(%r14), %al
decb %al
cmpb $0x3, %al
ja 0x30be
movzbl %al, %eax
leaq 0x303d(%rip), %rcx      # 0x60f8
movl (%rcx,%rax,4), %ebp
movq %r15, %rdi
movq %rbx, %rsi
callq 0x2490
movl (%r14), %edx
movl 0x4(%r14), %ecx
movsbl 0x9(%r14), %r8d
subq $0x8, %rsp
movq %r15, %rdi
movq 0x10(%rsp), %rsi
movl %ebp, %r9d
pushq $0x0
pushq $0x0
pushq $0x0
callq 0x2400
addq $0x20, %rsp
movl 0x88(%r14), %eax
cmpq $0x4, %rax
ja 0x341b
leaq 0x2f29(%rip), %rcx      # 0x6034
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x48(%r14), %r8
movq 0x50(%r14), %r9
cmpq %r8, %r9
je 0x31f1
subl %r8d, %r9d
movq 0x28(%r14), %rdx
movq %r15, %rdi
movq 0x8(%rsp), %rsi
xorl %ecx, %ecx
callq 0x2230
jmp 0x31f1
leaq 0x20(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x21d0
jmp 0x3409
cvtss2sd 0x60(%r14), %xmm1
movsd 0x2eb7(%rip), %xmm0     # 0x6018
divsd %xmm1, %xmm0
movq %r15, %rdi
movq 0x8(%rsp), %rsi
callq 0x2430
jmp 0x31f1
movsbl 0x20(%r14), %edx
movq %r15, %rdi
movq 0x8(%rsp), %rsi
callq 0x2150
jmp 0x31f1
cmpb $0x1, 0x84(%r14)
jne 0x31b1
cvtss2sd 0x60(%r14), %xmm1
movsd 0x2e78(%rip), %xmm0     # 0x6018
divsd %xmm1, %xmm0
movq %r15, %rdi
movq 0x8(%rsp), %rsi
callq 0x2430
cvtss2sd 0x64(%r14), %xmm0
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, %rdi
movq 0x8(%rsp), %rsi
callq 0x2480
movq %rbx, 0x28(%rsp)
movss 0x2e2a(%rip), %xmm0     # 0x6028
movss 0x8c(%r14), %xmm1
mulss %xmm0, %xmm1
movss 0x2e19(%rip), %xmm2     # 0x602c
addss %xmm2, %xmm1
movss 0x2e11(%rip), %xmm3     # 0x6030
divss %xmm3, %xmm1
cvttss2si %xmm1, %rdx
mulss 0x90(%r14), %xmm0
addss %xmm2, %xmm0
divss %xmm3, %xmm0
cvttss2si %xmm0, %rcx
pushq $0x1
popq %r8
movq %r15, %rdi
movq 0x8(%rsp), %rbx
movq %rbx, %rsi
callq 0x2470
movq %r15, %rdi
movq %rbx, %rsi
callq 0x21e0
movslq (%r14), %rcx
movb 0x9(%r14), %al
movsbl %al, %ebp
movb $0x8, %dl
movl %ebp, %eax
idivb %dl
movsbq %al, %rax
movsbq 0x8(%r14), %rdi
imulq %rcx, %rdi
imulq %rax, %rdi
callq 0x2040
movq %rax, %rbx
cmpb $0x8, %bpl
jne 0x333a
xorl %ebp, %ebp
cmpl 0x4(%r14), %ebp
jge 0x33c6
xorl %r12d, %r12d
cmpl (%r14), %r12d
jge 0x3328
movq %r14, %rdi
movl %r12d, %esi
movl %ebp, %edx
callq 0x2900
movq %rax, 0x10(%rsp)
movw %dx, 0x18(%rsp)
shrl $0x10, %edx
movb %dl, 0x1a(%rsp)
movsbl 0x8(%r14), %ecx
testl %ecx, %ecx
movl $0x0, %eax
cmovgl %ecx, %eax
imull %r12d, %ecx
movslq %ecx, %rcx
addq %rbx, %rcx
xorl %edx, %edx
movsd 0x2d27(%rip), %xmm1     # 0x6010
movsd 0x2d17(%rip), %xmm2     # 0x6008
movsd 0x2d27(%rip), %xmm3     # 0x6020
cmpq %rdx, %rax
je 0x3320
movzwl 0x10(%rsp,%rdx,2), %esi
cvtsi2sd %esi, %xmm0
divsd %xmm1, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm3, %xmm0
cvttsd2si %xmm0, %esi
movb %sil, (%rcx,%rdx)
incq %rdx
jmp 0x32f9
incl %r12d
jmp 0x329f
movq %r15, %rdi
movq %rbx, %rsi
callq 0x2170
incl %ebp
jmp 0x3292
movq %rbx, %r13
incq %r13
xorl %ebp, %ebp
movq %r15, 0x30(%rsp)
cmpl 0x4(%r14), %ebp
jge 0x33c6
xorl %r15d, %r15d
xorl %r12d, %r12d
cmpl (%r14), %r12d
jge 0x33b2
movq %r14, %rdi
movl %r12d, %esi
movl %ebp, %edx
callq 0x2900
movq %rax, 0x10(%rsp)
movw %dx, 0x18(%rsp)
shrl $0x10, %edx
movb %dl, 0x1a(%rsp)
movsbl 0x8(%r14), %ecx
testl %ecx, %ecx
movl $0x0, %eax
cmovgl %ecx, %eax
imull %r15d, %ecx
movslq %ecx, %rcx
addq %r13, %rcx
xorl %edx, %edx
cmpq %rdx, %rax
je 0x33a9
movzwl 0x10(%rsp,%rdx,2), %esi
rolw $0x8, %si
movw %si, -0x1(%rcx,%rdx,2)
incq %rdx
jmp 0x3391
incl %r12d
addl $0x2, %r15d
jmp 0x3353
movq 0x30(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
callq 0x2170
incl %ebp
jmp 0x3347
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x22e0
xorl %r13d, %r13d
movq %r15, %rdi
xorl %esi, %esi
callq 0x22f0
pushq $-0x1
popq %rcx
movq %r15, %rdi
movq 0x8(%rsp), %rsi
movl $0xffff, %edx           # imm = 0xFFFF
callq 0x2300
leaq 0x20(%rsp), %rdi
xorl %esi, %esi
callq 0x2220
movq 0x28(%rsp), %rdi
callq 0x22c0
movl %r13d, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x2c2f(%rip), %rdi      # 0x6051
leaq 0x2c50(%rip), %rsi      # 0x6079
leaq 0x2c55(%rip), %rcx      # 0x6085
movl $0xe4, %edx
callq 0x21f0