// File: tomfunkhouser[P]gaps/pkgs/R2Shapes/R2Image.cpp
// Function: gaps::R2Image::ReadPPMFile(char const*)
int R2Image::
ReadPPMFile(const char *filename)
{
  // Open file
  FILE *fp = fopen(filename, "rb");
  if (!fp) {
    RNFail("Unable to open image file: %s", filename);
    return 0;
  }

  // Read magic identifier
  char buffer[128];
  if (!fgets(buffer, 128, fp)) {
    RNFail("Unable to read magic id in PPM file");
    fclose(fp);
    return 0;
  }

  // skip comments
  int c = getc(fp);
  while (c == '#') {
    while (c != '\n') c = getc(fp);
    c = getc(fp);
  }
  ungetc(c, fp);

  // Read width and height
  if (fscanf(fp, "%d%d", &width, &height) != 2) {
    RNFail("Unable to read width and height in PPM file");
    fclose(fp);
    return 0;
  }
	
  // Read max value
  int max_value;
  if (fscanf(fp, "%d", &max_value) != 1) {
    RNFail("Unable to read max_value in PPM file");
    fclose(fp);
    return 0;
  }
	
  // Assign ncomponents and rowsize
  ncomponents = 3;
  rowsize = ncomponents * width;
  if ((rowsize % 4) != 0) rowsize = (rowsize / 4 + 1) * 4;

  // Allocate image pixels
  int nbytes = rowsize * height;
  pixels = new unsigned char [nbytes];
  if (!pixels) {
    RNFail("Unable to allocate memory for PPM file");
    fclose(fp);
    return 0;
  }

  // Check file type
  if (!strcmp(buffer, "P2\n")) {
    // Read asci gray image data 
    for (int j = height-1; j >= 0; j--) {
      unsigned char *p = &pixels[j*rowsize];
      for (int i = 0; i < width; i++) {
	// Read pixel values
	int value;
	if (fscanf(fp, "%d", &value) != 1) {
	  RNFail("Unable to read data at (%d,%d) in PGM file", i, j);
	  fclose(fp);
	  return 0;
	}

	// Assign pixel values
	*(p++) = ((255 * value) / max_value) & 0xFF;
	*(p++) = ((255 * value) / max_value) & 0xFF;
	*(p++) = ((255 * value) / max_value) & 0xFF;
      }
    }
  }
  else if (!strcmp(buffer, "P3\n")) {
    // Read asci rgb image data 
    for (int j = height-1; j >= 0; j--) {
      unsigned char *p = &pixels[j*rowsize];
      for (int i = 0; i < width; i++) {
	// Read pixel values
	int r, g, b;
	if (fscanf(fp, "%d%d%d", &r, &g, &b) != 3) {
	  RNFail("Unable to read data at (%d,%d) in PPM file", i, j);
	  fclose(fp);
	  return 0;
	}

	// Assign pixel values
	*(p++) = ((255 * r) / max_value) & 0xFF;
	*(p++) = ((255 * g) / max_value) & 0xFF;
	*(p++) = ((255 * b) / max_value) & 0xFF;
      }
    }
  }
  else if (!strcmp(buffer, "P5\n")) {
    // Read up to one character of whitespace (\n) after max_value
    int c = getc(fp);
    if (!isspace(c)) putc(c, fp);

    // Read binary gray image data 
    // First pgm pixel is top-left, so read in opposite scan-line order
    for (int j = height-1; j >= 0; j--) {
      unsigned char *p = &pixels[j*rowsize];
      for (int i = 0; i < width; i++) {
	// Read pixel values
        unsigned char value = ((255 * getc(fp)) / max_value) & 0xFF;
	*(p++) = value;
	*(p++) = value;
	*(p++) = value;
      }
    }
  }
  else if (!strcmp(buffer, "P6\n")) {
    // Read up to one character of whitespace (\n) after max_value
    int c = getc(fp);
    if (!isspace(c)) putc(c, fp);

    // Read binary rgb image data 
    // First ppm pixel is top-left, so read in opposite scan-line order
    for (int j = height-1; j >= 0; j--) {
      unsigned char *p = &pixels[j*rowsize];
      for (int i = 0; i < width; i++) {
	// Read pixel values
	*(p++) = ((255 * getc(fp)) / max_value) & 0xFF;
	*(p++) = ((255 * getc(fp)) / max_value) & 0xFF;
	*(p++) = ((255 * getc(fp)) / max_value) & 0xFF;
      }
    }
  }
  else {
    RNFail("Unrecognized magic header in pbm file: %s\n", buffer);
    fclose(fp);
    return 0;
  }

  // Close file
  fclose(fp);

  // Return success
  return 1;
}

