// File: /workspace/github_cpp_makefile_star2_O2/jpbalarini[P]otsus/./framework/CImage.cpp
// Function: CImage::load_PNG(char*)
void CImage::load_PNG(char *filename) {
  png_structp png_ptr;
  png_infop info_ptr;
  png_bytep * row_pointers;
  const unsigned PNG_SIG_LEN = 4;

  png_byte header[8];    // 8 is the maximum size that can be checked
  size_t dummy;
  
  /* open file and test for it being a png */
  FILE *fp = fopen(filename, "rb");
  if (!fp) {
    PRINT_ERROR("error opening PNG file %s!\n", filename);
    exit(-1);
  }

  dummy = fread(header, 1, PNG_SIG_LEN, fp);
  dummy = dummy; // To prevent the warning
  if (png_sig_cmp(header, 0, PNG_SIG_LEN)) {
    PRINT_ERROR("file %s is not recognized as a PNG file!\n", filename);
    exit(-1);
  }

  /* initialize stuff */
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

  if (!png_ptr) {
    PRINT_ERROR("png_create_read_struct failed\n");
    exit(-1);
  }

  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    PRINT_ERROR("png_create_info_struct failed\n");
    exit(-1);
  }

  if (setjmp(png_jmpbuf(png_ptr))) {
    PRINT_ERROR("Error during setjmp\n");
    exit(-1);
  }

  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, PNG_SIG_LEN);

  png_read_info(png_ptr, info_ptr);
  
  //png_get_IHDR(png_ptr, info_ptr, &this->Nx, &this->Ny, &this->bits,
  //    color_type, NULL, NULL, NULL);

  this->Nx = png_get_image_width(png_ptr, info_ptr);
  this->Ny = png_get_image_height(png_ptr, info_ptr);
  //color_type = png_get_color_type(png_ptr, info_ptr);
  this->bits = png_get_bit_depth(png_ptr, info_ptr);

  png_set_interlace_handling(png_ptr);
  png_read_update_info(png_ptr, info_ptr);

  /* read file */
  if (setjmp(png_jmpbuf(png_ptr))) {
    PRINT_ERROR("Error during read_image\n");
    exit(-1);
  }

  int bytes_per_row = png_get_rowbytes(png_ptr, info_ptr);  
  png_byte *png_buffer = new png_byte[this->Ny * bytes_per_row];
  
  row_pointers = (png_bytep*)png_malloc(png_ptr, this->Ny * sizeof(png_bytep));
  for (int y = 0; y < this->Ny; y++)
    row_pointers[y] = &png_buffer[y * bytes_per_row];  

  png_read_image(png_ptr, row_pointers);
  int num_channels = png_get_channels(png_ptr, info_ptr);
  fclose(fp);
  
  // Create data channels
  create_channels(num_channels, Nx, Ny);  

  switch (this->bits) {
    case 8:
      for (int ch = 0; ch < num_channels; ch++) {
        float *m = this->get_channel(ch);

        for (int y = 0; y < this->Ny; y++) {
          for (int x = 0; x < this->Nx; x++) {
            int pos = x * num_channels  + ch;
            m[this->Nx * y + x] = row_pointers[y][pos];
          }
        }
      }
      break;
    case 16:
      for (int ch = 0; ch < num_channels; ch++) {
        float *m = this->get_channel(ch);

        for (int y = 0; y < this->Ny; y++) {
          for (int x = 0; x < this->Nx; x++) {
            int pos = (num_channels * x + ch) * 2;
            m[this->Nx * y + x] = 256 * row_pointers[y][pos] + row_pointers[y][pos + 1];
          }
        }
      }
      break;
  }

  // Free memory
  free(row_pointers);
  delete[] png_buffer;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x34cf(%rip), %rsi      # 0x8110
