// File: srajangarg[P]image-morph/src/morph.cpp
// Function: sampleBilinear(Image const&, Vec2 const&, unsigned char*)
void
sampleBilinear(Image const & image, Vec2 const & loc, unsigned char sampled_color[4])
{  
  int w = image.width();
  int h = image.height();
  int n = image.numChannels();
 
  // raw cordinates
  int col0 = floor(loc.x());
  int col1 = col0 + 1;
  int row0 = floor(loc.y());
  int row1 = row0 + 1;

  // sanitized to get pixels form image
  int pc0 = max(0, min(col0, w-1));
  int pc1 = min(pc0 + 1, w-1);
  int pr0 = max(0, min(row0, h-1));
  int pr1 = min(pr0 + 1, h-1);
  
  // pixel values at the sanitized points
  const unsigned char * pix00 = image.pixel(pr0, pc0);
  const unsigned char * pix01 = image.pixel(pr0, pc1);
  const unsigned char * pix10 = image.pixel(pr1, pc0);
  const unsigned char * pix11 = image.pixel(pr1, pc1);
  
  // https://en.wikipedia.org/wiki/Bilinear_interpolation
  double res;
  for (int channel = 0; channel < n; ++channel)
  {
    res = 0;

    res += ((double)pix00[channel]) * (col1 - loc.x()) * (row1 - loc.y());
    res += ((double)pix01[channel]) * (col1 - loc.x()) * (loc.y() - row0);
    res += ((double)pix10[channel]) * (loc.x() - col0) * (row1 - loc.y());
    res += ((double)pix11[channel]) * (loc.x() - col0) * (loc.y() - row0);

    sampled_color[channel] = min(255, max(0, (int)floor(res)));
  }

  // if numchannels < 4, others set 4 
  for (int i = n; i < 4; ++i)
    sampled_color[i] = 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rdi
callq 0x5f80
movl %eax, -0x1c(%rbp)
movq -0x8(%rbp), %rdi
callq 0x5f90
movl %eax, -0x20(%rbp)
movq -0x8(%rbp), %rdi
callq 0x5fb0
movl %eax, -0x24(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5fd0
callq 0x34d0
cvttsd2si %xmm0, %eax
movl %eax, -0x28(%rbp)
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5ff0
callq 0x34d0
cvttsd2si %xmm0, %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
movl $0x0, -0x3c(%rbp)
movl -0x1c(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x40(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x6050
movq %rax, %rsi
leaq -0x3c(%rbp), %rdi
callq 0x6010
movl (%rax), %eax
movl %eax, -0x38(%rbp)
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
movl -0x1c(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x4c(%rbp)
leaq -0x48(%rbp), %rdi
leaq -0x4c(%rbp), %rsi
callq 0x6050
movl (%rax), %eax
movl %eax, -0x44(%rbp)
movl $0x0, -0x54(%rbp)
movl -0x20(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x58(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x6050
movq %rax, %rsi
leaq -0x54(%rbp), %rdi
callq 0x6010
movl (%rax), %eax
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
movl -0x20(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x64(%rbp)
leaq -0x60(%rbp), %rdi
leaq -0x64(%rbp), %rsi
callq 0x6050
movl (%rax), %eax
movl %eax, -0x5c(%rbp)
movq -0x8(%rbp), %rdi
movl -0x50(%rbp), %esi
movl -0x38(%rbp), %edx
callq 0x6090
movq %rax, -0x70(%rbp)
movq -0x8(%rbp), %rdi
movl -0x50(%rbp), %esi
movl -0x44(%rbp), %edx
callq 0x6090
movq %rax, -0x78(%rbp)
movq -0x8(%rbp), %rdi
movl -0x5c(%rbp), %esi
movl -0x38(%rbp), %edx
callq 0x6090
movq %rax, -0x80(%rbp)
movq -0x8(%rbp), %rdi
movl -0x5c(%rbp), %esi
movl -0x44(%rbp), %edx
callq 0x6090
movq %rax, -0x88(%rbp)
movl $0x0, -0x94(%rbp)
movl -0x94(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x45c8
movq $0x0, -0x90(%rbp)
movq -0x70(%rbp), %rax
movslq -0x94(%rbp), %rcx
movzbl (%rax,%rcx), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x100(%rbp)
cvtsi2sdl -0x2c(%rbp), %xmm0
movsd %xmm0, -0x108(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5fd0
movsd -0x108(%rbp), %xmm1
movaps %xmm0, %xmm2
movsd -0x100(%rbp), %xmm0
subsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, -0xf0(%rbp)
cvtsi2sdl -0x34(%rbp), %xmm0
movsd %xmm0, -0xf8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5ff0
movsd -0xf8(%rbp), %xmm2
movaps %xmm0, %xmm1
movsd -0xf0(%rbp), %xmm0
subsd %xmm1, %xmm2
movsd -0x90(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x90(%rbp)
movq -0x78(%rbp), %rax
movslq -0x94(%rbp), %rcx
movzbl (%rax,%rcx), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0xe0(%rbp)
cvtsi2sdl -0x2c(%rbp), %xmm0
movsd %xmm0, -0xe8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5fd0
movsd -0xe8(%rbp), %xmm1
movaps %xmm0, %xmm2
movsd -0xe0(%rbp), %xmm0
subsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, -0xd8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5ff0
movaps %xmm0, %xmm2
movsd -0xd8(%rbp), %xmm0
cvtsi2sdl -0x30(%rbp), %xmm1
subsd %xmm1, %xmm2
movsd -0x90(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x90(%rbp)
movq -0x80(%rbp), %rax
movslq -0x94(%rbp), %rcx
movzbl (%rax,%rcx), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0xd0(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5fd0
movaps %xmm0, %xmm1
movsd -0xd0(%rbp), %xmm0
cvtsi2sdl -0x28(%rbp), %xmm2
subsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, -0xc0(%rbp)
cvtsi2sdl -0x34(%rbp), %xmm0
movsd %xmm0, -0xc8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5ff0
movsd -0xc8(%rbp), %xmm2
movaps %xmm0, %xmm1
movsd -0xc0(%rbp), %xmm0
subsd %xmm1, %xmm2
movsd -0x90(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x90(%rbp)
movq -0x88(%rbp), %rax
movslq -0x94(%rbp), %rcx
movzbl (%rax,%rcx), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0xb8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5fd0
movaps %xmm0, %xmm1
movsd -0xb8(%rbp), %xmm0
cvtsi2sdl -0x28(%rbp), %xmm2
subsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, -0xb0(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5ff0
movaps %xmm0, %xmm2
movsd -0xb0(%rbp), %xmm0
cvtsi2sdl -0x30(%rbp), %xmm1
subsd %xmm1, %xmm2
movsd -0x90(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x90(%rbp)
movl $0xff, -0x98(%rbp)
movl $0x0, -0x9c(%rbp)
movsd -0x90(%rbp), %xmm0
callq 0x34d0
cvttsd2si %xmm0, %eax
movl %eax, -0xa0(%rbp)
leaq -0x9c(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x6010
movq %rax, %rsi
leaq -0x98(%rbp), %rdi
callq 0x6050
movl (%rax), %eax
movb %al, %dl
movq -0x18(%rbp), %rax
movslq -0x94(%rbp), %rcx
movb %dl, (%rax,%rcx)
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0x4314
movl -0x24(%rbp), %eax
movl %eax, -0xa4(%rbp)
cmpl $0x4, -0xa4(%rbp)
jge 0x45fa
movq -0x18(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movb $0x0, (%rax,%rcx)
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x45d1
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
nopw %cs:(%rax,%rax)