// File: tomfunkhouser[P]gaps/pkgs/R2Shapes/R2Image.cpp
// Function: gaps::R2Image::WritePPMFile(char const*, int) const
int R2Image::
WritePPMFile(const char *filename, int ascii) const
{
  // Check ncomponents
  assert(ncomponents == 3);

  // Check pgm/ppm
  int pgm = (strstr(filename, ".pgm")) ? 1 : 0;

  // Check type
  if (ascii) {
    // Open file
    FILE *fp = fopen(filename, "w");
    if (!fp) {
      RNFail("Unable to open image file: %s", filename);
      return 0;
    }

    // Print PPM image file 
    // First ppm pixel is top-left, so write in opposite scan-line order
    if (pgm) fprintf(fp, "P2\n");
    else fprintf(fp, "P3\n");
    fprintf(fp, "%d %d\n", width, height);
    fprintf(fp, "255\n");
    for (int j = height-1; j >= 0 ; j--) {
      for (int i = 0; i < width; i++) {
        const unsigned char *p = Pixel(i, j);
        int r = *(p++) & 0xFF;
        int g = *(p++) & 0xFF;
        int b = *(p++) & 0xFF;
        if (pgm) fprintf(fp, "%-3d  ", (int) (0.30*r + 0.59*g + 0.11*b));
        else fprintf(fp, "%-3d %-3d %-3d  ", r, g, b);
        if (((i+1) % 4) == 0) fprintf(fp, "\n");
      }
      if ((width % 4) != 0) fprintf(fp, "\n");
    }
    fprintf(fp, "\n");

    // Close file
    fclose(fp);
  }
  else {
    // Open file
    FILE *fp = fopen(filename, "wb");
    if (!fp) {
      RNFail("Unable to open image file: %s", filename);
      return 0;
    }
    
    // Print PPM image file 
    // First ppm pixel is top-left, so write in opposite scan-line order
    if (pgm) fprintf(fp, "P5\n");
    else fprintf(fp, "P6\n");
    fprintf(fp, "%d %d\n", width, height);
    fprintf(fp, "255\n");
    for (int j = height-1; j >= 0 ; j--) {
      for (int i = 0; i < width; i++) {
        const unsigned char *p = Pixel(i, j);
        int r = *(p++) & 0xFF;
        int g = *(p++) & 0xFF;
        int b = *(p++) & 0xFF;
        if (pgm) fprintf(fp, "%c", (int) (0.30*r + 0.59*g + 0.11*b));
        else fprintf(fp, "%c%c%c", r, g, b);
      }
    }
    
    // Close file
    fclose(fp);
  }

  // Return number of bytes written
  return width * height * ncomponents;  
}