movq %r14, %rdi
callq 0x3320
testq %rax, %rax
je 0x4f33
movq %rax, %r13
leaq 0x20(%rsp), %r15
pushq $0x1
popq %rsi
pushq $0x4
popq %r12
movq %r15, %rdi
movq %r12, %rdx
movq %rax, %rcx
callq 0x3410
xorl %eax, %eax
movl %eax, %esi
movq %r15, %rdi
movq %r12, %rdx
callq 0x31e0
testl %eax, %eax
jne 0x4f65
leaq 0x3818(%rip), %rdi      # 0x84a5
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rsi
movq %rcx, %rdx
callq 0x3080
testq %rax, %rax
je 0x4fa4
movq %rax, %rbp
movq %rax, %rdi
callq 0x34b0
testq %rax, %rax
je 0x4fd4
movq %rax, %r12
movq 0x72cd(%rip), %rsi      # 0xbf90
movl $0xc8, %edx
movq %rbp, %rdi
callq 0x32d0
movq %rax, %rdi
callq 0x33d0
testl %eax, %eax
jne 0x5006
movq %rbp, %rdi
movq %r13, 0x10(%rsp)
movq %r13, %rsi
callq 0x3500
pushq $0x4
popq %rsi
movq %rbp, %rdi
callq 0x30e0
movq %rbp, %rdi
movq %r12, %rsi
callq 0x3220
movq %rbp, %rdi
movq %r12, %rsi
callq 0x31d0
movl %eax, (%rbx)
movq %rbp, %rdi
movq %r12, %rsi
callq 0x3530
movl %eax, 0x4(%rbx)
movq %rbp, %rdi
movq %r12, %rsi
callq 0x3040
movzbl %al, %eax
movl %eax, 0x8(%rbx)
movq %rbp, %rdi
callq 0x34a0
movq %rbp, %rdi
movq %r12, %rsi
callq 0x3060
movq 0x7244(%rip), %rsi      # 0xbf90
movl $0xc8, %edx
movq %rbp, %rdi
callq 0x32d0
movq %rax, %rdi
callq 0x33d0
testl %eax, %eax
jne 0x5038
movq %rbp, %rdi
movq %r12, %rsi
callq 0x30b0
movslq 0x4(%rbx), %r15
movslq %eax, %r14
movq %r15, %rdi
imulq %r14, %rdi
callq 0x3030
movq %rax, %r13
movq %r15, %rsi
shlq $0x3, %rsi
movq %rbp, %rdi
callq 0x3480
movq %rax, %r15
movl 0x4(%rbx), %eax
xorl %ecx, %ecx
testl %eax, %eax
cmovlel %ecx, %eax
movl %ecx, %edx
movq %r13, 0x18(%rsp)
movq %r13, %rcx
movq 0x10(%rsp), %r13
cmpq %rdx, %rax
je 0x4dc6
movq %rcx, (%r15,%rdx,8)
incq %rdx
addq %r14, %rcx
jmp 0x4db5
movq %rbp, %rdi
movq %r15, %rsi
callq 0x3120
movq %rbp, %rdi
movq %r12, %rsi
callq 0x3510
movzbl %al, %ebp
movq %r13, %rdi
callq 0x3270
movl (%rbx), %edx
movl 0x4(%rbx), %ecx
movq %rbx, %rdi
movl %ebp, %esi
callq 0x4724
movl 0x8(%rbx), %eax
cmpl $0x8, %eax
je 0x4e9f
cmpl $0x10, %eax
jne 0x4f12
movl %ebp, %eax
movq %rax, 0x8(%rsp)
addl %ebp, %ebp
movl %ebp, %r13d
xorl %ebp, %ebp
movl %ebp, %r12d
pushq $0x1
popq %r14
cmpq 0x8(%rsp), %r12
je 0x4f12
movl %r12d, %esi
movq %rbx, %rdi
callq 0x598a
movl 0x4(%rbx), %edx
movslq (%rbx), %rsi
movq %rsi, %rcx
testl %esi, %esi
movl %ebp, %edi
cmovgl %esi, %edi
testl %edx, %edx
cmovlel %ebp, %edx
movq %rax, %rsi
movl %edx, %eax
movl %edi, %edx
shlq $0x2, %rcx
movl %ebp, %edi
cmpq %rax, %rdi
je 0x4e96
movl %ebp, %r9d
movq %r14, %r8
cmpq %r9, %rdx
je 0x4e8e
movq (%r15,%rdi,8), %r10
movzwl -0x1(%r10,%r8), %r10d
rolw $0x8, %r10w
movzwl %r10w, %r10d
cvtsi2ss %r10d, %xmm0
movss %xmm0, (%rsi,%r9,4)
incq %r9
addq %r13, %r8
jmp 0x4e63
incq %rdi
addq %rcx, %rsi
jmp 0x4e58
incq %r12
addq $0x2, %r14
jmp 0x4e20
movl %ebp, %r12d
xorl %ebp, %ebp
movl %ebp, %r14d
cmpq %r12, %r14
je 0x4f12
movl %r14d, %esi
movq %rbx, %rdi
callq 0x598a
movl 0x4(%rbx), %edx
movslq (%rbx), %rsi
movq %rsi, %rcx
testl %esi, %esi
movl %ebp, %edi
cmovgl %esi, %edi
testl %edx, %edx
cmovlel %ebp, %edx
movq %rax, %rsi
movl %edx, %eax
movl %edi, %edx
shlq $0x2, %rcx
movl %ebp, %edi
cmpq %rax, %rdi
je 0x4f0d
movl %ebp, %r9d
movq %r14, %r8
cmpq %r9, %rdx
je 0x4f05
movq (%r15,%rdi,8), %r10
movzbl (%r10,%r8), %r10d
cvtsi2ss %r10d, %xmm0
movss %xmm0, (%rsi,%r9,4)
incq %r9
addq %r12, %r8
jmp 0x4ee4
incq %rdi
addq %rcx, %rsi
jmp 0x4ed9
incq %r14
jmp 0x4ea7
movq %r15, %rdi
callq 0x3330
movq 0x18(%rsp), %rdi
callq 0x3380
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x7086(%rip), %r15      # 0xbfc0
movq (%r15), %rdi
leaq 0x3143(%rip), %rsi      # 0x8087
leaq 0x337d(%rip), %rcx      # 0x82c8
xorl %eax, %eax
movl %eax, %ebx
movl $0x124, %edx            # imm = 0x124
callq 0x33c0
movq (%r15), %rdi
leaq 0x34fc(%rip), %rsi      # 0x845f
jmp 0x4f95
movq 0x7054(%rip), %r15      # 0xbfc0
movq (%r15), %rdi
leaq 0x3111(%rip), %rsi      # 0x8087
leaq 0x334b(%rip), %rcx      # 0x82c8
xorl %eax, %eax
movl %eax, %ebx
movl $0x12b, %edx            # imm = 0x12B
callq 0x33c0
movq (%r15), %rdi
leaq 0x34e6(%rip), %rsi      # 0x847b
movq %r14, %rdx
movl %ebx, %eax
callq 0x33c0
jmp 0x5071
movq 0x7015(%rip), %rbx      # 0xbfc0
movq (%rbx), %rdi
leaq 0x30d2(%rip), %rsi      # 0x8087
leaq 0x330c(%rip), %rcx      # 0x82c8
xorl %eax, %eax
movl $0x133, %edx            # imm = 0x133
callq 0x33c0
movq (%rbx), %rcx
leaq 0x34da(%rip), %rdi      # 0x84ac
jmp 0x5002
movq 0x6fe5(%rip), %rbx      # 0xbfc0
movq (%rbx), %rdi
leaq 0x30a2(%rip), %rsi      # 0x8087
leaq 0x32dc(%rip), %rcx      # 0x82c8
xorl %eax, %eax
movl $0x139, %edx            # imm = 0x139
callq 0x33c0
movq (%rbx), %rcx
leaq 0x34c9(%rip), %rdi      # 0x84cb
pushq $0x1e
jmp 0x5068
movq 0x6fb3(%rip), %rbx      # 0xbfc0
movq (%rbx), %rdi
leaq 0x3070(%rip), %rsi      # 0x8087
leaq 0x32aa(%rip), %rcx      # 0x82c8
xorl %eax, %eax
movl $0x13e, %edx            # imm = 0x13E
callq 0x33c0
movq (%rbx), %rcx
leaq 0x34b6(%rip), %rdi      # 0x84ea
pushq $0x14
jmp 0x5068
movq 0x6f81(%rip), %rbx      # 0xbfc0
movq (%rbx), %rdi
leaq 0x303e(%rip), %rsi      # 0x8087
leaq 0x3278(%rip), %rcx      # 0x82c8
xorl %eax, %eax
movl $0x154, %edx            # imm = 0x154
callq 0x33c0
movq (%rbx), %rcx
leaq 0x3499(%rip), %rdi      # 0x84ff
pushq $0x18
popq %rsi
pushq $0x1
popq %rdx
callq 0x3520
pushq $-0x1
popq %rdi
callq 0x3340
nop