// File: shirat74[P]resample/PNGImage.cc
// Function: PNGImage::PNGImage(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
PNGImage::PNGImage (const std::string filename) : Image(0, 0, 0, 0) // dummy
{
  FILE       *fp;
  png_structp png_ptr;
  png_infop   png_info_ptr;
  png_byte    color_type, bpc, nComps;
  png_uint_32 width, height, rowbytes;

  fp = fopen(filename.c_str(), FOPEN_RBIN_MODE);
  if(!fp) {
    isValid = false;
    return;
  }

  png_ptr = png_create_read_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);
    isValid = false;
    return;
  }

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

  // Inititializing file IO.
  png_init_io(png_ptr, fp);

  // Read PNG info-header and get some info.
  png_read_info(png_ptr, png_info_ptr);
  color_type = png_get_color_type  (png_ptr, png_info_ptr);
  width      = png_get_image_width (png_ptr, png_info_ptr);
  height     = png_get_image_height(png_ptr, png_info_ptr);
  bpc        = png_get_bit_depth   (png_ptr, png_info_ptr);
  nComps     = png_get_channels    (png_ptr, png_info_ptr);

  if (color_type == PNG_COLOR_TYPE_PALETTE) {
    isValid = false;
    return;
  }
  png_read_update_info(png_ptr, png_info_ptr);

  // Read colorspace information.
  bool hassRGB, hasiCCP, hasgAMA, hascHRM;
  hassRGB = hasiCCP = hasgAMA = hascHRM = false;
  // Precedence in this order.
  if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP)) {
    png_charpp  name    = NULL;
    int         compression_type = 0;
    png_bytepp  profile = NULL;
    png_uint_32 proflen = 0;
    if (png_get_iCCP(png_ptr, png_info_ptr,
                     name, &compression_type, profile, &proflen)) {
      colorSpace.ICCP.name = std::string(*name, strlen(*name));
      colorSpace.ICCP.profile.resize(proflen);
      for (size_t i = 0; i < proflen; i++)
        colorSpace.ICCP.profile[i] = (*profile)[i];
      colorSpaceType = png_colorspace_iccp;
      hasiCCP = true;
    }
  } else if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_sRGB)) {
    int  intent;
    if (png_get_sRGB(png_ptr, png_info_ptr, &intent)) {
      colorSpace.sRGB = intent;
      colorSpaceType  = png_colorspace_srgb;
      hassRGB = true;
    }
  } else if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_cHRM)) {
    double xw, yw, xr, yr, xg, yg, xb, yb;
    if (png_get_cHRM(png_ptr, png_info_ptr, &xw, &yw,
                     &xr, &yr, &xg, &yg, &xb, &yb)) {
      colorSpace.calRGB.xw = xw;
      colorSpace.calRGB.yw = yw;
      colorSpace.calRGB.xr = xr;
      colorSpace.calRGB.yr = yr;
      colorSpace.calRGB.xg = xg;
      colorSpace.calRGB.yg = yg;
      colorSpace.calRGB.xb = xb;
      colorSpace.calRGB.yb = yb;
      colorSpace.gamma = 2.2;    // maybe wrong but PhotoShop assume this?
      colorSpaceType = png_colorspace_calibrated;
      hascHRM = true;
    }
  }
  if (!hasiCCP && !hassRGB &&
      png_get_valid(png_ptr, png_info_ptr, PNG_INFO_gAMA)) {
    double G;
    if (png_get_gAMA(png_ptr, png_info_ptr, &G)) {
      colorSpace.gamma = 1.0 / G;
      if (!hascHRM)
        colorSpaceType = png_colorspace_gamma_only;
      colorSpace.hasGamma = hasgAMA = true;
    }
  }

  // Read raster image data.
  rowbytes = png_get_rowbytes(png_ptr, png_info_ptr);
  png_bytep stream_data_ptr = new png_byte[rowbytes * height];

  png_bytepp rows_p = new png_bytep[height];
  for (uint32_t i = 0; i < height; i++)
    rows_p[i] = &(stream_data_ptr[rowbytes * i]);
  png_read_image(png_ptr, rows_p);
  delete rows_p;

  // Reading file finished.
  png_read_end(png_ptr, NULL);

  // Cleanup.
  if (png_info_ptr)
    png_destroy_info_struct(png_ptr, &png_info_ptr);
  if (png_ptr)
    png_destroy_read_struct(&png_ptr, NULL, NULL);
  fclose(fp);

  std::string raster(reinterpret_cast<const char *>(stream_data_ptr),
                     rowbytes * height);
  delete stream_data_ptr;

  // Actual timing of construction of Image base class is here.
  Image::reset(width, height, nComps, bpc, raster);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x240, %rsp            # imm = 0x240
