// File: matthewarcus[P]mmps/circularize.cpp
// Function: main
int main(int argc, char* argv[])
{
  Image inImage;
  const char* infilename = "images/earth.ppm";
  const char* outfilename = NULL;
  Rgb background = black;
  Rgb ibackground = black;
  int width;
  int height;
  double fuzz = 2.0;

  // array of pointers. Dynamic allocation is less typing than
  // stack allocating everything.
  OptSpec *optspecs [] = {
    // General options
    new RgbSpec ("-bg", background),
    new RgbSpec ("-ibg", ibackground),
    new DoubleSpec ("-fuzz", fuzz),
    new StringSpec ("-f", infilename),
    new StringSpec ("-out", outfilename),
    NULL // Finish up
  };
  
  char *progname = argv[0];
  argc--;argv++;
  while (argc > 0) {
    int result = OptSpec::ReadOpts(argc, argv, optspecs);
    if (result != 1) {
      error(usage, progname);
    }
    argc--; argv++;
  }

  inImage.Read(infilename);

  height = inImage.Height();
  // Make sure image is big enough to fit a full circular image
  width = inImage.Height();
  double radius = height/2.0;

  Image outImage(width, height);
  //fprintf(stderr, "Size %d\n", height);

  for (int row = 0; row < inImage.Height(); row++) {
    int first = -1;
    int last = -1;
    int column;
    // First scan the row in the input image to find the bounds.
    for (column = 0; column < inImage.Width(); column++) {
      Rgb rgb;
      inImage.GetRgb(column, row, rgb);
      if (!rgb.Match(ibackground, fuzz)) {
	first = column;
	break;
      }
    }
    if (first < 0) {
      // No non-background pixel found, what to do?
      first = last = inImage.Width()/2;
    } else {
      // Now look from the right
      for (column = inImage.Width()-1; column >= 0; column--) {
	Rgb rgb;
	inImage.GetRgb(column, row, rgb);
	if (!rgb.Match(ibackground, fuzz)) {
	  last = column+1;
	  break;
	}
      }
    }
    //fprintf(stderr, "%d %d\n", first, last);
    // Work out the half width of the image on this scan line
    double hw = sqrt(square(radius) - square(radius - (row + 0.5)));
    double a = (last-first)/(2.0*hw);
    double b = first - a * (radius - hw);
    for (column = 0; column < width; column++) {
      // Find the corresponding pixel in the input image
      int p = int(floor(a * column + b));
      if (p >= first && p < last) {
	Rgb rgb;
	inImage.GetRgb(p,row,rgb);
	outImage.SetRgb(column,row,rgb);
      } else {
	outImage.SetRgb(column,row,background);
      }
    }
  }
  outImage.Write(outfilename);
  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
xorl %eax, %eax
movl %eax, %edx
leaq -0x40(%rbp), %rdi
movq %rdx, %rsi
callq 0x11e10
leaq 0xe51e(%rip), %rax      # 0x1405e
movq %rax, -0x48(%rbp)
movq $0x0, -0x50(%rbp)
movb 0x16709(%rip), %al      # 0x1c25b
movb %al, -0x52(%rbp)
movw 0x166fd(%rip), %ax      # 0x1c259
movw %ax, -0x54(%rbp)
movb 0x166f5(%rip), %al      # 0x1c25b
movb %al, -0x56(%rbp)
movw 0x166e9(%rip), %ax      # 0x1c259
movw %ax, -0x58(%rbp)
movabsq $0x4000000000000000, %rax # imm = 0x4000000000000000
movq %rax, -0x68(%rbp)
movl $0x18, %edi
callq 0x52a0
movq %rax, -0x138(%rbp)
jmp 0x5b95
movq -0x138(%rbp), %rdi
leaq 0xe4cc(%rip), %rsi      # 0x1406f
leaq -0x54(%rbp), %rdx
callq 0x63a0
jmp 0x5bae
movq -0x138(%rbp), %rax
movq %rax, -0xa0(%rbp)
leaq -0x98(%rbp), %rax
movq %rax, -0x148(%rbp)
movl $0x18, %edi
callq 0x52a0
movq %rax, -0x140(%rbp)
jmp 0x5bdd
movq -0x140(%rbp), %rdi
leaq 0xe488(%rip), %rsi      # 0x14073
leaq -0x58(%rbp), %rdx
callq 0x63a0
jmp 0x5bf6
movq -0x148(%rbp), %rax
movq -0x140(%rbp), %rcx
movq %rcx, (%rax)
leaq -0x90(%rbp), %rax
movq %rax, -0x158(%rbp)
movl $0x20, %edi
callq 0x52a0
movq %rax, -0x150(%rbp)
jmp 0x5c28
movq -0x150(%rbp), %rdi
leaq 0xe442(%rip), %rsi      # 0x14078
leaq -0x68(%rbp), %rdx
movsd 0xe3c6(%rip), %xmm0     # 0x14008
callq 0xf1c0
jmp 0x5c49
movq -0x158(%rbp), %rax
movq -0x150(%rbp), %rcx
movq %rcx, (%rax)
leaq -0x88(%rbp), %rax
movq %rax, -0x168(%rbp)
movl $0x18, %edi
callq 0x52a0
movq %rax, -0x160(%rbp)
jmp 0x5c7b
movq -0x160(%rbp), %rdi
leaq 0xe3f5(%rip), %rsi      # 0x1407e
leaq -0x48(%rbp), %rdx
callq 0xefb0
jmp 0x5c94
movq -0x168(%rbp), %rax
movq -0x160(%rbp), %rcx
movq %rcx, (%rax)
leaq -0x80(%rbp), %rax
movq %rax, -0x178(%rbp)
movl $0x18, %edi
callq 0x52a0
movq %rax, -0x170(%rbp)
jmp 0x5cc3
movq -0x170(%rbp), %rdi
leaq 0xe3b0(%rip), %rsi      # 0x14081
leaq -0x50(%rbp), %rdx
callq 0xefb0
jmp 0x5cdc
movq -0x178(%rbp), %rax
movq -0x170(%rbp), %rcx
movq %rcx, (%rax)
movq $0x0, -0x78(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xb8(%rbp)
movl -0x8(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x8(%rbp)
movq -0x10(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x10(%rbp)
cmpl $0x0, -0x8(%rbp)
jle 0x5e6a
leaq -0x8(%rbp), %rdi
leaq -0x10(%rbp), %rsi
leaq -0xa0(%rbp), %rdx
callq 0xee90
movl %eax, -0x17c(%rbp)
jmp 0x5d3e
movl -0x17c(%rbp), %eax
movl %eax, -0xbc(%rbp)
cmpl $0x1, -0xbc(%rbp)
je 0x5e50
movq 0x164ea(%rip), %rdi     # 0x1c248
movq -0xb8(%rbp), %rsi
callq 0x63f0
jmp 0x5d6c
jmp 0x5e50
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
jmp 0x632e
movq -0x138(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
movl $0x18, %esi
callq 0x52b0
jmp 0x632e
movq -0x140(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
movl $0x18, %esi
callq 0x52b0
jmp 0x632e
movq -0x150(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
movl $0x20, %esi
callq 0x52b0
jmp 0x632e
movq -0x160(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
movl $0x18, %esi
callq 0x52b0
jmp 0x632e
movq -0x170(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
movl $0x18, %esi
callq 0x52b0
jmp 0x632e
movl -0x8(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x8(%rbp)
movq -0x10(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x10(%rbp)
jmp 0x5d18
movq -0x48(%rbp), %rsi
leaq -0x40(%rbp), %rdi
xorl %edx, %edx
callq 0x12160
jmp 0x5e7b
leaq -0x40(%rbp), %rdi
callq 0x6440
movq %rax, -0x188(%rbp)
jmp 0x5e8d
movq -0x188(%rbp), %rax
movl %eax, -0x60(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x6440
movq %rax, -0x190(%rbp)
jmp 0x5ea9
movq -0x190(%rbp), %rax
movl %eax, -0x5c(%rbp)
cvtsi2sdl -0x60(%rbp), %xmm0
movsd 0xe150(%rip), %xmm1     # 0x14010
mulsd %xmm1, %xmm0
movsd %xmm0, -0xc8(%rbp)
movslq -0x5c(%rbp), %rsi
movslq -0x60(%rbp), %rdx
leaq -0xf8(%rbp), %rdi
callq 0x11e10
jmp 0x5ee2
movl $0x0, -0xfc(%rbp)
movslq -0xfc(%rbp), %rax
movq %rax, -0x1a0(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x6440
movq %rax, -0x198(%rbp)
jmp 0x5f0c
movq -0x1a0(%rbp), %rax
movq -0x198(%rbp), %rcx
cmpq %rcx, %rax
jge 0x62f4
movl $0xffffffff, -0x100(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x104(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x108(%rbp)
movslq -0x108(%rbp), %rax
movq %rax, -0x1b0(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x6460
movq %rax, -0x1a8(%rbp)
jmp 0x5f61
movq -0x1b0(%rbp), %rax
movq -0x1a8(%rbp), %rcx
cmpq %rcx, %rax
jge 0x601c
leaq -0x10b(%rbp), %rdi
xorl %ecx, %ecx
movl %ecx, %esi
movl %ecx, %edx
callq 0x6370
jmp 0x5f8c
movslq -0x108(%rbp), %rsi
movslq -0xfc(%rbp), %rdx
leaq -0x40(%rbp), %rdi
leaq -0x10b(%rbp), %rcx
callq 0x6480
jmp 0x5fac
movsd -0x68(%rbp), %xmm0
leaq -0x10b(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x11c70
movb %al, -0x1b1(%rbp)
jmp 0x5fc9
movb -0x1b1(%rbp), %al
testb $0x1, %al
jne 0x6006
jmp 0x5fd5
movl -0x108(%rbp), %eax
movl %eax, -0x100(%rbp)
jmp 0x601c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x11ed0
jmp 0x632e
jmp 0x6008
movl -0x108(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x108(%rbp)
jmp 0x5f41
cmpl $0x0, -0x100(%rbp)
jge 0x6059
leaq -0x40(%rbp), %rdi
callq 0x6460
movq %rax, -0x1c0(%rbp)
jmp 0x6037
movq -0x1c0(%rbp), %rax
movl $0x2, %ecx
cqto
idivq %rcx
movl %eax, -0x104(%rbp)
movl %eax, -0x100(%rbp)
jmp 0x610f
leaq -0x40(%rbp), %rdi
callq 0x6460
movq %rax, -0x1c8(%rbp)
jmp 0x606b
movq -0x1c8(%rbp), %rax
subq $0x1, %rax
movl %eax, -0x108(%rbp)
cmpl $0x0, -0x108(%rbp)
jl 0x610d
leaq -0x10e(%rbp), %rdi
xorl %ecx, %ecx
movl %ecx, %esi
movl %ecx, %edx
callq 0x6370
jmp 0x609d
movslq -0x108(%rbp), %rsi
movslq -0xfc(%rbp), %rdx
leaq -0x40(%rbp), %rdi
leaq -0x10e(%rbp), %rcx
callq 0x6480
jmp 0x60bd
movsd -0x68(%rbp), %xmm0
leaq -0x10e(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x11c70
movb %al, -0x1c9(%rbp)
jmp 0x60da
movb -0x1c9(%rbp), %al
testb $0x1, %al
jne 0x60f7
jmp 0x60e6
movl -0x108(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x104(%rbp)
jmp 0x610d
jmp 0x60f9
movl -0x108(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x108(%rbp)
jmp 0x607c
jmp 0x610f
movsd -0xc8(%rbp), %xmm0
callq 0x6350
movsd %xmm0, -0x1d8(%rbp)
jmp 0x6126
movsd -0xc8(%rbp), %xmm0
cvtsi2sdl -0xfc(%rbp), %xmm1
movsd 0xded2(%rip), %xmm2     # 0x14010
addsd %xmm2, %xmm1
subsd %xmm1, %xmm0
callq 0x6350
movsd %xmm0, -0x1e0(%rbp)
jmp 0x6155
movsd -0x1e0(%rbp), %xmm1
movsd -0x1d8(%rbp), %xmm0
subsd %xmm1, %xmm0
callq 0x5200
movsd %xmm0, -0x118(%rbp)
movl -0x104(%rbp), %eax
subl -0x100(%rbp), %eax
cvtsi2sd %eax, %xmm0
movsd 0xde8a(%rip), %xmm1     # 0x14018
mulsd -0x118(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x120(%rbp)
cvtsi2sdl -0x100(%rbp), %xmm1
movsd -0x120(%rbp), %xmm0
movsd -0xc8(%rbp), %xmm2
subsd -0x118(%rbp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x128(%rbp)
movl $0x0, -0x108(%rbp)
movl -0x108(%rbp), %eax
cmpl -0x5c(%rbp), %eax
jge 0x62de
movsd -0x120(%rbp), %xmm0
cvtsi2sdl -0x108(%rbp), %xmm2
movsd -0x128(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
callq 0x53d0
cvttsd2si %xmm0, %eax
movl %eax, -0x12c(%rbp)
movl -0x12c(%rbp), %eax
cmpl -0x100(%rbp), %eax
jl 0x62a6
movl -0x12c(%rbp), %eax
cmpl -0x104(%rbp), %eax
jge 0x62a6
leaq -0x12f(%rbp), %rdi
xorl %ecx, %ecx
movl %ecx, %esi
movl %ecx, %edx
callq 0x6370
jmp 0x6261
movslq -0x12c(%rbp), %rsi
movslq -0xfc(%rbp), %rdx
leaq -0x40(%rbp), %rdi
leaq -0x12f(%rbp), %rcx
callq 0x6480
jmp 0x6281
movslq -0x108(%rbp), %rsi
movslq -0xfc(%rbp), %rdx
leaq -0xf8(%rbp), %rdi
leaq -0x12f(%rbp), %rcx
callq 0x64c0
jmp 0x62a4
jmp 0x62c8
movslq -0x108(%rbp), %rsi
movslq -0xfc(%rbp), %rdx
leaq -0xf8(%rbp), %rdi
leaq -0x54(%rbp), %rcx
callq 0x64c0
jmp 0x62c6
jmp 0x62c8
jmp 0x62ca
movl -0x108(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x108(%rbp)
jmp 0x61f3
jmp 0x62e0
movl -0xfc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xfc(%rbp)
jmp 0x5eec
movq -0x50(%rbp), %rsi
leaq -0xf8(%rbp), %rdi
callq 0x12500
jmp 0x6306
movl $0x0, -0x4(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x11ed0
leaq -0x40(%rbp), %rdi
callq 0x11ed0
movl -0x4(%rbp), %eax
addq $0x1e0, %rsp            # imm = 0x1E0
popq %rbp
retq
leaq -0x40(%rbp), %rdi
callq 0x11ed0
movq -0xa8(%rbp), %rdi
callq 0x53f0
nopw %cs:(%rax,%rax)