// File: tomfunkhouser[P]gaps/pkgs/R2Shapes/R2Image.cpp
// Function: gaps::R2Image::ReadPNGStream(_IO_FILE*)
int R2Image::
ReadPNGStream(FILE *fp)
{
#ifdef RN_USE_PNG
  // Create and initialize the png_struct 
  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL) {
    fclose(fp);
    return 0;
  }

  // Allocate/initialize the memory for image information. 
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    fclose(fp);
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    return 0;
  }

  // Set up the input control if you are using standard C streams 
  png_init_io(png_ptr, fp);

  // Read the png info 
  png_read_info(png_ptr, info_ptr);

  // Extract image info 
  png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  png_byte color_type = png_get_color_type(png_ptr, info_ptr);
  width = png_get_image_width(png_ptr, info_ptr);
  height = png_get_image_height(png_ptr, info_ptr);
  rowsize = png_get_rowbytes(png_ptr, info_ptr);
  if ((rowsize % 4) != 0) rowsize = (rowsize / 4 + 1) * 4;

  // Set ncomponents
  // ncomponents = bit_depth/8; ???
  ncomponents = 0;
  if (color_type == PNG_COLOR_TYPE_GRAY) ncomponents = 1;
  else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ncomponents = 2;
  else if (color_type == PNG_COLOR_TYPE_PALETTE) ncomponents = bit_depth/8;
  else if (color_type == PNG_COLOR_TYPE_RGB) ncomponents = 3;
  else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) ncomponents = 4;
  else { 
    fclose(fp);
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    return 0;
  }

  // Allocate the pixels and row pointers
  pixels = new unsigned char [ height * rowsize ]; 
  png_bytep *row_pointers = (png_bytep *) png_malloc(png_ptr, height * sizeof(png_bytep));
  for (int i = 0; i < height; i++) row_pointers[i] = &pixels[ (height - i - 1) * rowsize ];

  // Read the pixels 
  png_read_image(png_ptr, row_pointers);

  // Finish reading 
  png_read_end(png_ptr, info_ptr);

  // Free the row pointers 
  png_free(png_ptr, row_pointers);

  // Clean up after the read, and free any memory allocated  
  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

  // Return success 
  return 1;
#else
  RNFail("PNG not supported");
  return 0;
#endif
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x38(%rsp)
movq %rsi, 0x30(%rsp)
movq 0x38(%rsp), %rax
movq %rax, (%rsp)
leaq 0x6bea2(%rip), %rdi     # 0x136100
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rsi
movq %rcx, %rdx
callq 0x1006b0
movq %rax, 0x28(%rsp)
cmpq $0x0, 0x28(%rsp)
jne 0xca291
movq 0x30(%rsp), %rdi
callq 0xf4b0
movl $0x0, 0x44(%rsp)
jmp 0xca50e
movq 0x28(%rsp), %rdi
callq 0xfb820
movq %rax, 0x20(%rsp)
cmpq $0x0, 0x20(%rsp)
jne 0xca2d0
movq 0x30(%rsp), %rdi
callq 0xf4b0
leaq 0x28(%rsp), %rdi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x102b40
movl $0x0, 0x44(%rsp)
jmp 0xca50e
movq 0x28(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0xfc210
movq 0x28(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x100be0
movq 0x28(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0xff1b0
movb %al, 0x1f(%rsp)
movq 0x28(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0xff1f0
movb %al, 0x1e(%rsp)
movq 0x28(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0xff130
movl %eax, %ecx
movq (%rsp), %rax
movl %ecx, (%rax)
movq 0x28(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0xff170
movl %eax, %ecx
movq (%rsp), %rax
movl %ecx, 0x4(%rax)
movq 0x28(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0xff0b0
movq %rax, %rcx
movq (%rsp), %rax
movl %ecx, 0xc(%rax)
movl 0xc(%rax), %eax
movl $0x4, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0xca38a
movq (%rsp), %rax
movl 0xc(%rax), %eax
movl $0x4, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq (%rsp), %rax
addl $0x1, %ecx
shll $0x2, %ecx
movl %ecx, 0xc(%rax)
movq (%rsp), %rax
movl $0x0, 0x8(%rax)
movzbl 0x1e(%rsp), %eax
cmpl $0x0, %eax
jne 0xca3af
movq (%rsp), %rax
movl $0x1, 0x8(%rax)
jmp 0xca446
movzbl 0x1e(%rsp), %eax
cmpl $0x4, %eax
jne 0xca3c6
movq (%rsp), %rax
movl $0x2, 0x8(%rax)
jmp 0xca444
movzbl 0x1e(%rsp), %eax
cmpl $0x3, %eax
jne 0xca3e8
movzbl 0x1f(%rsp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq (%rsp), %rax
movl %ecx, 0x8(%rax)
jmp 0xca442
movzbl 0x1e(%rsp), %eax
cmpl $0x2, %eax
jne 0xca3ff
movq (%rsp), %rax
movl $0x3, 0x8(%rax)
jmp 0xca440
movzbl 0x1e(%rsp), %eax
cmpl $0x6, %eax
jne 0xca416
movq (%rsp), %rax
movl $0x4, 0x8(%rax)
jmp 0xca43e
movq 0x30(%rsp), %rdi
callq 0xf4b0
leaq 0x28(%rsp), %rdi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x102b40
movl $0x0, 0x44(%rsp)
jmp 0xca50e
jmp 0xca440
jmp 0xca442
jmp 0xca444
jmp 0xca446
movq (%rsp), %rcx
movl 0x4(%rcx), %eax
imull 0xc(%rcx), %eax
movslq %eax, %rdi
callq 0xf030
movq %rax, %rcx
movq (%rsp), %rax
movq %rcx, 0x10(%rax)
movq 0x28(%rsp), %rdi
movslq 0x4(%rax), %rsi
shlq $0x3, %rsi
callq 0x1135b0
movq %rax, 0x10(%rsp)
movl $0x0, 0xc(%rsp)
movq (%rsp), %rcx
movl 0xc(%rsp), %eax
cmpl 0x4(%rcx), %eax
jge 0xca4c6
movq (%rsp), %rcx
movq 0x10(%rcx), %rdx
movl 0x4(%rcx), %eax
subl 0xc(%rsp), %eax
subl $0x1, %eax
imull 0xc(%rcx), %eax
cltq
addq %rax, %rdx
movq 0x10(%rsp), %rax
movslq 0xc(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movl 0xc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
jmp 0xca483
movq 0x28(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0x1022e0
movq 0x28(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x1023a0
movq 0x28(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0x1136d0
leaq 0x28(%rsp), %rdi
leaq 0x20(%rsp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x102b40
movl $0x1, 0x44(%rsp)
movl 0x44(%rsp), %eax
addq $0x48, %rsp
retq
nopw (%rax,%rax)