movq %rsi, -0x158(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x168(%rbp)
xorl %r8d, %r8d
movl %r8d, %esi
movl %r8d, %edx
movl %r8d, %ecx
callq 0x3760
movq -0x168(%rbp), %rdi
addq $0x20, %rdi
movq %rdi, -0x160(%rbp)
callq 0x54d0
movq -0x158(%rbp), %rdi
callq 0x3140
movq %rax, %rdi
leaq 0x9133(%rip), %rsi      # 0xd556
callq 0x33e0
movq %rax, -0x150(%rbp)
jmp 0x4431
movq -0x150(%rbp), %rax
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
jne 0x4464
movq -0x168(%rbp), %rax
movb $0x0, 0x18(%rax)
jmp 0x4c4a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x4c9f
leaq 0x8bed(%rip), %rdi      # 0xd058
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rsi
movq %rcx, %rdx
callq 0x3080
movq %rax, -0x170(%rbp)
jmp 0x4483
movq -0x170(%rbp), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x44b8
movq -0x20(%rbp), %rdi
callq 0x34e0
movq %rax, -0x178(%rbp)
jmp 0x44a7
movq -0x178(%rbp), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, %rax
jne 0x44e3
cmpq $0x0, -0x20(%rbp)
je 0x44d3
xorl %eax, %eax
movl %eax, %edx
leaq -0x20(%rbp), %rdi
movq %rdx, %rsi
callq 0x31e0
jmp 0x44d1
jmp 0x44d3
movq -0x168(%rbp), %rax
movb $0x0, 0x18(%rax)
jmp 0x4c4a
movq -0x20(%rbp), %rdi
movl $0x2, %esi
movl $0x3, %edx
callq 0x3470
jmp 0x44f8
movq -0x20(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x3570
jmp 0x4507
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x32b0
jmp 0x4516
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x3440
movb %al, -0x179(%rbp)
jmp 0x452b
movb -0x179(%rbp), %al
movb %al, -0x29(%rbp)
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x3230
movl %eax, -0x180(%rbp)
jmp 0x4549
movl -0x180(%rbp), %eax
movl %eax, -0x30(%rbp)
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x35d0
movl %eax, -0x184(%rbp)
jmp 0x4567
movl -0x184(%rbp), %eax
movl %eax, -0x34(%rbp)
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x3050
movb %al, -0x185(%rbp)
jmp 0x4585
movb -0x185(%rbp), %al
movb %al, -0x2a(%rbp)
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x3590
movb %al, -0x186(%rbp)
jmp 0x45a3
movb -0x186(%rbp), %al
movb %al, -0x2b(%rbp)
movzbl -0x29(%rbp), %eax
cmpl $0x3, %eax
jne 0x45c5
movq -0x168(%rbp), %rax
movb $0x0, 0x18(%rax)
jmp 0x4c4a
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x3060
jmp 0x45d4
movb $0x0, -0x48(%rbp)
movb $0x0, -0x47(%rbp)
movb $0x0, -0x46(%rbp)
movb $0x0, -0x45(%rbp)
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x1000, %edx           # imm = 0x1000
callq 0x34a0
movl %eax, -0x18c(%rbp)
jmp 0x45fe
movl -0x18c(%rbp), %eax
cmpl $0x0, %eax
je 0x479f
movq $0x0, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
movq $0x0, -0x60(%rbp)
movl $0x0, -0x64(%rbp)
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x50(%rbp), %rdx
movq -0x60(%rbp), %r8
leaq -0x54(%rbp), %rcx
leaq -0x64(%rbp), %r9
callq 0x32d0
movl %eax, -0x190(%rbp)
jmp 0x4650
movl -0x190(%rbp), %eax
cmpl $0x0, %eax
je 0x479a
movq -0x50(%rbp), %rax
movq (%rax), %rdi
movq %rdi, -0x1a8(%rbp)
callq 0x3170
movq %rax, -0x1a0(%rbp)
leaq -0x89(%rbp), %rdi
movq %rdi, -0x198(%rbp)
callq 0x3510
movq -0x1a8(%rbp), %rsi
movq -0x1a0(%rbp), %rdx
movq -0x198(%rbp), %rcx
leaq -0x88(%rbp), %rdi
callq 0x33b0
jmp 0x46af
movq -0x168(%rbp), %rdi
addq $0x28, %rdi
leaq -0x88(%rbp), %rsi
movq %rsi, -0x1b0(%rbp)
callq 0x3400
movq -0x1b0(%rbp), %rdi
callq 0x3210
leaq -0x89(%rbp), %rdi
callq 0x3380
movq -0x168(%rbp), %rdi
addq $0x48, %rdi
movl -0x64(%rbp), %eax
movl %eax, %esi
callq 0x54f0
jmp 0x46fc
movq $0x0, -0x98(%rbp)
movq -0x98(%rbp), %rax
movl -0x64(%rbp), %ecx
cmpq %rcx, %rax
jae 0x4785
movq -0x168(%rbp), %rdi
movq -0x60(%rbp), %rax
movq (%rax), %rax
movq -0x98(%rbp), %rcx
movb (%rax,%rcx), %al
movb %al, -0x1b1(%rbp)
addq $0x20, %rdi
addq $0x8, %rdi
addq $0x20, %rdi
movq -0x98(%rbp), %rsi
callq 0x5580
movb -0x1b1(%rbp), %cl
movb %cl, (%rax)
movq -0x98(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x98(%rbp)
jmp 0x4707
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x89(%rbp), %rdi
callq 0x3380
jmp 0x4c9f
movq -0x168(%rbp), %rax
movl $0x1, 0x88(%rax)
movb $0x1, -0x46(%rbp)
jmp 0x4958
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x800, %edx            # imm = 0x800
callq 0x34a0
movl %eax, -0x1b8(%rbp)
jmp 0x47b9
movl -0x1b8(%rbp), %eax
cmpl $0x0, %eax
je 0x480e
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
leaq -0x9c(%rbp), %rdx
callq 0x3030
movl %eax, -0x1bc(%rbp)
jmp 0x47e0
movl -0x1bc(%rbp), %eax
cmpl $0x0, %eax
je 0x4809
movq -0x168(%rbp), %rax
movl -0x9c(%rbp), %ecx
movb %cl, 0x20(%rax)
movl $0x2, 0x88(%rax)
movb $0x1, -0x45(%rbp)
jmp 0x4956
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x4, %edx
callq 0x34a0
movl %eax, -0x1c0(%rbp)
jmp 0x4828
movl -0x1c0(%rbp), %eax
cmpl $0x0, %eax
je 0x4954
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq %rsp, %rax
leaq -0xe0(%rbp), %rcx
movq %rcx, 0x18(%rax)
leaq -0xd8(%rbp), %rcx
movq %rcx, 0x10(%rax)
leaq -0xd0(%rbp), %rcx
movq %rcx, 0x8(%rax)
leaq -0xc8(%rbp), %rcx
movq %rcx, (%rax)
leaq -0xa8(%rbp), %rdx
leaq -0xb0(%rbp), %rcx
leaq -0xb8(%rbp), %r8
leaq -0xc0(%rbp), %r9
callq 0x3540
movl %eax, -0x1c4(%rbp)
jmp 0x4896
movl -0x1c4(%rbp), %eax
cmpl $0x0, %eax
je 0x4952
movq -0x168(%rbp), %rax
movsd -0xa8(%rbp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x64(%rax)
movsd -0xb0(%rbp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x68(%rax)
movsd -0xb8(%rbp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x6c(%rax)
movsd -0xc0(%rbp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x70(%rax)
movsd -0xc8(%rbp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x74(%rax)
movsd -0xd0(%rbp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x78(%rax)
movsd -0xd8(%rbp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x7c(%rax)
movsd -0xe0(%rbp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x80(%rax)
movss 0x86d9(%rip), %xmm0     # 0xd018
movss %xmm0, 0x60(%rax)
movl $0x3, 0x88(%rax)
movb $0x1, -0x48(%rbp)
jmp 0x4954
jmp 0x4956
jmp 0x4958
testb $0x1, -0x46(%rbp)
jne 0x4a03
testb $0x1, -0x45(%rbp)
jne 0x4a03
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x1, %edx
callq 0x34a0
movl %eax, -0x1c8(%rbp)
jmp 0x4986
movl -0x1c8(%rbp), %eax
cmpl $0x0, %eax
je 0x4a03
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
leaq -0xe8(%rbp), %rdx
callq 0x31a0
movl %eax, -0x1cc(%rbp)
jmp 0x49ad
movl -0x1cc(%rbp), %eax
cmpl $0x0, %eax
je 0x4a01
movq -0x168(%rbp), %rax
movsd 0x8661(%rip), %xmm0     # 0xd028
divsd -0xe8(%rbp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x60(%rax)
testb $0x1, -0x48(%rbp)
jne 0x49ef
movq -0x168(%rbp), %rax
movl $0x4, 0x88(%rax)
movq -0x168(%rbp), %rax
movb $0x1, -0x47(%rbp)
movb $0x1, 0x84(%rax)
jmp 0x4a03
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x30a0
movq %rax, -0x1d8(%rbp)
jmp 0x4a19
movq -0x1d8(%rbp), %rax
movl %eax, -0x38(%rbp)
movl -0x38(%rbp), %eax
movl -0x34(%rbp), %ecx
imull %ecx, %eax
movl %eax, %edi
callq 0x3040
movq %rax, -0x1e0(%rbp)
jmp 0x4a3c
movq -0x1e0(%rbp), %rax
movq %rax, -0xf0(%rbp)
movl -0x34(%rbp), %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0x3040
movq %rax, -0x1e8(%rbp)
jmp 0x4a61
movq -0x1e8(%rbp), %rax
movq %rax, -0xf8(%rbp)
movl $0x0, -0xfc(%rbp)
movl -0xfc(%rbp), %eax
cmpl -0x34(%rbp), %eax
jae 0x4abc
movq -0xf0(%rbp), %rdx
movl -0x38(%rbp), %eax
imull -0xfc(%rbp), %eax
movl %eax, %eax
addq %rax, %rdx
movq -0xf8(%rbp), %rax
movl -0xfc(%rbp), %ecx
movq %rdx, (%rax,%rcx,8)
movl -0xfc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xfc(%rbp)
jmp 0x4a79
movq -0x20(%rbp), %rdi
movq -0xf8(%rbp), %rsi
callq 0x30f0
jmp 0x4ace
movq -0xf8(%rbp), %rax
movq %rax, -0x1f0(%rbp)
cmpq $0x0, %rax
je 0x4af3
movq -0x1f0(%rbp), %rdi
movl $0x8, %esi
callq 0x3340
movq -0x20(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x3300
jmp 0x4b02
cmpq $0x0, -0x28(%rbp)
je 0x4b1a
movq -0x20(%rbp), %rdi
leaq -0x28(%rbp), %rsi
callq 0x3530
jmp 0x4b18
jmp 0x4b1a
cmpq $0x0, -0x20(%rbp)
je 0x4b35
xorl %eax, %eax
movl %eax, %edx
leaq -0x20(%rbp), %rdi
movq %rdx, %rsi
callq 0x31e0
jmp 0x4b33
jmp 0x4b35
movq -0x18(%rbp), %rdi
callq 0x3320
jmp 0x4b40
movq -0xf0(%rbp), %rax
movq %rax, -0x208(%rbp)
movl -0x38(%rbp), %eax
movl -0x34(%rbp), %ecx
imull %ecx, %eax
movq %rax, -0x200(%rbp)
leaq -0x121(%rbp), %rdi
movq %rdi, -0x1f8(%rbp)
callq 0x3510
movq -0x208(%rbp), %rsi
movq -0x200(%rbp), %rdx
movq -0x1f8(%rbp), %rcx
leaq -0x120(%rbp), %rdi
callq 0x33b0
jmp 0x4b94
leaq -0x121(%rbp), %rdi
callq 0x3380
movq -0xf0(%rbp), %rax
movq %rax, -0x210(%rbp)
cmpq $0x0, %rax
je 0x4bc5
movq -0x210(%rbp), %rdi
movl $0x1, %esi
callq 0x3340
movl -0x30(%rbp), %eax
movl %eax, -0x21c(%rbp)
movl -0x34(%rbp), %eax
movl %eax, -0x218(%rbp)
movb -0x2b(%rbp), %al
movb %al, -0x212(%rbp)
movb -0x2a(%rbp), %al
movb %al, -0x211(%rbp)
leaq -0x148(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x3160
jmp 0x4bfe
movl -0x218(%rbp), %edx
movl -0x21c(%rbp), %esi
movq -0x168(%rbp), %rdi
movb -0x211(%rbp), %al
movb -0x212(%rbp), %cl
movsbl %cl, %ecx
movsbl %al, %r8d
leaq -0x148(%rbp), %r9
callq 0x55a0
jmp 0x4c32
leaq -0x148(%rbp), %rdi
callq 0x3210
leaq -0x120(%rbp), %rdi
callq 0x3210
addq $0x240, %rsp            # imm = 0x240
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x121(%rbp), %rdi
callq 0x3380
jmp 0x4c9f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x4c93
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x148(%rbp), %rdi
callq 0x3210
leaq -0x120(%rbp), %rdi
callq 0x3210
movq -0x160(%rbp), %rdi
callq 0x5670
movq -0x168(%rbp), %rdi
callq 0x3df0
movq -0x40(%rbp), %rdi
callq 0x34f0