// File: 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
movq %rsp, %rbp
subq $0x290, %rsp            # imm = 0x290
movq %rdi, -0x230(%rbp)
movq %rdi, %rax
movq %rax, -0x228(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movsd %xmm0, -0x28(%rbp)
movsd %xmm1, -0x30(%rbp)
movsd %xmm2, -0x38(%rbp)
movsd %xmm3, -0x40(%rbp)
movq -0x18(%rbp), %rdi
callq 0x60c0
movq %rax, -0x220(%rbp)
movq -0x20(%rbp), %rdi
callq 0x60c0
movq %rax, %rcx
movq -0x220(%rbp), %rax
cmpq %rcx, %rax
jne 0x467a
jmp 0x4699
leaq 0x17a1f(%rip), %rdi     # 0x1c0a0
leaq 0x17a3b(%rip), %rsi     # 0x1c0c3
movl $0x79, %edx
leaq 0x17a3d(%rip), %rcx     # 0x1c0d1
callq 0x31e0
movq 0x1d928(%rip), %rdi     # 0x21fc8
leaq 0x17ab0(%rip), %rsi     # 0x1c157
callq 0x32c0
movq %rax, %rdi
movq 0x1d8fa(%rip), %rsi     # 0x21fb0
callq 0x3310
movq -0x10(%rbp), %rdi
callq 0x5f80
movl %eax, -0x44(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5f90
movl %eax, -0x48(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5fb0
movq -0x230(%rbp), %rdi
movl %eax, -0x4c(%rbp)
movb $0x0, -0x4d(%rbp)
movl -0x44(%rbp), %esi
movl -0x48(%rbp), %edx
movl -0x4c(%rbp), %ecx
callq 0x37e0
leaq -0x60(%rbp), %rdi
callq 0x60e0
jmp 0x4703
leaq -0x80(%rbp), %rdi
callq 0x60e0
jmp 0x470e
leaq -0x90(%rbp), %rdi
callq 0x60e0
jmp 0x471c
leaq -0xa0(%rbp), %rdi
callq 0x60e0
jmp 0x472a
leaq -0xc0(%rbp), %rdi
callq 0x60f0
jmp 0x4738
leaq -0xe0(%rbp), %rdi
callq 0x60f0
jmp 0x4746
movl $0x0, -0x114(%rbp)
movl -0x114(%rbp), %eax
cmpl -0x48(%rbp), %eax
jge 0x4c27
movl $0x0, -0x118(%rbp)
movl -0x118(%rbp), %eax
cmpl -0x44(%rbp), %eax
jge 0x4c11
movq $0x0, -0x110(%rbp)
leaq -0x128(%rbp), %rdi
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0x6140
jmp 0x4797
leaq -0x90(%rbp), %rdi
leaq -0x128(%rbp), %rsi
callq 0x6170
jmp 0x47ac
cvtsi2sdl -0x118(%rbp), %xmm0
cvtsi2sdl -0x114(%rbp), %xmm1
leaq -0x138(%rbp), %rdi
callq 0x6140
jmp 0x47ca
leaq -0xa0(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0x6170
jmp 0x47df
movl $0x0, -0x13c(%rbp)
movl -0x13c(%rbp), %eax
movq %rax, -0x238(%rbp)
movq -0x18(%rbp), %rdi
callq 0x60c0
movq %rax, %rcx
movq -0x238(%rbp), %rax
cmpq %rcx, %rax
jae 0x4b26
movq -0x18(%rbp), %rdi
movl -0x13c(%rbp), %eax
movl %eax, %esi
callq 0x61a0
movq %rax, %rsi
leaq -0xc0(%rbp), %rdi
callq 0x61c0
jmp 0x4834
movq -0x20(%rbp), %rdi
movl -0x13c(%rbp), %eax
movl %eax, %esi
callq 0x61a0
movq %rax, %rdx
movsd -0x28(%rbp), %xmm0
leaq -0x160(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x6230
jmp 0x4862
leaq -0xe0(%rbp), %rdi
leaq -0x160(%rbp), %rsi
callq 0x6370
jmp 0x4877
leaq -0xe0(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x63e0
movsd %xmm0, -0x240(%rbp)
jmp 0x4894
movsd -0x240(%rbp), %xmm0
movsd %xmm0, -0xf8(%rbp)
leaq -0xe0(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x6470
movsd %xmm0, -0x248(%rbp)
jmp 0x48c1
movsd -0x248(%rbp), %xmm0
movsd %xmm0, -0x100(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x6530
movq %rax, -0x250(%rbp)
jmp 0x48e6
movsd -0xf8(%rbp), %xmm0
movsd %xmm0, -0x258(%rbp)
leaq -0x1a0(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x6580
jmp 0x490b
movsd -0x258(%rbp), %xmm0
leaq -0x190(%rbp), %rdi
leaq -0x1a0(%rbp), %rsi
callq 0x6540
jmp 0x4928
movq -0x250(%rbp), %rsi
leaq -0x180(%rbp), %rdi
leaq -0x190(%rbp), %rdx
callq 0x64e0
jmp 0x4944
movsd -0x100(%rbp), %xmm0
movsd %xmm0, -0x260(%rbp)
leaq -0x1d0(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x6630
jmp 0x4969
leaq -0xc0(%rbp), %rdi
callq 0x6670
movsd %xmm0, -0x268(%rbp)
jmp 0x497f
movsd -0x268(%rbp), %xmm0
leaq -0x1c0(%rbp), %rdi
leaq -0x1d0(%rbp), %rsi
callq 0x65d0
jmp 0x499c
movsd -0x260(%rbp), %xmm0
leaq -0x1b0(%rbp), %rdi
leaq -0x1c0(%rbp), %rsi
callq 0x6540
jmp 0x49b9
leaq -0x170(%rbp), %rdi
leaq -0x180(%rbp), %rsi
leaq -0x1b0(%rbp), %rdx
callq 0x64e0
jmp 0x49d5
leaq -0x60(%rbp), %rdi
leaq -0x170(%rbp), %rsi
callq 0x6170
jmp 0x49e7
leaq -0x1e0(%rbp), %rdi
leaq -0x60(%rbp), %rsi
leaq -0xa0(%rbp), %rdx
callq 0x6690
jmp 0x4a00
leaq -0x80(%rbp), %rdi
leaq -0x1e0(%rbp), %rsi
callq 0x6170
jmp 0x4a12
leaq -0xc0(%rbp), %rdi
callq 0x6670
movsd %xmm0, -0x270(%rbp)
jmp 0x4a28
movsd -0x270(%rbp), %xmm0
movsd -0x40(%rbp), %xmm1
callq 0x3510
movsd %xmm0, -0x288(%rbp)
movsd -0x30(%rbp), %xmm0
movsd %xmm0, -0x280(%rbp)
movsd -0xf8(%rbp), %xmm0
movsd -0x100(%rbp), %xmm1
leaq -0xc0(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x66e0
movsd %xmm0, -0x278(%rbp)
jmp 0x4a7c
movsd -0x288(%rbp), %xmm0
movsd -0x278(%rbp), %xmm2
movsd -0x280(%rbp), %xmm1
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd -0x38(%rbp), %xmm1
callq 0x3510
movsd %xmm0, -0x108(%rbp)
movsd -0x108(%rbp), %xmm0
leaq -0x1f0(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x67b0
jmp 0x4ac8
leaq -0x90(%rbp), %rdi
leaq -0x1f0(%rbp), %rsi
callq 0x6800
jmp 0x4add
movsd -0x108(%rbp), %xmm0
addsd -0x110(%rbp), %xmm0
movsd %xmm0, -0x110(%rbp)
movl -0x13c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x13c(%rbp)
jmp 0x47e9
movq -0x230(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
callq 0x3b30
jmp 0x4c4d
movsd -0x110(%rbp), %xmm0
leaq -0x210(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x65d0
jmp 0x4b43
leaq -0x200(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
leaq -0x210(%rbp), %rdx
callq 0x64e0
jmp 0x4b5f
leaq -0x60(%rbp), %rdi
leaq -0x200(%rbp), %rsi
callq 0x6170
jmp 0x4b71
movq -0x10(%rbp), %rdi
leaq -0x60(%rbp), %rsi
leaq -0xe4(%rbp), %rdx
callq 0x41a0
jmp 0x4b87
movq -0x230(%rbp), %rdi
movl -0x114(%rbp), %esi
movl -0x118(%rbp), %edx
callq 0x6840
movq %rax, -0x290(%rbp)
jmp 0x4ba8
movq -0x290(%rbp), %rax
movq %rax, -0xf0(%rbp)
movl $0x0, -0x214(%rbp)
movl -0x214(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0x4bfb
movslq -0x214(%rbp), %rax
movb -0xe4(%rbp,%rax), %dl
movq -0xf0(%rbp), %rax
movslq -0x214(%rbp), %rcx
movb %dl, (%rax,%rcx)
movl -0x214(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x214(%rbp)
jmp 0x4bc0
jmp 0x4bfd
movl -0x118(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x118(%rbp)
jmp 0x4769
jmp 0x4c13
movl -0x114(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x114(%rbp)
jmp 0x4750
movb $0x1, -0x4d(%rbp)
testb $0x1, -0x4d(%rbp)
jne 0x4c3d
movq -0x230(%rbp), %rdi
callq 0x3b30
movq -0x228(%rbp), %rax
addq $0x290, %rsp            # imm = 0x290
popq %rbp
retq
movq -0x68(%rbp), %rdi
callq 0x3520
nopw %cs:(%rax,%rax)