// File: /workspace/github_cpp_makefile_star2_O1/tomfunkhouser[P]gaps/pkgs/RGBD/RGBDUtil.cpp
// Function: gaps::RGBDCreateBoundaryChannel(gaps::R2Grid const&, gaps::R2Grid&, double)
int RGBDCreateBoundaryChannel(
  const R2Grid& input_depth_image, R2Grid& output_boundary_image,
  RNScalar depth_threshold)
{
  // Initialize position images
  output_boundary_image = input_depth_image; 
  output_boundary_image.Clear(R2_GRID_UNKNOWN_VALUE);

  // Mark bottom and top border boundaries
  for (int i = 0; i < output_boundary_image.XResolution(); i++) {
    for (int j = 0; j < output_boundary_image.YResolution(); j++) {
      output_boundary_image.SetGridValue(i, j, RGBD_BORDER_BOUNDARY);
      if (RNIsPositive(input_depth_image.GridValue(i, j))) break;
    }
    for (int j = output_boundary_image.YResolution()-1; j >= 0; j--) {
      output_boundary_image.SetGridValue(i, j, RGBD_BORDER_BOUNDARY);
      if (RNIsPositive(input_depth_image.GridValue(i, j))) break;
    }
  }

  // Mark left and right border boundaries
  for (int j = 0; j < output_boundary_image.YResolution(); j++) {
    for (int i = 0; i < output_boundary_image.XResolution(); i++) {
      output_boundary_image.SetGridValue(i, j, RGBD_BORDER_BOUNDARY);
      if (RNIsPositive(input_depth_image.GridValue(i, j))) break;
    }
    for (int i = output_boundary_image.XResolution()-1; i >= 0; i--) {
      output_boundary_image.SetGridValue(i, j, RGBD_BORDER_BOUNDARY);
      if (RNIsPositive(input_depth_image.GridValue(i, j))) break;
    }
  }

  // Create copy of depth image with holes filled
  R2Grid filled_input_depth_image(input_depth_image);
  filled_input_depth_image.Substitute(0, R2_GRID_UNKNOWN_VALUE);
  filled_input_depth_image.FillHoles();

  // Mark interior boundaries, silhouettes, and shadows
  for (int i = 1; i < output_boundary_image.XResolution()-1; i++) {
    for (int j = 1; j < output_boundary_image.YResolution()-1; j++) {
      // Get original depth
      RNScalar depth = input_depth_image.GridValue(i, j);

      // Check if in hole
      if (RNIsNegativeOrZero(depth)) {
        output_boundary_image.SetGridValue(i, j, RGBD_BORDER_BOUNDARY);
        continue;
      }

      // Get filled depth
      depth = filled_input_depth_image.GridValue(i, j);
      if (RNIsNegativeOrZero(depth)) continue;

      // Check depth relative to neighbors
      for (int k = 0; k < 4; k++) {
        int s = (k < 3) ? -1 : 0;
        int t = (k < 3) ? k-1 : -1;

        // Get depth on one side
        RNScalar depthA = filled_input_depth_image.GridValue(i-s, j-t);
        if (RNIsNegativeOrZero(depthA)) {
          output_boundary_image.SetGridValue(i, j, RGBD_BORDER_BOUNDARY);
          break;
        }

        // Get depth on other side
        RNScalar depthB = filled_input_depth_image.GridValue(i+s, j+t);
        if (RNIsNegativeOrZero(depthB)) {
          output_boundary_image.SetGridValue(i, j, RGBD_BORDER_BOUNDARY);
          break;
        }

        // Check differences of depth for shadow/silhouette
        RNScalar deltaA = depth - depthA;
        RNScalar deltaB = depthB - depth;
        RNScalar threshold = depth * depth_threshold;
        if (threshold < 0.1) threshold = 0.1;
        if (deltaA < -threshold) {
          if (deltaA < 4*deltaB) {
            output_boundary_image.SetGridValue(i-s, j-t, RGBD_SHADOW_BOUNDARY);
            output_boundary_image.SetGridValue(i, j, RGBD_SILHOUETTE_BOUNDARY);
          }
        }
        else if (deltaA > threshold) {
          if (deltaA > 4*deltaB) {
            output_boundary_image.SetGridValue(i-s, j-t, RGBD_SILHOUETTE_BOUNDARY);
            output_boundary_image.SetGridValue(i, j, RGBD_SHADOW_BOUNDARY);
          }
        }
        if (deltaB < -threshold) {
          if (deltaB < 4*deltaA) {
            output_boundary_image.SetGridValue(i+s, j+t, RGBD_SILHOUETTE_BOUNDARY);
            output_boundary_image.SetGridValue(i, j, RGBD_SHADOW_BOUNDARY);
          }
        }
        else if (deltaB > threshold) {
          if (deltaB > 4*deltaA) {
            output_boundary_image.SetGridValue(i+s, j+t, RGBD_SHADOW_BOUNDARY);
            output_boundary_image.SetGridValue(i, j, RGBD_SILHOUETTE_BOUNDARY);
          }
        }
      }
    }
  }

  // Return success 
  return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x138, %rsp            # imm = 0x138
movsd %xmm0, 0x38(%rsp)
movq %rsi, %rbx
movq %rdi, %rsi
movq %rbx, %rdi
movq %rsi, (%rsp)
callq 0x60d3c
movsd 0x9b360(%rip), %xmm0    # 0xbd018
movq %rbx, %rdi
callq 0x62582
movq %rbx, 0x8(%rsp)
movslq 0xc0(%rbx), %rax
movabsq $0x3ff0000000000000, %rbp # imm = 0x3FF0000000000000
testq %rax, %rax
jle 0x21dfb
movq 0x8(%rsp), %rsi
movslq 0xc4(%rsi), %rcx
movq 0xb8(%rsi), %rdx
movslq 0xc8(%rsi), %rsi
movq (%rsp), %r8
movq 0xb8(%r8), %rdi
movslq 0xc8(%r8), %r8
shlq $0x3, %rsi
shlq $0x3, %r8
leaq 0x1(%rcx), %r9
movq %r9, 0x10(%rsp)
leaq -0x8(,%rcx,8), %r9
movq %r9, 0x20(%rsp)
xorl %r11d, %r11d
leaq 0xe4fb5(%rip), %rbx     # 0x106ce8
xorl %r15d, %r15d
testl %ecx, %ecx
jle 0x21d68
movl $0x1, %r10d
movq %rdi, %r12
movq %rdx, %r13
movq %rbp, (%r13)
movsd (%r12), %xmm0
ucomisd (%rbx), %xmm0
ja 0x21d68
addq %rsi, %r13
addq %r8, %r12
leaq 0x1(%r10), %r14
cmpq %rcx, %r10
movq %r14, %r10
jl 0x21d46
movq 0x8(%rsp), %r14
movslq 0xc8(%r14), %r12
movq (%rsp), %r9
movslq 0xc8(%r9), %r13
movq 0x20(%rsp), %r10
movq %r10, %rbp
imulq %r13, %rbp
addq %r11, %rbp
addq 0xb8(%r9), %rbp
shlq $0x3, %r13
imulq %r12, %r10
addq %r11, %r10
addq 0xb8(%r14), %r10
negq %r13
shlq $0x3, %r12
negq %r12
movq 0x10(%rsp), %r14
decq %r14
jle 0x21dd9
movabsq $0x3ff0000000000000, %r9 # imm = 0x3FF0000000000000
movq %r9, (%r10)
addq %r12, %r10
movsd (%rbp), %xmm0
addq %r13, %rbp
ucomisd (%rbx), %xmm0
jbe 0x21db6
incq %r15
addq $0x8, %rdx
addq $0x8, %rdi
addq $0x8, %r11
cmpq %rax, %r15
movabsq $0x3ff0000000000000, %rbp # imm = 0x3FF0000000000000
jne 0x21d36
movq 0x8(%rsp), %rcx
movslq 0xc4(%rcx), %rcx
testq %rcx, %rcx
jle 0x21ee0
movq 0x8(%rsp), %rsi
movq 0xb8(%rsi), %rdx
movslq 0xc8(%rsi), %rsi
movq (%rsp), %r8
movq 0xb8(%r8), %rdi
movslq 0xc8(%r8), %r8
shlq $0x3, %r8
shlq $0x3, %rsi
xorl %r9d, %r9d
leaq 0xe4ea1(%rip), %r10     # 0x106ce8
xorl %r11d, %r11d
testl %eax, %eax
jle 0x21e71
movl $0x1, %ebx
movq %rbp, -0x8(%rdx,%rbx,8)
movsd -0x8(%rdi,%rbx,8), %xmm0
ucomisd (%r10), %xmm0
ja 0x21e71
leaq 0x1(%rbx), %r14
cmpq %rax, %rbx
movq %r14, %rbx
jl 0x21e53
movq 0x8(%rsp), %rbx
movq 0xb8(%rbx), %r14
movslq 0xc8(%rbx), %r15
movq (%rsp), %r12
movq 0xb8(%r12), %rbx
movslq 0xc8(%r12), %r12
imulq %r9, %r12
addq %r12, %rbx
addq $-0x8, %rbx
imulq %r9, %r15
addq %r15, %r14
addq $-0x8, %r14
movq %rax, %r15
testq %r15, %r15
jle 0x21eca
movq %rbp, (%r14,%r15,8)
movsd (%rbx,%r15,8), %xmm0
decq %r15
ucomisd (%r10), %xmm0
jbe 0x21eb1
incq %r11
addq %r8, %rdi
addq %rsi, %rdx
addq $0x8, %r9
cmpq %rcx, %r11
jne 0x21e4a
leaq 0x68(%rsp), %r15
movq %r15, %rdi
movq (%rsp), %rsi
callq 0x60e18
movsd 0x9b11f(%rip), %xmm1    # 0xbd018
xorpd %xmm0, %xmm0
movq %r15, %rdi
callq 0x64d52
leaq 0x68(%rsp), %rdi
callq 0x61c08
movq 0x8(%rsp), %rax
movl 0xc0(%rax), %eax
movq %rax, 0x18(%rsp)
cmpl $0x3, %eax
jl 0x22269
movq 0x18(%rsp), %rax
decl %eax
movq %rax, 0x18(%rsp)
movq 0x8(%rsp), %rax
movl 0xc4(%rax), %eax
movq %rax, 0x30(%rsp)
decl %eax
movq %rax, 0x60(%rsp)
movq (%rsp), %rax
movq 0xb8(%rax), %rcx
movq %rcx, 0x28(%rsp)
movslq 0xc8(%rax), %rax
movq %rax, 0x58(%rsp)
movl $0x1, %r8d
movsd 0x9b093(%rip), %xmm0    # 0xbd008
movapd 0x9b0d3(%rip), %xmm1    # 0xbd050
movsd 0x9c10b(%rip), %xmm2    # 0xbe090
cmpl $0x3, 0x30(%rsp)
jl 0x2225b
movq 0x8(%rsp), %rax
movslq 0xc8(%rax), %rcx
movq %rcx, 0x50(%rsp)
movq 0x120(%rsp), %r13
movslq 0x130(%rsp), %rbp
movq 0x28(%rsp), %rcx
leaq (%rcx,%r8,8), %rcx
movq %rcx, 0x20(%rsp)
leaq (,%r8,8), %rcx
leaq (,%r8,8), %rdx
addq %r13, %rdx
movq %rdx, 0x40(%rsp)
addq 0xb8(%rax), %rcx
movq %rcx, 0x48(%rsp)
movl $0x1, %ebx
movq %rbx, %rax
imulq 0x58(%rsp), %rax
leaq 0xe4cf0(%rip), %rcx     # 0x106ce8
movsd (%rcx), %xmm4
movq 0x20(%rsp), %rcx
ucomisd (%rcx,%rax,8), %xmm4
jae 0x22231
movq %rbx, %rax
imulq %rbp, %rax
movq 0x40(%rsp), %rcx
movsd (%rcx,%rax,8), %xmm3
ucomisd %xmm3, %xmm4
jae 0x2224d
movq 0x8(%rsp), %rax
movq 0xb8(%rax), %rdx
movslq 0xc8(%rax), %rcx
movslq %ebx, %rax
movq %rcx, %r15
imulq %rax, %r15
movq %rdx, (%rsp)
leaq (%rdx,%r8,8), %rdx
movapd %xmm3, %xmm5
mulsd 0x38(%rsp), %xmm5
movapd %xmm0, %xmm4
maxsd %xmm5, %xmm4
movapd %xmm4, %xmm5
xorpd %xmm1, %xmm5
imull %ecx, %eax
cltq
movq %rax, 0x10(%rsp)
xorl %r14d, %r14d
movl $0x3, %r11d
leal -0x1(%r14), %esi
movl %r11d, %eax
addl $-0x1, %eax
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmovael %eax, %esi
movl %r8d, %r10d
adcl $0x0, %r10d
movl %ebx, %edi
subl %esi, %edi
movl %edi, %r9d
imull %ebp, %r9d
xorl %r12d, %r12d
addl $-0x1, %r11d
setb %al
adcl %r8d, %r9d
movslq %r9d, %r9
movsd (%r13,%r9,8), %xmm9
leaq 0xe4c2d(%rip), %r9      # 0x106ce8
movsd (%r9), %xmm6
ucomisd %xmm9, %xmm6
jae 0x22231
movb %al, %r12b
negl %r12d
addl %r8d, %r12d
addl %ebx, %esi
movl %esi, %eax
imull %ebp, %eax
addl %r12d, %eax
cltq
movsd (%r13,%rax,8), %xmm7
ucomisd %xmm7, %xmm6
jae 0x22144
movapd %xmm3, %xmm8
subsd %xmm9, %xmm8
movapd %xmm7, %xmm9
subsd %xmm3, %xmm9
ucomisd %xmm8, %xmm5
jbe 0x22157
movapd %xmm9, %xmm10
mulsd %xmm2, %xmm10
ucomisd %xmm8, %xmm10
jbe 0x2219d
imull %ecx, %edi
addl %r10d, %edi
movslq %edi, %rax
movabsq $0x4010000000000000, %rdi # imm = 0x4010000000000000
movq (%rsp), %r9
movq %rdi, (%r9,%rax,8)
movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000
jmp 0x22194
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, (%rdx,%r15,8)
jmp 0x22218
ucomisd %xmm4, %xmm8
movapd %xmm9, %xmm10
mulsd %xmm2, %xmm10
jbe 0x2219d
ucomisd %xmm10, %xmm8
jbe 0x2219d
imull %ecx, %edi
addl %r10d, %edi
movslq %edi, %rax
movabsq $0x4000000000000000, %rdi # imm = 0x4000000000000000
movq (%rsp), %r9
movq %rdi, (%r9,%rax,8)
movabsq $0x4010000000000000, %rax # imm = 0x4010000000000000
movq 0x10(%rsp), %rdi
movq %rax, (%rdx,%rdi,8)
ucomisd %xmm9, %xmm5
jbe 0x221d7
mulsd %xmm2, %xmm8
ucomisd %xmm9, %xmm8
jbe 0x22218
imull %ecx, %esi
addl %r12d, %esi
movslq %esi, %rax
movabsq $0x4000000000000000, %rsi # imm = 0x4000000000000000
movq (%rsp), %rdi
movq %rsi, (%rdi,%rax,8)
movabsq $0x4010000000000000, %rax # imm = 0x4010000000000000
jmp 0x2220f
ucomisd %xmm4, %xmm9
mulsd %xmm2, %xmm8
jbe 0x22218
ucomisd %xmm8, %xmm9
jbe 0x22218
imull %ecx, %esi
addl %r12d, %esi
movslq %esi, %rax
movabsq $0x4010000000000000, %rsi # imm = 0x4010000000000000
movq (%rsp), %rdi
movq %rsi, (%rdi,%rax,8)
movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000
movq 0x10(%rsp), %rsi
movq %rax, (%rdx,%rsi,8)
ucomisd %xmm7, %xmm6
jae 0x2224d
leal 0x1(%r14), %eax
cmpl $0x3, %r14d
movl %eax, %r14d
jb 0x22079
jmp 0x2224d
movq %rbx, %rax
imulq 0x50(%rsp), %rax
movabsq $0x3ff0000000000000, %rcx # imm = 0x3FF0000000000000
movq 0x48(%rsp), %rdx
movq %rcx, (%rdx,%rax,8)
incq %rbx
cmpq 0x60(%rsp), %rbx
jne 0x21fe8
incq %r8
cmpq 0x18(%rsp), %r8
jne 0x21f85
leaq 0x68(%rsp), %rdi
callq 0x60ff0
movl $0x1, %eax
addq $0x138, %rsp            # imm = 0x138
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x60ff0
movq %rbx, %rdi
callq 0x11a70