// File: tomfunkhouser[P]gaps/pkgs/GSV/GSVImage.cpp
// Function: gaps::GSVImage::UndistortedImage() const
R2Image *GSVImage::
UndistortedImage(void) const
{
  // Get convenient variables
  int image_index = PanoramaIndex();
  GSVPanorama *panorama = Panorama();
  if (!panorama) return NULL;
  int panorama_index = panorama->RunIndex();
  GSVSegment *segment = panorama->Segment();
  if (!segment) return NULL;
  int segment_index = segment->RunIndex();
  GSVRun *run = segment->Run();
  if (!run) return NULL;
  char run_name[1024];
  if (run->Name()) sprintf(run_name, "%s", run->Name());
  else sprintf(run_name, "Run%d", run->SceneIndex());
  GSVScene *scene = run->Scene();
  if (!scene) return NULL;
  GSVCamera *camera = Camera();
  if (!camera) return NULL;
  R2Image *undistorted_image = NULL;
  
  // Construct undistorted image name
  if (scene->CacheDataDirectoryName()) {
    // Get cached undistorted image name
    char undistorted_image_name[4096];
    sprintf(undistorted_image_name, "%s/undistorted_images/%s/%02d_%06d_%02d_UndistortedImage.jpg", 
      scene->CacheDataDirectoryName(), run_name, segment_index, panorama_index, image_index);

    // Check if undistorted image file exists
    if (RNFileExists(undistorted_image_name)) { 
      // Allocate undistorted image
      undistorted_image = new R2Image();
      if (!undistorted_image) {
        RNFail("Unable to allocate image for %s\n", undistorted_image_name);
        return NULL;
      }

      // Read undistorted image
      if (!undistorted_image->Read(undistorted_image_name)) {
        RNFail("Unable to read undistorted image %s\n", undistorted_image_name);
        delete undistorted_image;
        return NULL;
      }
    }
  }

  // If did not read from cache ...
  if (!undistorted_image) {
    // Get distorted image
    R2Image *distorted_image = DistortedImage();
    if (!distorted_image) return NULL;

    // Allocate undistorted image with same resolution
    undistorted_image = new R2Image(distorted_image->Width(), distorted_image->Height());
    if (!undistorted_image) {
      RNFail("Unable to allocate undistorted image\n");
      return NULL;
    }

    // Undistort image
    if (!camera->UndistortImage(*distorted_image, *undistorted_image)) {
      RNFail("Unable to undistort image\n");
      delete undistorted_image;
      return NULL;
    }

    // Write undistorted image
    if (scene->CacheDataDirectoryName()) {
      if (scene->CreateCacheDataDirectory("undistorted_images", run)) {
        char undistorted_image_name[4096];
        sprintf(undistorted_image_name, "%s/undistorted_images/%s/%02d_%06d_%02d_UndistortedImage.jpg", 
          scene->CacheDataDirectoryName(), run_name, segment_index, panorama_index, image_index);
        if (!undistorted_image->Write(undistorted_image_name)) {
          RNFail("Unable to write undistorted image for %s\n", undistorted_image_name);
        }
      }
    }

    // Delete distorted image
    delete distorted_image;
  }

  // Return undistorted image
  return undistorted_image;
}