// Assembly:
subq $0x78, %rsp
movq %rdi, 0x68(%rsp)
movq %rsi, 0x60(%rsp)
movl %edx, 0x5c(%rsp)
movq 0x68(%rsp), %rax
movq %rax, (%rsp)
movq 0x60(%rsp), %rdi
leaq 0x6d1cd(%rip), %rsi     # 0x136424
callq 0xf110
movq %rax, %rdx
xorl %eax, %eax
movl $0x1, %ecx
cmpq $0x0, %rdx
cmovnel %ecx, %eax
movl %eax, 0x58(%rsp)
cmpl $0x0, 0x5c(%rsp)
je 0xc94c7
movq 0x60(%rsp), %rdi
leaq 0x6b06b(%rip), %rsi     # 0x1342f3
callq 0xf5e0
movq %rax, 0x50(%rsp)
cmpq $0x0, 0x50(%rsp)
jne 0xc92ba
movq 0x60(%rsp), %rsi
leaq 0x6d1e7(%rip), %rdi     # 0x13648d
movb $0x0, %al
callq 0xd4f30
movl $0x0, 0x74(%rsp)
jmp 0xc96bf
cmpl $0x0, 0x58(%rsp)
je 0xc92d6
movq 0x50(%rsp), %rdi
leaq 0x6d2da(%rip), %rsi     # 0x1365a7
movb $0x0, %al
callq 0xf730
jmp 0xc92e9
movq 0x50(%rsp), %rdi
leaq 0x6d2f4(%rip), %rsi     # 0x1365d6
movb $0x0, %al
callq 0xf730
movq (%rsp), %rax
movq 0x50(%rsp), %rdi
movl (%rax), %edx
movl 0x4(%rax), %ecx
leaq 0x6a772(%rip), %rsi     # 0x133a70
movb $0x0, %al
callq 0xf730
movq 0x50(%rsp), %rdi
leaq 0x6d327(%rip), %rsi     # 0x136638
movb $0x0, %al
callq 0xf730
movq (%rsp), %rax
movl 0x4(%rax), %eax
subl $0x1, %eax
movl %eax, 0x4c(%rsp)
cmpl $0x0, 0x4c(%rsp)
jl 0xc94a5
movl $0x0, 0x48(%rsp)
movq (%rsp), %rcx
movl 0x48(%rsp), %eax
cmpl (%rcx), %eax
jge 0xc946d
movq (%rsp), %rdi
movl 0x48(%rsp), %esi
movl 0x4c(%rsp), %edx
callq 0xca870
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x40(%rsp)
movzbl (%rax), %eax
andl $0xff, %eax
movl %eax, 0x3c(%rsp)
movq 0x40(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x40(%rsp)
movzbl (%rax), %eax
andl $0xff, %eax
movl %eax, 0x38(%rsp)
movq 0x40(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x40(%rsp)
movzbl (%rax), %eax
andl $0xff, %eax
movl %eax, 0x34(%rsp)
cmpl $0x0, 0x58(%rsp)
je 0xc9414
movq 0x50(%rsp), %rdi
cvtsi2sdl 0x3c(%rsp), %xmm1
cvtsi2sdl 0x38(%rsp), %xmm2
movsd 0x6c88a(%rip), %xmm0    # 0x135c60
mulsd %xmm2, %xmm0
movsd 0x6c876(%rip), %xmm2    # 0x135c58
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
cvtsi2sdl 0x34(%rsp), %xmm0
movsd 0x6c858(%rip), %xmm2    # 0x135c50
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %edx
leaq 0x6d23c(%rip), %rsi     # 0x136647
movb $0x0, %al
callq 0xf730
jmp 0xc9434
movq 0x50(%rsp), %rdi
movl 0x3c(%rsp), %edx
movl 0x38(%rsp), %ecx
movl 0x34(%rsp), %r8d
leaq 0x6d210(%rip), %rsi     # 0x13663d
movb $0x0, %al
callq 0xf730
movl 0x48(%rsp), %eax
addl $0x1, %eax
movl $0x4, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0xc945b
movq 0x50(%rsp), %rdi
leaq 0x6f5be(%rip), %rsi     # 0x138a12
movb $0x0, %al
callq 0xf730
jmp 0xc945d
movl 0x48(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x48(%rsp)
jmp 0xc9339
movq (%rsp), %rax
movl (%rax), %eax
movl $0x4, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0xc9493
movq 0x50(%rsp), %rdi
leaq 0x6f586(%rip), %rsi     # 0x138a12
movb $0x0, %al
callq 0xf730
jmp 0xc9495
movl 0x4c(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0xc9326
movq 0x50(%rsp), %rdi
leaq 0x6f561(%rip), %rsi     # 0x138a12
movb $0x0, %al
callq 0xf730
movq 0x50(%rsp), %rdi
callq 0xf4b0
jmp 0xc96ad
movq 0x60(%rsp), %rdi
leaq 0x6a5e7(%rip), %rsi     # 0x133aba
callq 0xf5e0
movq %rax, 0x28(%rsp)
cmpq $0x0, 0x28(%rsp)
jne 0xc9505
movq 0x60(%rsp), %rsi
leaq 0x6cf9c(%rip), %rdi     # 0x13648d
movb $0x0, %al
callq 0xd4f30
movl $0x0, 0x74(%rsp)
jmp 0xc96bf
cmpl $0x0, 0x58(%rsp)
je 0xc9521
movq 0x28(%rsp), %rdi
leaq 0x6d0ed(%rip), %rsi     # 0x136605
movb $0x0, %al
callq 0xf730
jmp 0xc9534
movq 0x28(%rsp), %rdi
leaq 0x6d0dc(%rip), %rsi     # 0x136609
movb $0x0, %al
callq 0xf730
movq (%rsp), %rax
movq 0x28(%rsp), %rdi
movl (%rax), %edx
movl 0x4(%rax), %ecx
leaq 0x6a527(%rip), %rsi     # 0x133a70
movb $0x0, %al
callq 0xf730
movq 0x28(%rsp), %rdi
leaq 0x6d0dc(%rip), %rsi     # 0x136638
movb $0x0, %al
callq 0xf730
movq (%rsp), %rax
movl 0x4(%rax), %eax
subl $0x1, %eax
movl %eax, 0x24(%rsp)
cmpl $0x0, 0x24(%rsp)
jl 0xc96a3
movl $0x0, 0x20(%rsp)
movq (%rsp), %rcx
movl 0x20(%rsp), %eax
cmpl (%rcx), %eax
jge 0xc9691
movq (%rsp), %rdi
movl 0x20(%rsp), %esi
movl 0x24(%rsp), %edx
callq 0xca870
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %eax
andl $0xff, %eax
movl %eax, 0x14(%rsp)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %eax
andl $0xff, %eax
movl %eax, 0x10(%rsp)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %eax
andl $0xff, %eax
movl %eax, 0xc(%rsp)
cmpl $0x0, 0x58(%rsp)
je 0xc965f
movq 0x28(%rsp), %rdi
cvtsi2sdl 0x14(%rsp), %xmm1
cvtsi2sdl 0x10(%rsp), %xmm2
movsd 0x6c63f(%rip), %xmm0    # 0x135c60
mulsd %xmm2, %xmm0
movsd 0x6c62b(%rip), %xmm2    # 0x135c58
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
cvtsi2sdl 0xc(%rsp), %xmm0
movsd 0x6c60d(%rip), %xmm2    # 0x135c50
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %edx
leaq 0x6cffc(%rip), %rsi     # 0x136652
movb $0x0, %al
callq 0xf730
jmp 0xc967f
movq 0x28(%rsp), %rdi
movl 0x14(%rsp), %edx
movl 0x10(%rsp), %ecx
movl 0xc(%rsp), %r8d
leaq 0x6cfd6(%rip), %rsi     # 0x13664e
movb $0x0, %al
callq 0xf730
jmp 0xc9681
movl 0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
jmp 0xc9584
jmp 0xc9693
movl 0x24(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0xc9571
movq 0x28(%rsp), %rdi
callq 0xf4b0
movq (%rsp), %rcx
movl (%rcx), %eax
imull 0x4(%rcx), %eax
imull 0x8(%rcx), %eax
movl %eax, 0x74(%rsp)
movl 0x74(%rsp), %eax
addq $0x78, %rsp
retq
nopl (%rax,%rax)