// File: manikandan5[P]Image-Matching-Stitching-Warping/./Homography.h
// Function: projectiveTransform(Image const&, cimg_library::CImg<double>&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
void projectiveTransform(const Image& I,CImg<double>& projection,const string& name)
{
	CImg<double> imageData = I.getImageData();
	
	CImg<double> transformedImage(imageData.width(),imageData.height(),imageData.depth(),3,255);
	
	projection.invert();
	
	
	double ai = projection(0,0) ,bi = projection(1,0), ci = projection(2,0), di = projection(0,1), ei = projection(1,1), 
	        fi = projection(2,1), gi = projection(0,2), hi = projection(1,2), ii = projection(2,2);
	
	// Inverse warping
	for(int i = 0;i<transformedImage.width();++i)
	{
		for(int j = 0;j<transformedImage.height();++j)
		{
			double w = (ai*i + bi*j + ci)/(gi*i + hi*j + ii);
			double h = (di*i + ei*j + fi)/(gi*i + hi*j + ii);
			
			//Bilinear Interpolation
			// Credit to wikipedia  = https://en.wikipedia.org/wiki/Bilinear_interpolation	
			int w0 = (int)floor(w);
			int h0 = (int)floor(h);
			int w1 = (int)ceil(w);
			int h1 = (int)ceil(h);
			
			
			if(w0 <0 || h0<0 || w1<0 || h1<0 || w0>=imageData.width() || w1>=imageData.width() || h0>=imageData.height() || h1>=imageData.height())
				continue;
			
			for(int k = 0;k<3;++k)
			{
				double v1 = imageData(w0,h0,0,k);
				double v2 = imageData(w1,h0,0,k);
				double v3 = imageData(w0,h1,0,k);
				double v4 = imageData(w1,h1,0,k);
				
				double Tw = (((w1 - w)/(w1-w0)) * v1) + (((w-w0)/(w1-w0)) * v2);
				double Th = (((w1 - w)/(w1-w0)) * v3) + (((w-w0)/(w1-w0)) * v4);

				double value = (((h1-h)/(h1-h0)) * Tw) + (((h-h0)/(h1-h0)) * Th);
				
				transformedImage(i,j,k)	= value;		
			}
		}
	}
	
	transformedImage.get_normalize(0,255).save(name.c_str());	
}