// Assembly:
subq $0x128, %rsp            # imm = 0x128
movq %rdi, 0x118(%rsp)
movq %rsi, 0x110(%rsp)
movq 0x118(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x110(%rsp), %rdi
leaq 0x6c296(%rip), %rsi     # 0x1335d9
callq 0xf5e0
movq %rax, 0x108(%rsp)
cmpq $0x0, 0x108(%rsp)
jne 0xc7381
movq 0x110(%rsp), %rsi
leaq 0x6f123(%rip), %rdi     # 0x13648d
movb $0x0, %al
callq 0xd4f30
movl $0x0, 0x124(%rsp)
jmp 0xc7ae4
leaq 0x80(%rsp), %rdi
movq 0x108(%rsp), %rdx
movl $0x80, %esi
callq 0xf7e0
cmpq $0x0, %rax
jne 0xc73cc
leaq 0x6f163(%rip), %rdi     # 0x13650b
movb $0x0, %al
callq 0xd4f30
movq 0x108(%rsp), %rdi
callq 0xf4b0
movl $0x0, 0x124(%rsp)
jmp 0xc7ae4
movq 0x108(%rsp), %rdi
callq 0xf180
movl %eax, 0x7c(%rsp)
cmpl $0x23, 0x7c(%rsp)
jne 0xc7413
jmp 0xc73e6
cmpl $0xa, 0x7c(%rsp)
je 0xc7400
movq 0x108(%rsp), %rdi
callq 0xf180
movl %eax, 0x7c(%rsp)
jmp 0xc73e6
movq 0x108(%rsp), %rdi
callq 0xf180
movl %eax, 0x7c(%rsp)
jmp 0xc73dd
movl 0x7c(%rsp), %edi
movq 0x108(%rsp), %rsi
callq 0xf0b0
movq 0x8(%rsp), %rdx
movq 0x108(%rsp), %rdi
movq %rdx, %rcx
addq $0x4, %rcx
leaq 0x6c2e7(%rip), %rsi     # 0x133726
movb $0x0, %al
callq 0xf910
cmpl $0x2, %eax
je 0xc7476
leaq 0x6f0dd(%rip), %rdi     # 0x13652f
movb $0x0, %al
callq 0xd4f30
movq 0x108(%rsp), %rdi
callq 0xf4b0
movl $0x0, 0x124(%rsp)
jmp 0xc7ae4
movq 0x108(%rsp), %rdi
leaq 0x70e65(%rip), %rsi     # 0x1382ea
leaq 0x78(%rsp), %rdx
movb $0x0, %al
callq 0xf910
cmpl $0x1, %eax
je 0xc74c1
leaq 0x6f0be(%rip), %rdi     # 0x13655b
movb $0x0, %al
callq 0xd4f30
movq 0x108(%rsp), %rdi
callq 0xf4b0
movl $0x0, 0x124(%rsp)
jmp 0xc7ae4
movq 0x8(%rsp), %rax
movl $0x3, 0x8(%rax)
movl 0x8(%rax), %ecx
imull (%rax), %ecx
movl %ecx, 0xc(%rax)
movl 0xc(%rax), %eax
movl $0x4, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0xc7506
movq 0x8(%rsp), %rax
movl 0xc(%rax), %eax
movl $0x4, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq 0x8(%rsp), %rax
addl $0x1, %ecx
shll $0x2, %ecx
movl %ecx, 0xc(%rax)
movq 0x8(%rsp), %rcx
movl 0xc(%rcx), %eax
imull 0x4(%rcx), %eax
movl %eax, 0x74(%rsp)
movslq 0x74(%rsp), %rdi
callq 0xf030
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x10(%rax)
cmpq $0x0, 0x10(%rax)
jne 0xc755e
leaq 0x6f046(%rip), %rdi     # 0x136580
movb $0x0, %al
callq 0xd4f30
movq 0x108(%rsp), %rdi
callq 0xf4b0
movl $0x0, 0x124(%rsp)
jmp 0xc7ae4
leaq 0x80(%rsp), %rdi
leaq 0x6f03a(%rip), %rsi     # 0x1365a7
callq 0xf700
cmpl $0x0, %eax
jne 0xc76b9
movq 0x8(%rsp), %rax
movl 0x4(%rax), %eax
subl $0x1, %eax
movl %eax, 0x70(%rsp)
cmpl $0x0, 0x70(%rsp)
jl 0xc76b4
movq 0x8(%rsp), %rdx
movq 0x10(%rdx), %rax
movl 0x70(%rsp), %ecx
imull 0xc(%rdx), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x68(%rsp)
movl $0x0, 0x64(%rsp)
movq 0x8(%rsp), %rcx
movl 0x64(%rsp), %eax
cmpl (%rcx), %eax
jge 0xc76a2
movq 0x108(%rsp), %rdi
leaq 0x70d11(%rip), %rsi     # 0x1382ea
leaq 0x60(%rsp), %rdx
movb $0x0, %al
callq 0xf910
cmpl $0x1, %eax
je 0xc761d
movl 0x64(%rsp), %esi
movl 0x70(%rsp), %edx
leaq 0x6efb2(%rip), %rdi     # 0x1365ab
movb $0x0, %al
callq 0xd4f30
movq 0x108(%rsp), %rdi
callq 0xf4b0
movl $0x0, 0x124(%rsp)
jmp 0xc7ae4
imull $0xff, 0x60(%rsp), %eax
cltd
idivl 0x78(%rsp)
andl $0xff, %eax
movb %al, %cl
movq 0x68(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x68(%rsp)
movb %cl, (%rax)
imull $0xff, 0x60(%rsp), %eax
cltd
idivl 0x78(%rsp)
andl $0xff, %eax
movb %al, %cl
movq 0x68(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x68(%rsp)
movb %cl, (%rax)
imull $0xff, 0x60(%rsp), %eax
cltd
idivl 0x78(%rsp)
andl $0xff, %eax
movb %al, %cl
movq 0x68(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x68(%rsp)
movb %cl, (%rax)
movl 0x64(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x64(%rsp)
jmp 0xc75b9
jmp 0xc76a4
movl 0x70(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x70(%rsp)
jmp 0xc758a
jmp 0xc7acc
leaq 0x80(%rsp), %rdi
leaq 0x6ef0e(%rip), %rsi     # 0x1365d6
callq 0xf700
cmpl $0x0, %eax
jne 0xc781e
movq 0x8(%rsp), %rax
movl 0x4(%rax), %eax
subl $0x1, %eax
movl %eax, 0x5c(%rsp)
cmpl $0x0, 0x5c(%rsp)
jl 0xc7819
movq 0x8(%rsp), %rdx
movq 0x10(%rdx), %rax
movl 0x5c(%rsp), %ecx
imull 0xc(%rdx), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x50(%rsp)
movl $0x0, 0x4c(%rsp)
movq 0x8(%rsp), %rcx
movl 0x4c(%rsp), %eax
cmpl (%rcx), %eax
jge 0xc7807
movq 0x108(%rsp), %rdi
leaq 0x6bff0(%rip), %rsi     # 0x133724
leaq 0x48(%rsp), %rdx
leaq 0x44(%rsp), %rcx
leaq 0x40(%rsp), %r8
movb $0x0, %al
callq 0xf910
cmpl $0x3, %eax
je 0xc7782
movl 0x4c(%rsp), %esi
movl 0x5c(%rsp), %edx
leaq 0x6ee7c(%rip), %rdi     # 0x1365da
movb $0x0, %al
callq 0xd4f30
movq 0x108(%rsp), %rdi
callq 0xf4b0
movl $0x0, 0x124(%rsp)
jmp 0xc7ae4
imull $0xff, 0x48(%rsp), %eax
cltd
idivl 0x78(%rsp)
andl $0xff, %eax
movb %al, %cl
movq 0x50(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x50(%rsp)
movb %cl, (%rax)
imull $0xff, 0x44(%rsp), %eax
cltd
idivl 0x78(%rsp)
andl $0xff, %eax
movb %al, %cl
movq 0x50(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x50(%rsp)
movb %cl, (%rax)
imull $0xff, 0x40(%rsp), %eax
cltd
idivl 0x78(%rsp)
andl $0xff, %eax
movb %al, %cl
movq 0x50(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x50(%rsp)
movb %cl, (%rax)
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0xc7714
jmp 0xc7809
movl 0x5c(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x5c(%rsp)
jmp 0xc76e5
jmp 0xc7aca
leaq 0x80(%rsp), %rdi
leaq 0x6edd8(%rip), %rsi     # 0x136605
callq 0xf700
cmpl $0x0, %eax
jne 0xc7940
movq 0x108(%rsp), %rdi
callq 0xf180
movl %eax, 0x3c(%rsp)
movl 0x3c(%rsp), %edi
callq 0xf080
cmpl $0x0, %eax
jne 0xc786b
movl 0x3c(%rsp), %edi
movq 0x108(%rsp), %rsi
callq 0xf960
movq 0x8(%rsp), %rax
movl 0x4(%rax), %eax
subl $0x1, %eax
movl %eax, 0x38(%rsp)
cmpl $0x0, 0x38(%rsp)
jl 0xc793b
movq 0x8(%rsp), %rdx
movq 0x10(%rdx), %rax
movl 0x38(%rsp), %ecx
imull 0xc(%rdx), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x30(%rsp)
movl $0x0, 0x2c(%rsp)
movq 0x8(%rsp), %rcx
movl 0x2c(%rsp), %eax
cmpl (%rcx), %eax
jge 0xc7929
movq 0x108(%rsp), %rdi
callq 0xf180
imull $0xff, %eax, %eax
cltd
idivl 0x78(%rsp)
andl $0xff, %eax
movb %al, 0x2b(%rsp)
movb 0x2b(%rsp), %cl
movq 0x30(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x30(%rsp)
movb %cl, (%rax)
movb 0x2b(%rsp), %cl
movq 0x30(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x30(%rsp)
movb %cl, (%rax)
movb 0x2b(%rsp), %cl
movq 0x30(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x30(%rsp)
movb %cl, (%rax)
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0xc78a9
jmp 0xc792b
movl 0x38(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0xc787a
jmp 0xc7ac8
leaq 0x80(%rsp), %rdi
leaq 0x6ecba(%rip), %rsi     # 0x136609
callq 0xf700
cmpl $0x0, %eax
jne 0xc7a96
movq 0x108(%rsp), %rdi
callq 0xf180
movl %eax, 0x24(%rsp)
movl 0x24(%rsp), %edi
callq 0xf080
cmpl $0x0, %eax
jne 0xc798d
movl 0x24(%rsp), %edi
movq 0x108(%rsp), %rsi
callq 0xf960
movq 0x8(%rsp), %rax
movl 0x4(%rax), %eax
subl $0x1, %eax
movl %eax, 0x20(%rsp)
cmpl $0x0, 0x20(%rsp)
jl 0xc7a94
movq 0x8(%rsp), %rdx
movq 0x10(%rdx), %rax
movl 0x20(%rsp), %ecx
imull 0xc(%rdx), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x18(%rsp)
movl $0x0, 0x14(%rsp)
movq 0x8(%rsp), %rcx
movl 0x14(%rsp), %eax
cmpl (%rcx), %eax
jge 0xc7a82
movq 0x108(%rsp), %rdi
callq 0xf180
imull $0xff, %eax, %eax
cltd
idivl 0x78(%rsp)
andl $0xff, %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x18(%rsp)
movb %cl, (%rax)
movq 0x108(%rsp), %rdi
callq 0xf180
imull $0xff, %eax, %eax
cltd
idivl 0x78(%rsp)
andl $0xff, %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x18(%rsp)
movb %cl, (%rax)
movq 0x108(%rsp), %rdi
callq 0xf180
imull $0xff, %eax, %eax
cltd
idivl 0x78(%rsp)
andl $0xff, %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x18(%rsp)
movb %cl, (%rax)
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0xc79cb
jmp 0xc7a84
movl 0x20(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x20(%rsp)
jmp 0xc799c
jmp 0xc7ac6
leaq 0x80(%rsp), %rsi
leaq 0x6eb68(%rip), %rdi     # 0x13660d
movb $0x0, %al
callq 0xd4f30
movq 0x108(%rsp), %rdi
callq 0xf4b0
movl $0x0, 0x124(%rsp)
jmp 0xc7ae4
jmp 0xc7ac8
jmp 0xc7aca
jmp 0xc7acc
movq 0x108(%rsp), %rdi
callq 0xf4b0
movl $0x1, 0x124(%rsp)
movl 0x124(%rsp), %eax
addq $0x128, %rsp            # imm = 0x128
retq
nopw %cs:(%rax,%rax)