// File: /workspace/github_cpp_makefile_star2_O1/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 $0x18, %rsp
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x2e8d(%rip), %rsi      # 0x8110
movq %r14, %rdi
callq 0x32f0
testq %rax, %rax
je 0x55a3
movq %rax, %r12
leaq 0x10(%rsp), %r15
movl $0x4, %r13d
movl $0x1, %esi
movq %r15, %rdi
movq %r13, %rdx
movq %rax, %rcx
callq 0x33d0
xorl %eax, %eax
movl %eax, %esi
movq %r15, %rdi
movq %r13, %rdx
callq 0x31c0
testl %eax, %eax
jne 0x55ab
leaq 0x31d2(%rip), %rdi      # 0x84a5
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rsi
movq %rcx, %rdx
callq 0x3080
testq %rax, %rax
je 0x55b3
movq %rax, %r13
movq %rax, %rdi
callq 0x34a0
testq %rax, %rax
je 0x55b8
movq %rax, %rbp
movq 0x6c7f(%rip), %rsi      # 0xbf88
movl $0xc8, %edx
movq %r13, %rdi
callq 0x3290
movq %rax, %rdi
callq 0x3390
testl %eax, %eax
jne 0x55bd
movq %r13, %rdi
movq %r12, %rsi
callq 0x34e0
movq %r13, %rdi
movl $0x4, %esi
callq 0x30e0
movq %r13, %rdi
movq %rbp, %rsi
callq 0x3200
movq %r13, %rdi
movq %rbp, %rsi
callq 0x31b0
movl %eax, (%rbx)
movq %r13, %rdi
movq %rbp, %rsi
callq 0x3520
movl %eax, 0x4(%rbx)
movq %r13, %rdi
movq %rbp, %rsi
callq 0x3040
movzbl %al, %eax
movl %eax, 0x8(%rbx)
movq %r13, %rdi
callq 0x3490
movq %r13, %rdi
movq %rbp, %rsi
callq 0x3060
movq 0x6bf9(%rip), %rsi      # 0xbf88
movl $0xc8, %edx
movq %r13, %rdi
callq 0x3290
movq %rax, %rdi
callq 0x3390
testl %eax, %eax
jne 0x55c2
movq %r13, %rdi
movq %rbp, %rsi
callq 0x30b0
movq %rax, %r14
movslq 0x4(%rbx), %r15
movslq %eax, %rdi
imulq %r15, %rdi
callq 0x3030
movq %rax, (%rsp)
movq %r15, %rsi
shlq $0x3, %rsi
movq %r13, %rdi
callq 0x3460
movq %rax, %r15
movslq 0x4(%rbx), %rax
testq %rax, %rax
jle 0x5409
movslq %r14d, %rcx
xorl %edx, %edx
movl %edx, %esi
movq (%rsp), %rdx
movq %rdx, (%r15,%rsi,8)
movq %rsi, %rdi
incq %rdi
addq %rcx, %rdx
movq %rdi, %rsi
cmpq %rdi, %rax
jne 0x53f4
movq %r13, %rdi
movq %r15, %rsi
callq 0x3110
movq %r13, %rdi
movq %rbp, %rsi
callq 0x3500
movl %eax, %r14d
movzbl %al, %ebp
movq %r12, %rdi
callq 0x3240
movl (%rbx), %edx
movl 0x4(%rbx), %ecx
movq %rbx, %rdi
movl %ebp, %esi
callq 0x4df0
movl 0x8(%rbx), %eax
cmpl $0x8, %eax
je 0x5500
cmpl $0x10, %eax
jne 0x5583
testb %r14b, %r14b
je 0x5583
movl %ebp, %eax
movq %rax, 0x8(%rsp)
addl %ebp, %ebp
movl %ebp, %r12d
movl $0x1, %r13d
xorl %ebp, %ebp
movl %ebp, %r14d
movl %r14d, %esi
movq %rbx, %rdi
callq 0x5cc2
movslq 0x4(%rbx), %rcx
testq %rcx, %rcx
jle 0x54e3
movq %rax, %rdi
movl (%rbx), %eax
leaq (,%rax,4), %rdx
movl %ebp, %r8d
movl %eax, %esi
testl %esi, %esi
jle 0x54d2
movq (%r15,%r8,8), %r9
addq %r13, %r9
movl %ebp, %r10d
movzwl -0x1(%r9), %r11d
rolw $0x8, %r11w
movzwl %r11w, %r11d
xorps %xmm0, %xmm0
cvtsi2ss %r11d, %xmm0
movss %xmm0, (%rdi,%r10,4)
movq %r10, %r11
incq %r11
addq %r12, %r9
movq %r11, %r10
cmpq %r11, %rax
jne 0x54a5
movq %r8, %r9
incq %r9
addq %rdx, %rdi
movq %r9, %r8
cmpq %rcx, %r9
jne 0x5497
movq %r14, %rax
incq %rax
addq $0x2, %r13
movq %rax, %r14
cmpq 0x8(%rsp), %rax
jne 0x5471
jmp 0x5583
testb %r14b, %r14b
je 0x5583
movl %ebp, %r14d
xorl %ebp, %ebp
movl %ebp, %r12d
movl %r12d, %esi
movq %rbx, %rdi
callq 0x5cc2
movslq 0x4(%rbx), %rcx
testq %rcx, %rcx
jle 0x5575
movq %rax, %rdi
movl (%rbx), %eax
leaq (,%rax,4), %rdx
movl %ebp, %r8d
movl %eax, %esi
testl %esi, %esi
jle 0x5564
movq (%r15,%r8,8), %r9
addq %r12, %r9
movl %ebp, %r10d
movzbl (%r9), %r11d
xorps %xmm0, %xmm0
cvtsi2ss %r11d, %xmm0
movss %xmm0, (%rdi,%r10,4)
movq %r10, %r11
incq %r11
addq %r14, %r9
movq %r11, %r10
cmpq %r11, %rax
jne 0x5541
movq %r8, %r9
incq %r9
addq %rdx, %rdi
movq %r9, %r8
cmpq %rcx, %r9
jne 0x5533
movq %r12, %rax
incq %rax
movq %rax, %r12
cmpq %r14, %rax
jne 0x550d
movq %r15, %rdi
callq 0x3300
movq (%rsp), %rdi
callq 0x3350
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
callq 0x3858
movq %r14, %rdi
callq 0x3709
callq 0x3816
callq 0x37d4
callq 0x3750
callq 0x3792
nop