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

  // Read grid resolution from file
  int grid_resolution[2];
  if (fread(&grid_resolution, sizeof(int), 2, fp) != 2) {
    RNFail("Unable to read resolution from grid file");
    return 0;
  }

  // Read world_to_grid transformation from file
  RNScalar m[9];
  if (fread(m, sizeof(RNScalar), 9, fp) != 9) {
    RNFail("Unable to read transformation matrix from file");
    return 0;
  }

  // Allocate grid values
  int grid_size = grid_resolution[0] * grid_resolution[1];
  RNScalar *grid_values = new RNScalar [ grid_size ];
  assert(grid_values);

  // Read grid values
  if (fread(grid_values, sizeof(RNScalar), grid_size, fp) != (unsigned int) grid_size) {
    RNFail("Unable to read %d grid values from file", grid_size);
    return 0;
  }

  // Close file
  fclose(fp);

  // Determine offset and scale
  RNScalar offset = 0;
  RNScalar scale = 1;
  if (grid_size > 0) {
    RNScalar sum = 0;
    RNScalar min_value = FLT_MAX;
    RNScalar max_value = -FLT_MAX;
    for (int i = 0; i < grid_size; i++) {
      if (grid_values[i] == R2_GRID_UNKNOWN_VALUE) continue;
      if (grid_values[i] > max_value) max_value = grid_values[i];
      if (grid_values[i] < min_value) min_value = grid_values[i];
      sum += grid_values[i];
    }
    RNScalar mean = sum / grid_size;
    RNScalar ssd = 0;
    for (int i = 0; i < grid_size; i++) {
      if (grid_values[i] == R2_GRID_UNKNOWN_VALUE) continue;
      RNScalar delta = grid_values[i] - mean;
      ssd += delta * delta;
    }
    RNScalar stddev = sqrt(ssd);
    RNScalar min_clamped = mean - 3 * stddev;
    if (min_clamped < min_value) min_clamped = min_value;
    RNScalar max_clamped = mean + 3 * stddev;
    if (max_clamped > max_value) max_clamped = max_value;
    RNScalar range = max_clamped - min_clamped;
    if (range > 0) {
      offset = min_clamped;
      scale = 1.0 / range;
    }
  }

  // Allocate pixels
  ncomponents = 3;
  width = grid_resolution[0];
  height = grid_resolution[1];
  rowsize = ncomponents * width;
  if ((rowsize % 4) != 0) rowsize = (rowsize / 4 + 1) * 4;
  int nbytes = rowsize * height;
  pixels = new unsigned char [nbytes];
  assert(pixels);

  // Fill in pixels
  RNScalar *grid_valuesp = grid_values;
  for (int j = 0; j < height; j++) {
    unsigned char *pixelsp = &pixels[j*rowsize];
    for (int i = 0; i < width; i++) {
      int value = (int) ((*(grid_valuesp++) - offset) * 255.0 * scale);
      if (value < 0) value = 0;
      if (value > 255) value = 255;
      unsigned char p = (unsigned char) value;
      *(pixelsp++) = p;
      *(pixelsp++) = p;
      *(pixelsp++) = p;
    }
  }

  // Delete grid values
  delete [] grid_values;

  // Return number of bytes
  return nbytes;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x31b13(%rip), %rsi     # 0x9355b
