// File: tomfunkhouser[P]gaps/pkgs/R2Shapes/R2Image.cpp
// Function: gaps::R2Image::WritePNGStream(_IO_FILE*) const
int R2Image::
WritePNGStream(FILE *fp) const
{
#ifdef RN_USE_PNG
  // Create and initialize the png_struct 
  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL) {
    fclose(fp);
    return 0;
  }
  
  // Allocate/initialize the image information data. 
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    fclose(fp);
    png_destroy_write_struct(&png_ptr,  NULL);
    return 0;
  }
  
  // Determine color type  
  png_byte color_type = 0;
  if (ncomponents == 1) color_type = PNG_COLOR_TYPE_GRAY;
  else if (ncomponents == 2) color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
  else if (ncomponents == 3) color_type = PNG_COLOR_TYPE_RGB;
  else if (ncomponents == 4) color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  else { RNFail("Invalid number of components in PNG file\n"); return 0; }

  // Fill in the image data 
  png_set_IHDR(png_ptr, info_ptr, width, height,
    8, color_type, PNG_INTERLACE_NONE,
    PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

  // Allocate the row pointers 
  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];
  
  // Set up the output control 
  png_init_io(png_ptr, fp);
  
  // Write the png info 
  png_write_info(png_ptr, info_ptr);
  
  // Write the pixels 
  png_write_image(png_ptr, row_pointers);
  
  // Finish writing 
  png_write_end(png_ptr, info_ptr);
  
  // Free the row pointers 
  png_free(png_ptr, row_pointers);

  // Clean up after the write, and free any memory allocated 
  png_destroy_write_struct(&png_ptr, &info_ptr);

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

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x58(%rsp)
movq %rsi, 0x50(%rsp)
movq 0x58(%rsp), %rax
movq %rax, 0x20(%rsp)
leaq 0x6bbc1(%rip), %rdi     # 0x136100
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rsi
movq %rcx, %rdx
callq 0x104540
movq %rax, 0x48(%rsp)
cmpq $0x0, 0x48(%rsp)
jne 0xca572
movq 0x50(%rsp), %rdi
callq 0xf4b0
movl $0x0, 0x64(%rsp)
jmp 0xca725
movq 0x48(%rsp), %rdi
callq 0xfb820
movq %rax, 0x40(%rsp)
cmpq $0x0, 0x40(%rsp)
jne 0xca5ae
movq 0x50(%rsp), %rdi
callq 0xf4b0
leaq 0x48(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x105530
movl $0x0, 0x64(%rsp)
jmp 0xca725
movq 0x20(%rsp), %rax
movb $0x0, 0x3f(%rsp)
cmpl $0x1, 0x8(%rax)
jne 0xca5c5
movb $0x0, 0x3f(%rsp)
jmp 0xca61c
movq 0x20(%rsp), %rax
cmpl $0x2, 0x8(%rax)
jne 0xca5d7
movb $0x4, 0x3f(%rsp)
jmp 0xca61a
movq 0x20(%rsp), %rax
cmpl $0x3, 0x8(%rax)
jne 0xca5e9
movb $0x2, 0x3f(%rsp)
jmp 0xca618
movq 0x20(%rsp), %rax
cmpl $0x4, 0x8(%rax)
jne 0xca5fb
movb $0x6, 0x3f(%rsp)
jmp 0xca616
leaq 0x6c0f5(%rip), %rdi     # 0x1366f7
movb $0x0, %al
callq 0xd4f30
movl $0x0, 0x64(%rsp)
jmp 0xca725
jmp 0xca618
jmp 0xca61a
jmp 0xca61c
movq 0x20(%rsp), %rax
movq 0x48(%rsp), %rdi
movq 0x40(%rsp), %rsi
movl (%rax), %edx
movl 0x4(%rax), %ecx
movzbl 0x3f(%rsp), %r9d
movl $0x8, %r8d
xorl %eax, %eax
movl $0x0, (%rsp)
movl $0x0, 0x8(%rsp)
movl $0x0, 0x10(%rsp)
callq 0xfd370
movq 0x20(%rsp), %rax
movq 0x48(%rsp), %rdi
movslq 0x4(%rax), %rsi
shlq $0x3, %rsi
callq 0x1135b0
movq %rax, 0x30(%rsp)
movl $0x0, 0x2c(%rsp)
movq 0x20(%rsp), %rcx
movl 0x2c(%rsp), %eax
cmpl 0x4(%rcx), %eax
jge 0xca6c3
movq 0x20(%rsp), %rcx
movq 0x10(%rcx), %rdx
movl 0x4(%rcx), %eax
subl 0x2c(%rsp), %eax
subl $0x1, %eax
imull 0xc(%rcx), %eax
cltq
addq %rax, %rdx
movq 0x30(%rsp), %rax
movslq 0x2c(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0xca67e
movq 0x48(%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0xfc210
movq 0x48(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0x103a80
movq 0x48(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x1052a0
movq 0x48(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0x1040f0
movq 0x48(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x1136d0
leaq 0x48(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x105530
movl $0x1, 0x64(%rsp)
movl 0x64(%rsp), %eax
addq $0x68, %rsp
retq
nop