// Assembly:
subq $0x1f8, %rsp            # imm = 0x1F8
movq %rdi, 0x1f0(%rsp)
movq %rsi, 0x1e8(%rsp)
movq %rdx, 0x1e0(%rsp)
movq 0x1f0(%rsp), %rsi
leaq 0x1c0(%rsp), %rdi
movq %rdi, 0xb0(%rsp)
callq 0x8990
movq 0xb0(%rsp), %rdi
callq 0x89c0
movl %eax, 0xbc(%rsp)
jmp 0x5d62
leaq 0x1c0(%rsp), %rdi
callq 0x89d0
movl %eax, 0xac(%rsp)
jmp 0x5d78
leaq 0x1c0(%rsp), %rdi
callq 0x89e0
movl %eax, 0xa8(%rsp)
jmp 0x5d8e
movl 0xa8(%rsp), %ecx
movl 0xac(%rsp), %edx
movl 0xbc(%rsp), %esi
leaq 0x1a0(%rsp), %rdi
movl $0x3, %r8d
movsd 0xc224f(%rip), %xmm0    # 0xc8008
callq 0x89f0
jmp 0x5dc0
movq 0x1e8(%rsp), %rdi
movl $0x1, %esi
callq 0x8d30
jmp 0x5dd4
movq 0x1e8(%rsp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x9850
movq %rax, 0xa0(%rsp)
jmp 0x5def
movq 0xa0(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x188(%rsp)
movq 0x1e8(%rsp), %rdi
movl $0x1, %esi
xorl %edx, %edx
callq 0x9850
movq %rax, 0x98(%rsp)
jmp 0x5e22
movq 0x98(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x180(%rsp)
movq 0x1e8(%rsp), %rdi
movl $0x2, %esi
xorl %edx, %edx
callq 0x9850
movq %rax, 0x90(%rsp)
jmp 0x5e55
movq 0x90(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x178(%rsp)
movq 0x1e8(%rsp), %rdi
xorl %esi, %esi
movl $0x1, %edx
callq 0x9850
movq %rax, 0x88(%rsp)
jmp 0x5e88
movq 0x88(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x170(%rsp)
movq 0x1e8(%rsp), %rdi
movl $0x1, %edx
movl %edx, %esi
callq 0x9850
movq %rax, 0x80(%rsp)
jmp 0x5ebb
movq 0x80(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x168(%rsp)
movq 0x1e8(%rsp), %rdi
movl $0x2, %esi
movl $0x1, %edx
callq 0x9850
movq %rax, 0x78(%rsp)
jmp 0x5eee
movq 0x78(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x160(%rsp)
movq 0x1e8(%rsp), %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x9850
movq %rax, 0x70(%rsp)
jmp 0x5f1b
movq 0x70(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x158(%rsp)
movq 0x1e8(%rsp), %rdi
movl $0x1, %esi
movl $0x2, %edx
callq 0x9850
movq %rax, 0x68(%rsp)
jmp 0x5f4b
movq 0x68(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x150(%rsp)
movq 0x1e8(%rsp), %rdi
movl $0x2, %edx
movl %edx, %esi
callq 0x9850
movq %rax, 0x60(%rsp)
jmp 0x5f78
movq 0x60(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x148(%rsp)
movl $0x0, 0x144(%rsp)
movl 0x144(%rsp), %eax
movl %eax, 0x58(%rsp)
leaq 0x1a0(%rsp), %rdi
callq 0x89c0
movl %eax, 0x5c(%rsp)
jmp 0x5fb3
movl 0x58(%rsp), %eax
movl 0x5c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x6525
movl $0x0, 0x140(%rsp)
movl 0x140(%rsp), %eax
movl %eax, 0x50(%rsp)
leaq 0x1a0(%rsp), %rdi
callq 0x89d0
movl %eax, 0x54(%rsp)
jmp 0x5fec
movl 0x50(%rsp), %eax
movl 0x54(%rsp), %ecx
cmpl %ecx, %eax
jge 0x650d
movsd 0x188(%rsp), %xmm0
cvtsi2sdl 0x144(%rsp), %xmm2
movsd 0x180(%rsp), %xmm1
cvtsi2sdl 0x140(%rsp), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
addsd 0x178(%rsp), %xmm0
movsd 0x158(%rsp), %xmm1
cvtsi2sdl 0x144(%rsp), %xmm3
movsd 0x150(%rsp), %xmm2
cvtsi2sdl 0x140(%rsp), %xmm4
mulsd %xmm4, %xmm2
mulsd %xmm3, %xmm1
addsd %xmm2, %xmm1
addsd 0x148(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x138(%rsp)
movsd 0x170(%rsp), %xmm0
cvtsi2sdl 0x144(%rsp), %xmm2
movsd 0x168(%rsp), %xmm1
cvtsi2sdl 0x140(%rsp), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
addsd 0x160(%rsp), %xmm0
movsd 0x158(%rsp), %xmm1
cvtsi2sdl 0x144(%rsp), %xmm3
movsd 0x150(%rsp), %xmm2
cvtsi2sdl 0x140(%rsp), %xmm4
mulsd %xmm4, %xmm2
mulsd %xmm3, %xmm1
addsd %xmm2, %xmm1
addsd 0x148(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x130(%rsp)
movsd 0x138(%rsp), %xmm0
callq 0x5900
cvttsd2si %xmm0, %eax
movl %eax, 0x12c(%rsp)
movsd 0x130(%rsp), %xmm0
callq 0x5900
cvttsd2si %xmm0, %eax
movl %eax, 0x128(%rsp)
movsd 0x138(%rsp), %xmm0
callq 0x5080
cvttsd2si %xmm0, %eax
movl %eax, 0x124(%rsp)
movsd 0x130(%rsp), %xmm0
callq 0x5080
cvttsd2si %xmm0, %eax
movl %eax, 0x120(%rsp)
cmpl $0x0, 0x12c(%rsp)
jl 0x623e
cmpl $0x0, 0x128(%rsp)
jl 0x623e
cmpl $0x0, 0x124(%rsp)
jl 0x623e
cmpl $0x0, 0x120(%rsp)
jl 0x623e
movl 0x12c(%rsp), %eax
movl %eax, 0x48(%rsp)
leaq 0x1c0(%rsp), %rdi
callq 0x89c0
movl %eax, 0x4c(%rsp)
jmp 0x61b4
movl 0x48(%rsp), %eax
movl 0x4c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x623e
movl 0x124(%rsp), %eax
movl %eax, 0x40(%rsp)
leaq 0x1c0(%rsp), %rdi
callq 0x89c0
movl %eax, 0x44(%rsp)
jmp 0x61de
movl 0x40(%rsp), %eax
movl 0x44(%rsp), %ecx
cmpl %ecx, %eax
jge 0x623e
movl 0x128(%rsp), %eax
movl %eax, 0x38(%rsp)
leaq 0x1c0(%rsp), %rdi
callq 0x89d0
movl %eax, 0x3c(%rsp)
jmp 0x6208
movl 0x38(%rsp), %eax
movl 0x3c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x623e
movl 0x120(%rsp), %eax
movl %eax, 0x30(%rsp)
leaq 0x1c0(%rsp), %rdi
callq 0x89d0
movl %eax, 0x34(%rsp)
jmp 0x6232
movl 0x30(%rsp), %eax
movl 0x34(%rsp), %ecx
cmpl %ecx, %eax
jl 0x6275
jmp 0x64f7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
jmp 0x65cd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
jmp 0x65c0
movl $0x0, 0x11c(%rsp)
cmpl $0x3, 0x11c(%rsp)
jge 0x64f5
movl 0x12c(%rsp), %esi
movl 0x128(%rsp), %edx
movl 0x11c(%rsp), %r8d
leaq 0x1c0(%rsp), %rdi
xorl %ecx, %ecx
callq 0x9880
movq %rax, 0x28(%rsp)
jmp 0x62ba
movq 0x28(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x110(%rsp)
movl 0x124(%rsp), %esi
movl 0x128(%rsp), %edx
movl 0x11c(%rsp), %r8d
leaq 0x1c0(%rsp), %rdi
xorl %ecx, %ecx
callq 0x9880
movq %rax, 0x20(%rsp)
jmp 0x62f8
movq 0x20(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x108(%rsp)
movl 0x12c(%rsp), %esi
movl 0x120(%rsp), %edx
movl 0x11c(%rsp), %r8d
leaq 0x1c0(%rsp), %rdi
xorl %ecx, %ecx
callq 0x9880
movq %rax, 0x18(%rsp)
jmp 0x6336
movq 0x18(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x100(%rsp)
movl 0x124(%rsp), %esi
movl 0x120(%rsp), %edx
movl 0x11c(%rsp), %r8d
leaq 0x1c0(%rsp), %rdi
xorl %ecx, %ecx
callq 0x9880
movq %rax, 0x10(%rsp)
jmp 0x6374
movq 0x10(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0xf8(%rsp)
movl 0x124(%rsp), %ecx
cvtsi2sd %ecx, %xmm0
movsd 0x138(%rsp), %xmm1
subsd %xmm1, %xmm0
movl 0x12c(%rsp), %eax
subl %eax, %ecx
cvtsi2sd %ecx, %xmm3
divsd %xmm3, %xmm0
movsd 0x110(%rsp), %xmm2
cvtsi2sd %eax, %xmm4
subsd %xmm4, %xmm1
divsd %xmm3, %xmm1
movsd 0x108(%rsp), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xf0(%rsp)
movl 0x124(%rsp), %ecx
cvtsi2sd %ecx, %xmm0
movsd 0x138(%rsp), %xmm1
subsd %xmm1, %xmm0
movl 0x12c(%rsp), %eax
subl %eax, %ecx
cvtsi2sd %ecx, %xmm3
divsd %xmm3, %xmm0
movsd 0x100(%rsp), %xmm2
cvtsi2sd %eax, %xmm4
subsd %xmm4, %xmm1
divsd %xmm3, %xmm1
movsd 0xf8(%rsp), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xe8(%rsp)
movl 0x120(%rsp), %ecx
cvtsi2sd %ecx, %xmm0
movsd 0x130(%rsp), %xmm1
subsd %xmm1, %xmm0
movl 0x128(%rsp), %eax
subl %eax, %ecx
cvtsi2sd %ecx, %xmm3
divsd %xmm3, %xmm0
movsd 0xf0(%rsp), %xmm2
cvtsi2sd %eax, %xmm4
subsd %xmm4, %xmm1
divsd %xmm3, %xmm1
movsd 0xe8(%rsp), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xe0(%rsp)
movsd 0xe0(%rsp), %xmm0
movsd %xmm0, (%rsp)
movl 0x144(%rsp), %esi
movl 0x140(%rsp), %edx
movl 0x11c(%rsp), %ecx
leaq 0x1a0(%rsp), %rdi
callq 0x98f0
movq %rax, 0x8(%rsp)
jmp 0x64d1
movq 0x8(%rsp), %rax
movsd (%rsp), %xmm0
movsd %xmm0, (%rax)
movl 0x11c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x11c(%rsp)
jmp 0x6280
jmp 0x64f7
movl 0x140(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x140(%rsp)
jmp 0x5fce
jmp 0x650f
movl 0x144(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x144(%rsp)
jmp 0x5f95
leaq 0xc0(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
xorps %xmm0, %xmm0
movsd 0xc1ac8(%rip), %xmm1    # 0xc8008
callq 0x9940
jmp 0x6547
movq 0x1e0(%rsp), %rdi
callq 0x51f0
movq %rax, %rsi
leaq 0xc0(%rsp), %rdi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0x6, %ecx
callq 0x99f0
jmp 0x6570
leaq 0xc0(%rsp), %rdi
callq 0xa540
leaq 0x1a0(%rsp), %rdi
callq 0xa540
leaq 0x1c0(%rsp), %rdi
callq 0xa540
addq $0x1f8, %rsp            # imm = 0x1F8
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0xa540
leaq 0x1a0(%rsp), %rdi
callq 0xa540
leaq 0x1c0(%rsp), %rdi
callq 0xa540
movq 0x198(%rsp), %rdi
callq 0x5970
nopw (%rax,%rax)