// Assembly:
subq $0x24f8, %rsp           # imm = 0x24F8
movq %rdi, 0x24e8(%rsp)
movq 0x24e8(%rsp), %rdi
movq %rdi, 0x68(%rsp)
callq 0x51890
movq 0x68(%rsp), %rdi
movl %eax, 0x24e4(%rsp)
callq 0x518a0
movq %rax, 0x24d8(%rsp)
cmpq $0x0, 0x24d8(%rsp)
jne 0x50086
movq $0x0, 0x24f0(%rsp)
jmp 0x505ac
movq 0x24d8(%rsp), %rdi
callq 0x4e7b0
movl %eax, 0x24d4(%rsp)
movq 0x24d8(%rsp), %rdi
callq 0x47d30
movq %rax, 0x24c8(%rsp)
cmpq $0x0, 0x24c8(%rsp)
jne 0x500cb
movq $0x0, 0x24f0(%rsp)
jmp 0x505ac
movq 0x24c8(%rsp), %rdi
callq 0x4a640
movl %eax, 0x24c4(%rsp)
movq 0x24c8(%rsp), %rdi
callq 0x4f380
movq %rax, 0x24b8(%rsp)
cmpq $0x0, 0x24b8(%rsp)
jne 0x50110
movq $0x0, 0x24f0(%rsp)
jmp 0x505ac
movq 0x24b8(%rsp), %rdi
callq 0x44310
cmpq $0x0, %rax
je 0x50155
leaq 0x20b0(%rsp), %rax
movq %rax, 0x60(%rsp)
movq 0x24b8(%rsp), %rdi
callq 0x44310
movq 0x60(%rsp), %rdi
movq %rax, %rdx
leaq 0x2300db(%rip), %rsi    # 0x280227
movb $0x0, %al
callq 0x2a280
jmp 0x50184
leaq 0x20b0(%rsp), %rax
movq %rax, 0x58(%rsp)
movq 0x24b8(%rsp), %rdi
callq 0x443f0
movq 0x58(%rsp), %rdi
movl %eax, %edx
leaq 0x2169d2(%rip), %rsi    # 0x266b4f
movb $0x0, %al
callq 0x2a280
movq 0x24b8(%rsp), %rdi
callq 0x4a630
movq %rax, 0x20a8(%rsp)
cmpq $0x0, 0x20a8(%rsp)
jne 0x501b5
movq $0x0, 0x24f0(%rsp)
jmp 0x505ac
movq 0x68(%rsp), %rdi
callq 0x4f700
movq %rax, 0x20a0(%rsp)
cmpq $0x0, 0x20a0(%rsp)
jne 0x501e3
movq $0x0, 0x24f0(%rsp)
jmp 0x505ac
movq $0x0, 0x2098(%rsp)
movq 0x20a8(%rsp), %rdi
callq 0x518e0
cmpq $0x0, %rax
je 0x50362
leaq 0x1090(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x20a8(%rsp), %rdi
callq 0x518e0
movq 0x50(%rsp), %rdi
movq %rax, %rdx
leaq 0x20b0(%rsp), %rcx
movl 0x24c4(%rsp), %r8d
movl 0x24d4(%rsp), %r9d
movl 0x24e4(%rsp), %eax
leaq 0x216eb3(%rip), %rsi    # 0x267101
movl %eax, (%rsp)
movb $0x0, %al
callq 0x2a280
leaq 0x1090(%rsp), %rdi
callq 0x1cadd0
cmpl $0x0, %eax
je 0x50360
movl $0x18, %edi
callq 0x292e0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x48(%rsp)
callq 0x1bb3c0
jmp 0x5028a
movq 0x48(%rsp), %rax
movq %rax, 0x2098(%rsp)
cmpq $0x0, 0x2098(%rsp)
jne 0x502f1
leaq 0x1090(%rsp), %rsi
leaq 0x216e0c(%rip), %rdi    # 0x2670bd
movb $0x0, %al
callq 0x1cbff0
movq $0x0, 0x24f0(%rsp)
jmp 0x505ac
movq 0x48(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1088(%rsp)
movl %eax, 0x1084(%rsp)
movl $0x18, %esi
callq 0x291f0
jmp 0x505bc
movq 0x2098(%rsp), %rdi
leaq 0x1090(%rsp), %rsi
callq 0x518b0
cmpl $0x0, %eax
jne 0x5035e
leaq 0x1090(%rsp), %rsi
leaq 0x216e24(%rip), %rdi    # 0x26713e
movb $0x0, %al
callq 0x1cbff0
movq 0x2098(%rsp), %rax
movq %rax, 0x40(%rsp)
cmpq $0x0, %rax
je 0x5034d
movq 0x40(%rsp), %rdi
callq 0x1bbe10
movq 0x40(%rsp), %rdi
movl $0x18, %esi
callq 0x291f0
movq $0x0, 0x24f0(%rsp)
jmp 0x505ac
jmp 0x50360
jmp 0x50362
cmpq $0x0, 0x2098(%rsp)
jne 0x5059c
movq 0x68(%rsp), %rdi
callq 0x4fd40
movq %rax, 0x1078(%rsp)
cmpq $0x0, 0x1078(%rsp)
jne 0x5039f
movq $0x0, 0x24f0(%rsp)
jmp 0x505ac
movl $0x18, %edi
callq 0x292e0
movq %rax, 0x30(%rsp)
movq 0x1078(%rsp), %rdi
callq 0x39d10
movl %eax, 0x3c(%rsp)
jmp 0x503c1
movq 0x1078(%rsp), %rdi
callq 0x39d20
movl %eax, 0x2c(%rsp)
jmp 0x503d4
movl 0x2c(%rsp), %edx
movl 0x3c(%rsp), %esi
movq 0x30(%rsp), %rdi
movl $0x3, %ecx
callq 0x1bb8f0
jmp 0x503ed
movq 0x30(%rsp), %rax
movq %rax, 0x2098(%rsp)
cmpq $0x0, 0x2098(%rsp)
jne 0x5044c
leaq 0x216d57(%rip), %rdi    # 0x267163
movb $0x0, %al
callq 0x1cbff0
movq $0x0, 0x24f0(%rsp)
jmp 0x505ac
movq 0x30(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1088(%rsp)
movl %eax, 0x1084(%rsp)
movl $0x18, %esi
callq 0x291f0
jmp 0x505bc
movq 0x20a0(%rsp), %rdi
movq 0x1078(%rsp), %rsi
movq 0x2098(%rsp), %rdx
callq 0x4d5c0
cmpl $0x0, %eax
jne 0x504b9
leaq 0x216d14(%rip), %rdi    # 0x267189
movb $0x0, %al
callq 0x1cbff0
movq 0x2098(%rsp), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, %rax
je 0x504a8
movq 0x20(%rsp), %rdi
callq 0x1bbe10
movq 0x20(%rsp), %rdi
movl $0x18, %esi
callq 0x291f0
movq $0x0, 0x24f0(%rsp)
jmp 0x505ac
movq 0x20a8(%rsp), %rdi
callq 0x518e0
cmpq $0x0, %rax
je 0x5056e
movq 0x20a8(%rsp), %rdi
movq 0x24b8(%rsp), %rdx
leaq 0x216cbd(%rip), %rsi    # 0x2671a4
callq 0x3baa0
cmpl $0x0, %eax
je 0x5056c
leaq 0x70(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x20a8(%rsp), %rdi
callq 0x518e0
movq 0x18(%rsp), %rdi
movq %rax, %rdx
leaq 0x20b0(%rsp), %rcx
movl 0x24c4(%rsp), %r8d
movl 0x24d4(%rsp), %r9d
movl 0x24e4(%rsp), %eax
leaq 0x216bcb(%rip), %rsi    # 0x267101
movl %eax, (%rsp)
movb $0x0, %al
callq 0x2a280
movq 0x2098(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x518f0
cmpl $0x0, %eax
jne 0x5056a
leaq 0x70(%rsp), %rsi
leaq 0x216c54(%rip), %rdi    # 0x2671b7
movb $0x0, %al
callq 0x1cbff0
jmp 0x5056c
jmp 0x5056e
movq 0x1078(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x5059a
movq 0x10(%rsp), %rdi
callq 0x1bbe10
movq 0x10(%rsp), %rdi
movl $0x18, %esi
callq 0x291f0
jmp 0x5059c
movq 0x2098(%rsp), %rax
movq %rax, 0x24f0(%rsp)
movq 0x24f0(%rsp), %rax
addq $0x24f8, %rsp           # imm = 0x24F8
retq
movq 0x1088(%rsp), %rdi
callq 0x29c10
nopl (%rax)