// File: /workspace/github_cpp_makefile_star2_O2/srajangarg[P]image-morph/src/morph.cpp
// Function: distortImage(Image const&, std::vector<LineSegment, std::allocator<LineSegment>> const&, std::vector<LineSegment, std::allocator<LineSegment>> const&, double, double, double, double)
Image
distortImage(Image const & image,
             std::vector<LineSegment> const & seg_start,
             std::vector<LineSegment> const & seg_end,
             double t,
             double a, double b, double p)
{
  assert(seg_start.size() == seg_end.size());

  std::cout << "Distorting image..." << std::endl;

  int w = image.width();
  int h = image.height();
  int n = image.numChannels();
  
  Image result(w, h, n);
  Vec2 interpolated, dis, dissum, curr;
  LineSegment start_ln, end_ln;

  unsigned char sample[4];
  unsigned char* pix;
  double u, v, wt, wtsum;

  for (int row = 0; row < h; ++row)
  {
    for (int col = 0; col < w; ++col)
    {
      wtsum = 0;
      dissum = Vec2(0, 0);
      curr = Vec2(col, row);

      for (unsigned int i = 0; i < seg_start.size(); ++i)
      { 
        // src line
        start_ln = seg_start[i];
        // final line
        end_ln = start_ln.lerp(seg_end[i], t);

        u = end_ln.lineParameter(curr);
        v = end_ln.signedLineDistance(curr);

        // point interpolated wrt to the src line
        interpolated = start_ln.start() + u * (start_ln.direction())
                     + v * (start_ln.perp() / start_ln.length());

        // displacement vector from the line
        dis = (interpolated - curr);
        // weight of this displacement
        wt = pow(pow(start_ln.length(), p)/(a + start_ln.segmentDistance(curr, u, v)), b);
        dissum += dis * wt;
        wtsum += wt;
      }

      // weighted average
      interpolated = curr + (dissum/wtsum);
      sampleBilinear(image, interpolated, sample);

      // fill in the interpolated color
      pix = result.pixel(row, col);
      for (int channel = 0; channel < n; ++channel)
        pix[channel] = sample[channel];
    }
  }

  return result;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x148, %rsp            # imm = 0x148
movsd %xmm3, 0x80(%rsp)
movsd %xmm2, 0x78(%rsp)
movsd %xmm1, 0x70(%rsp)
movsd %xmm0, 0x90(%rsp)
movq %rdx, %r15
movq 0x8(%rdx), %rax
subq (%rdx), %rax
movq 0x8(%rcx), %rdx
movq %rcx, 0x88(%rsp)
subq (%rcx), %rdx
cmpq %rdx, %rax
jne 0x2f11
movq %rsi, %r13
movq %rdi, %rbx
movq 0x123d0(%rip), %rdi     # 0x14fd0
leaq 0xc570(%rip), %rsi      # 0xf177
callq 0x21f0
movq %rax, %rdi
callq 0x2110
movl (%r13), %ebp
movl 0x4(%r13), %r14d
movl 0x8(%r13), %r12d
movq %rbx, 0x8(%rsp)
movq %rbx, %rdi
movl %ebp, %esi
movl %r14d, %edx
movl %r12d, %ecx
callq 0x25ce
movq %r12, %rsi
xorl %edi, %edi
testl %esi, %esi
cmovlel %edi, %esi
testl %ebp, %ebp
cmovlel %edi, %ebp
movl %ebp, 0x14(%rsp)
testl %r14d, %r14d
cmovlel %edi, %r14d
movl %r14d, 0x10(%rsp)
leaq 0xe0(%rsp), %r12
leaq 0x20(%rsp), %r14
movq %r13, 0x58(%rsp)
movq %rsi, 0x50(%rsp)
cmpl 0x10(%rsp), %edi
je 0x2efa
cvtsi2sd %edi, %xmm0
movsd %xmm0, 0x68(%rsp)
xorl %r8d, %r8d
movq %rdi, 0x60(%rsp)
cmpl 0x14(%rsp), %r8d
je 0x2ef3
movl %r8d, 0x18(%rsp)
cvtsi2sd %r8d, %xmm0
movsd %xmm0, 0x20(%rsp)
movsd 0x68(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
xorpd %xmm1, %xmm1
xorl %ebp, %ebp
xorpd %xmm2, %xmm2
movl %ebp, %ebp
movq (%r15), %rsi
movq 0x8(%r15), %rax
subq %rsi, %rax
sarq $0x5, %rax
cmpq %rbp, %rax
jbe 0x2e78
movsd %xmm2, 0x98(%rsp)
movapd %xmm1, 0xc0(%rsp)
movq %rbp, %r13
shlq $0x5, %r13
addq %r13, %rsi
movq %r12, %rdi
callq 0x3a90
movq 0x88(%rsp), %rax
addq (%rax), %r13
leaq 0x128(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
movq %r13, %rdx
movsd 0x90(%rsp), %xmm0
callq 0x3aba
leaq 0x108(%rsp), %r13
movq %r13, %rdi
movq %rbx, %rsi
callq 0x3b06
movq %r13, %rdi
movq %r14, %rsi
callq 0x3b30
movapd %xmm0, 0xb0(%rsp)
leaq 0x108(%rsp), %rdi
movq %r14, %rsi
callq 0x3b82
movapd %xmm0, 0xa0(%rsp)
movaps 0xe0(%rsp), %xmm0
movaps %xmm0, 0x30(%rsp)
movapd 0xf0(%rsp), %xmm0
movapd %xmm0, 0x40(%rsp)
movq %r12, %rdi
callq 0x3bd4
movapd 0x40(%rsp), %xmm3
movapd 0x30(%rsp), %xmm4
subpd %xmm4, %xmm3
movapd %xmm3, %xmm1
unpckhpd %xmm3, %xmm1            # xmm1 = xmm1[1],xmm3[1]
xorpd 0xc30d(%rip), %xmm1     # 0xf0b0
movsd 0xc2e5(%rip), %xmm2     # 0xf090
divsd %xmm0, %xmm2
movapd 0xb0(%rsp), %xmm0
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
mulpd %xmm3, %xmm0
addpd %xmm4, %xmm0
unpcklpd %xmm2, %xmm2            # xmm2 = xmm2[0,0]
unpcklpd %xmm3, %xmm1            # xmm1 = xmm1[0],xmm3[0]
mulpd %xmm2, %xmm1
movapd 0xa0(%rsp), %xmm2
unpcklpd %xmm2, %xmm2            # xmm2 = xmm2[0,0]
mulpd %xmm1, %xmm2
addpd %xmm0, %xmm2
subpd 0x20(%rsp), %xmm2
movapd %xmm2, 0x40(%rsp)
movq %r12, %rdi
callq 0x3bd4
movsd 0x80(%rsp), %xmm1
callq 0x23e0
movsd %xmm0, 0x30(%rsp)
movq %r12, %rdi
movq %r14, %rsi
movapd 0xb0(%rsp), %xmm0
movapd 0xa0(%rsp), %xmm1
callq 0x3bf0
addsd 0x70(%rsp), %xmm0
movsd 0x30(%rsp), %xmm1
divsd %xmm0, %xmm1
movapd %xmm1, %xmm0
movsd 0x78(%rsp), %xmm1
callq 0x23e0
movsd 0x98(%rsp), %xmm2
addsd %xmm0, %xmm2
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
movapd 0x40(%rsp), %xmm3
mulpd %xmm0, %xmm3
movapd 0xc0(%rsp), %xmm1
addpd %xmm3, %xmm1
incl %ebp
jmp 0x2cb8
movsd 0xc210(%rip), %xmm0     # 0xf090
divsd %xmm2, %xmm0
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
mulpd %xmm0, %xmm1
addpd 0x20(%rsp), %xmm1
movapd %xmm1, 0xd0(%rsp)
movq 0x58(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
leaq 0x1c(%rsp), %rdx
callq 0x29a0
movq 0x8(%rsp), %rcx
movl (%rcx), %eax
movq 0x60(%rsp), %rdi
imull %edi, %eax
movl 0x18(%rsp), %r8d
addl %r8d, %eax
imull 0x8(%rcx), %eax
cltq
addq 0x10(%rcx), %rax
xorl %ecx, %ecx
movq 0x50(%rsp), %rsi
cmpq %rcx, %rsi
je 0x2eeb
movb 0x1c(%rsp,%rcx), %dl
movb %dl, (%rax,%rcx)
incq %rcx
jmp 0x2eda
incl %r8d
jmp 0x2c87
incl %edi
jmp 0x2c6b
movq 0x8(%rsp), %rax
addq $0x148, %rsp            # imm = 0x148
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xc1a8(%rip), %rdi      # 0xf0c0
leaq 0xc1c4(%rip), %rsi      # 0xf0e3
leaq 0xc1cb(%rip), %rcx      # 0xf0f1
pushq $0x79
popq %rdx
callq 0x2150
jmp 0x2f32
jmp 0x2f32
movq %rax, %rbx
movq 0x8(%rsp), %rdi
callq 0x27b4
movq %rbx, %rdi
callq 0x23f0