// File: /workspace/github_cpp_makefile_star2_O3/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 0x37df5(%rip), %rsi     # 0xa25ab
movq %r14, %rdi
callq 0xe530
testq %rax, %rax
je 0x6a91e
movq %rax, %r13
leaq 0x8(%rsp), %rdi
movl $0x4, %esi
movl $0x2, %edx
movq %rax, %rcx
callq 0xe6c0
cmpq $0x2, %rax
jne 0x6a934
leaq 0x40(%rsp), %rdi
movl $0x8, %esi
movl $0x9, %edx
movq %r13, %rcx
callq 0xe6c0
cmpq $0x9, %rax
jne 0x6a93d
movl 0x8(%rsp), %ebp
movl 0xc(%rsp), %eax
movl %eax, 0x10(%rsp)
movl %eax, %r12d
imull %ebp, %r12d
movslq %r12d, %r15
leaq (,%r15,8), %rax
testl %r15d, %r15d
movq $-0x1, %rdi
cmovnsq %rax, %rdi
callq 0xe030
movq %rax, %r14
movl $0x8, %esi
movq %rax, %rdi
movq %r15, %rdx
movq %r13, %rcx
callq 0xe6c0
cmpq %r12, %rax
jne 0x6a963
movq %rax, %r15
movq %r13, %rdi
callq 0xe430
movq %r12, %rcx
testl %ecx, %ecx
jle 0x6a979
movsd 0x3843e(%rip), %xmm6    # 0xa2cb8
movsd 0x377be(%rip), %xmm5    # 0xa2040
xorpd %xmm7, %xmm7
xorl %eax, %eax
movsd 0x38728(%rip), %xmm1    # 0xa2fb8
movl 0x10(%rsp), %r12d
movsd (%r14,%rax,8), %xmm0
ucomisd %xmm1, %xmm0
jne 0x6a8a3
jnp 0x6a8bb
movapd %xmm0, %xmm2
maxsd %xmm6, %xmm2
addsd %xmm0, %xmm7
minsd %xmm5, %xmm0
movapd %xmm2, %xmm6
movapd %xmm0, %xmm5
incq %rax
cmpq %rax, %r15
jne 0x6a895
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
divsd %xmm0, %xmm7
xorpd %xmm0, %xmm0
xorl %eax, %eax
movsd (%r14,%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
movapd %xmm2, %xmm0
incq %rax
cmpq %rax, %r15
jne 0x6a8d4
xorpd %xmm2, %xmm2
ucomisd %xmm2, %xmm0
jb 0x6a98c
sqrtsd %xmm0, %xmm0
jmp 0x6a9b9
leaq 0x37a95(%rip), %rdi     # 0xa23ba
xorl %r15d, %r15d
movq %r14, %rsi
xorl %eax, %eax
callq 0x719d2
jmp 0x6a94e
leaq 0x3ed66(%rip), %rdi     # 0xa96a1
jmp 0x6a944
leaq 0x3ed86(%rip), %rdi     # 0xa96ca
xorl %r15d, %r15d
xorl %eax, %eax
callq 0x719d2
movl %r15d, %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3f563(%rip), %rdi     # 0xa9ecd
xorl %r15d, %r15d
movl %r12d, %esi
xorl %eax, %eax
callq 0x719d2
jmp 0x6a94e
xorpd %xmm2, %xmm2
movsd 0x376b3(%rip), %xmm0    # 0xa2038
movl 0x10(%rsp), %r12d
jmp 0x6a9fc
movapd %xmm5, 0x20(%rsp)
movsd %xmm6, 0x38(%rsp)
movsd %xmm7, 0x30(%rsp)
callq 0xe340
movsd 0x30(%rsp), %xmm7
movsd 0x38(%rsp), %xmm6
movapd 0x20(%rsp), %xmm5
xorpd %xmm2, %xmm2
movsd 0x3e657(%rip), %xmm1    # 0xa9018
mulsd %xmm0, %xmm1
addsd %xmm7, %xmm1
maxsd %xmm1, %xmm5
mulsd 0x37803(%rip), %xmm0    # 0xa21d8
addsd %xmm7, %xmm0
minsd %xmm0, %xmm6
subsd %xmm5, %xmm6
ucomisd %xmm2, %xmm6
movsd 0x3764b(%rip), %xmm0    # 0xa2038
jbe 0x6a9f3
divsd %xmm6, %xmm0
cmpltsd %xmm6, %xmm2
andpd %xmm5, %xmm2
movl $0x3, 0x8(%rbx)
movl %ebp, (%rbx)
movl %r12d, 0x4(%rbx)
leal (%rbp,%rbp,2), %r15d
testb $0x3, %r15b
movapd %xmm2, 0x10(%rsp)
movsd %xmm0, 0x20(%rsp)
je 0x6aa34
leal 0x3(%r15), %eax
testl %r15d, %r15d
cmovnsl %r15d, %eax
andl $-0x4, %eax
addl $0x4, %eax
movl %eax, %r15d
movl %r15d, 0xc(%rbx)
imull %r12d, %r15d
movslq %r15d, %rdi
callq 0xe030
movq %rax, 0x10(%rbx)
testl %r12d, %r12d
movapd 0x10(%rsp), %xmm2
movsd 0x20(%rsp), %xmm3
jle 0x6aacb
xorl %eax, %eax
movsd 0x377b5(%rip), %xmm0    # 0xa2218
movq %r14, %rcx
movl $0xff, %r8d
testl %ebp, %ebp
jle 0x6aac4
movslq 0xc(%rbx), %rsi
movslq %eax, %rdx
imulq %rsi, %rdx
addq 0x10(%rbx), %rdx
xorl %esi, %esi
movsd (%rcx), %xmm1
subsd %xmm2, %xmm1
mulsd %xmm0, %xmm1
mulsd %xmm3, %xmm1
cvttsd2si %xmm1, %edi
testl %edi, %edi
jg 0x6aa9b
xorl %edi, %edi
cmpl %r8d, %edi
jl 0x6aaa5
movl $0xff, %edi
addq $0x8, %rcx
movb %dil, (%rdx)
movb %dil, 0x1(%rdx)
movb %dil, 0x2(%rdx)
addq $0x3, %rdx
incl %esi
movl (%rbx), %ebp
cmpl %ebp, %esi
jl 0x6aa81
movl 0x4(%rbx), %r12d
incl %eax
cmpl %r12d, %eax
jl 0x6aa6c
movq %r14, %rdi
callq 0xe5b0
jmp 0x6a94e