movq %r14, %rdi
callq 0xe550
testq %rax, %rax
je 0x61b54
movq %rax, %r13
leaq 0x8(%rsp), %rdi
pushq $0x4
popq %rsi
pushq $0x2
popq %rdx
movq %rax, %rcx
callq 0xe6f0
cmpq $0x2, %rax
jne 0x61b69
leaq 0x40(%rsp), %rdi
pushq $0x8
popq %rsi
pushq $0x9
popq %rdx
movq %r13, %rcx
callq 0xe6f0
cmpq $0x9, %rax
jne 0x61b72
movl 0x8(%rsp), %r12d
movl 0xc(%rsp), %r14d
movl %r14d, %ebp
imull %r12d, %ebp
movslq %ebp, %r15
leaq (,%r15,8), %rax
testl %r15d, %r15d
pushq $-0x1
popq %rdi
cmovnsq %rax, %rdi
callq 0xe030
pushq $0x8
popq %rsi
movq %rax, 0x10(%rsp)
movq %rax, %rdi
movq %r15, %rdx
movq %r13, %rcx
callq 0xe6f0
movq %rbp, %rsi
cmpq %rbp, %rax
jne 0x61b96
movq %rax, %r15
movq %r13, %rdi
movq %rsi, %r13
callq 0xe440
movq %r13, %rcx
testl %ecx, %ecx
jle 0x61c00
xorpd %xmm7, %xmm7
movsd 0x31510(%rip), %xmm5    # 0x93018
movsd 0x32158(%rip), %xmm6    # 0x93c68
xorl %eax, %eax
movsd 0x3244e(%rip), %xmm1    # 0x93f68
movq 0x10(%rsp), %r13
cmpq %rax, %r15
je 0x61ba8
movsd (%r13,%rax,8), %xmm0
ucomisd %xmm1, %xmm0
jne 0x61b37
jnp 0x61b4f
movapd %xmm0, %xmm2
maxsd %xmm6, %xmm2
addsd %xmm0, %xmm7
minsd %xmm5, %xmm0
movapd %xmm2, %xmm6
movapd %xmm0, %xmm5
incq %rax
jmp 0x61b1f
leaq 0x3180f(%rip), %rdi     # 0x9336a
xorl %ebp, %ebp
movq %r14, %rsi
xorl %eax, %eax
callq 0x681ca
jmp 0x61b82
leaq 0x38ac1(%rip), %rdi     # 0x9a631
jmp 0x61b79
leaq 0x38ae1(%rip), %rdi     # 0x9a65a
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x681ca
movl %ebp, %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x392b0(%rip), %rdi     # 0x9ae4d
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x681ca
jmp 0x61b82
cvtsi2sd %ecx, %xmm0
divsd %xmm0, %xmm7
xorpd %xmm0, %xmm0
xorl %eax, %eax
cmpq %rax, %r15
je 0x61bf0
movsd (%r13,%rax,8), %xmm2
movapd %xmm2, %xmm3
subsd %xmm7, %xmm3
mulsd %xmm3, %xmm3
addsd %xmm0, %xmm3
cmpeqsd %xmm1, %xmm2
movapd %xmm2, %xmm4
andnpd %xmm3, %xmm4
andpd %xmm0, %xmm2
orpd %xmm4, %xmm2
incq %rax
movapd %xmm2, %xmm0
jmp 0x61bb6
xorpd %xmm2, %xmm2
ucomisd %xmm2, %xmm0
jb 0x61c13
sqrtsd %xmm0, %xmm0
jmp 0x61c40
xorpd %xmm2, %xmm2
movsd 0x313fc(%rip), %xmm0    # 0x93008
movq 0x10(%rsp), %r13
jmp 0x61c83
movapd %xmm5, 0x20(%rsp)
movsd %xmm6, 0x38(%rsp)
movsd %xmm7, 0x30(%rsp)
callq 0xe350
movsd 0x30(%rsp), %xmm7
movsd 0x38(%rsp), %xmm6
movapd 0x20(%rsp), %xmm5
xorpd %xmm2, %xmm2
movsd 0x38380(%rip), %xmm1    # 0x99fc8
mulsd %xmm0, %xmm1
addsd %xmm7, %xmm1
maxsd %xmm1, %xmm5
mulsd 0x3157c(%rip), %xmm0    # 0x931d8
addsd %xmm7, %xmm0
minsd %xmm0, %xmm6
subsd %xmm5, %xmm6
ucomisd %xmm2, %xmm6
movsd 0x31394(%rip), %xmm0    # 0x93008
jbe 0x61c7a
divsd %xmm6, %xmm0
cmpltsd %xmm6, %xmm2
andpd %xmm5, %xmm2
movl $0x3, 0x8(%rbx)
movl %r12d, (%rbx)
movl %r14d, 0x4(%rbx)
leal (%r12,%r12,2), %ebp
testb $0x3, %bpl
movapd %xmm2, 0x10(%rsp)
movsd %xmm0, 0x20(%rsp)
je 0x61cb6
pushq $0x4
popq %rcx
movl %ebp, %eax
cltd
idivl %ecx
leal 0x4(,%rax,4), %ebp
movl %ebp, 0xc(%rbx)
imull %r14d, %ebp
movslq %ebp, %rdi
callq 0xe030
movq %rax, 0x10(%rbx)
xorl %eax, %eax
movsd 0x31545(%rip), %xmm0    # 0x93218
movq %r13, %rcx
movapd 0x10(%rsp), %xmm2
movsd 0x20(%rsp), %xmm3
movl $0xff, %r8d
cmpl %r14d, %eax
jge 0x61d49
movslq 0xc(%rbx), %rsi
movslq %eax, %rdx
imulq %rsi, %rdx
addq 0x10(%rbx), %rdx
xorl %esi, %esi
cmpl %r12d, %esi
jge 0x61d41
movsd (%rcx), %xmm1
subsd %xmm2, %xmm1
mulsd %xmm0, %xmm1
mulsd %xmm3, %xmm1
cvttsd2si %xmm1, %edi
testl %edi, %edi
jg 0x61d1d
xorl %edi, %edi
cmpl %r8d, %edi
jl 0x61d27
movl $0xff, %edi
addq $0x8, %rcx
movb %dil, (%rdx)
movb %dil, 0x1(%rdx)
movb %dil, 0x2(%rdx)
addq $0x3, %rdx
incl %esi
movl (%rbx), %r12d
jmp 0x61cfe
incl %eax
movl 0x4(%rbx), %r14d
jmp 0x61ce8
movq %r13, %rdi
callq 0xe5d0
jmp 0x61b82