// File: jpbalarini[P]otsus/./algo.cpp
// Function: algorithm(int, char**)
void algorithm(int argc, char **argv) {
  // Optional parameters
  vector <OptStruct *> options;
  // Mandatory parameters
  vector <ParStruct *> parameters;

  OptStruct oThreshold = {"t:", 0,  NULL, NULL, "override threshold"};
  options.push_back(&oThreshold);

  ParStruct pinput = {"input", NULL, "input image"}; parameters.push_back(&pinput);
  ParStruct pout = {"output", NULL, "output image"}; parameters.push_back(&pout);

  if (!parsecmdline("otsus", "otsu's segmentation",
                    argc, argv, options, parameters)) {
    printf("\n");
    exit(-1);
  }

  // Optional parameters
  bool override_thres = oThreshold.flag;
  int overrided_threshold = 0;
  if (override_thres){
    overrided_threshold = atoi(oThreshold.value);
    // Check threshold bounds
    if (overrided_threshold > MAX_INTENSITY || overrided_threshold < 0){
      printf("Invalid threshold value\n");
      exit(-1);
    }
  }

  // Load input image
  CImage input;
  input.load((char*)pinput.value);

  // Input image properties
  int bits = input.get_bits_per_channel();
  int num_channels = input.get_num_channels();
  int Nx = input.get_width();
  int Ny = input.get_height();
  long int N = Nx * Ny;

  if (num_channels > 1){
    fprintf(stderr, "Algorithm works only with grayscale images\n");
    exit(-1);
  }
  // Create output
  CImage *output = new CImage(Nx, Ny,
                              bits,
                              num_channels);

  unsigned hist[MAX_INTENSITY + 1];
  computeHistogram(input, hist);

  computeOtsusSegmentation(input, hist, output, overrided_threshold);

  // Save output
  output->save((char*)pout.value, bits);
  delete output;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x160, %rsp            # imm = 0x160
movl %edi, -0x4(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x28(%rbp), %rdi
movq %rdi, -0x128(%rbp)
callq 0xb470
leaq -0x40(%rbp), %rdi
callq 0xb490
movq -0x128(%rbp), %rdi
movq 0x7c8f(%rip), %rax      # 0x12d28
movq %rax, -0x50(%rbp)
movups 0x7c74(%rip), %xmm0     # 0x12d18
movaps %xmm0, -0x60(%rbp)
movups 0x7c59(%rip), %xmm0     # 0x12d08
movaps %xmm0, -0x70(%rbp)
leaq -0x70(%rbp), %rax
movq %rax, -0x78(%rbp)
leaq -0x78(%rbp), %rsi
callq 0xb4b0
jmp 0xb0c6
movq 0x7c73(%rip), %rax      # 0x12d40
movq %rax, -0x90(%rbp)
movups 0x7c55(%rip), %xmm0     # 0x12d30
movaps %xmm0, -0xa0(%rbp)
leaq -0xa0(%rbp), %rax
movq %rax, -0xa8(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0xb4e0
jmp 0xb102
movq 0x7c4f(%rip), %rax      # 0x12d58
movq %rax, -0xb0(%rbp)
movups 0x7c31(%rip), %xmm0     # 0x12d48
movaps %xmm0, -0xc0(%rbp)
leaq -0xc0(%rbp), %rax
movq %rax, -0xc8(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0xb4e0
jmp 0xb13e
movl -0x4(%rbp), %edx
movq -0x10(%rbp), %rcx
leaq 0x2a70(%rip), %rdi      # 0xdbbc
leaq 0x2a6f(%rip), %rsi      # 0xdbc2
leaq -0x28(%rbp), %r8
leaq -0x40(%rbp), %r9
callq 0x6260
movl %eax, -0x12c(%rbp)
jmp 0xb168
movl -0x12c(%rbp), %eax
cmpl $0x0, %eax
jne 0xb1a1
leaq 0x2972(%rip), %rdi      # 0xdaec
xorl %eax, %eax
callq 0x3070
jmp 0xb183
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x33e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xb44f
cmpl $0x0, -0x68(%rbp)
setne %al
andb $0x1, %al
movb %al, -0xc9(%rbp)
movl $0x0, -0xd0(%rbp)
testb $0x1, -0xc9(%rbp)
je 0xb205
movq -0x58(%rbp), %rdi
callq 0x34e0
movl %eax, -0xd0(%rbp)
movl -0xd0(%rbp), %eax
cmpl 0x813a(%rip), %eax      # 0x13318
jg 0xb1e9
cmpl $0x0, -0xd0(%rbp)
jge 0xb203
leaq 0x29e6(%rip), %rdi      # 0xdbd6
xorl %eax, %eax
callq 0x3070
jmp 0xb1f9
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x33e0
jmp 0xb205
leaq -0xf0(%rbp), %rdi
callq 0x6820
jmp 0xb213
movq -0x98(%rbp), %rsi
leaq -0xf0(%rbp), %rdi
callq 0x6b20
jmp 0xb228
leaq -0xf0(%rbp), %rdi
callq 0x77a0
movl %eax, -0x130(%rbp)
jmp 0xb23c
movl -0x130(%rbp), %eax
movl %eax, -0xf4(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x69f0
movl %eax, -0x134(%rbp)
jmp 0xb25c
movl -0x134(%rbp), %eax
movl %eax, -0xf8(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x82d0
movl %eax, -0x138(%rbp)
jmp 0xb27c
movl -0x138(%rbp), %eax
movl %eax, -0xfc(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x82b0
movl %eax, -0x13c(%rbp)
jmp 0xb29c
movl -0x13c(%rbp), %eax
movl %eax, -0x100(%rbp)
movl -0xfc(%rbp), %eax
imull -0x100(%rbp), %eax
cltq
movq %rax, -0x108(%rbp)
cmpl $0x1, -0xf8(%rbp)
jle 0xb2fd
movq 0x7cea(%rip), %rax      # 0x12fb8
movq (%rax), %rdi
leaq 0x2917(%rip), %rsi      # 0xdbef
movb $0x0, %al
callq 0x3470
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x33e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xb443
movl $0x20, %edi
callq 0x32f0
movq %rax, -0x148(%rbp)
jmp 0xb310
movq -0x148(%rbp), %rdi
movl -0xfc(%rbp), %esi
movl -0x100(%rbp), %edx
movl -0xf4(%rbp), %ecx
movl -0xf8(%rbp), %r8d
callq 0x6880
jmp 0xb337
movq -0x148(%rbp), %rax
movq %rax, -0x110(%rbp)
movl 0x7fcd(%rip), %eax      # 0x13318
incl %eax
movq %rsp, %rcx
movq %rcx, -0x118(%rbp)
leaq 0xf(,%rax,4), %rcx
andq $-0x10, %rcx
movq %rsp, %rsi
subq %rcx, %rsi
movq %rsi, -0x150(%rbp)
movq %rsi, %rsp
movq %rax, -0x120(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0xad10
jmp 0xb388
movq -0x150(%rbp), %rsi
movq -0x110(%rbp), %rdx
movl -0xd0(%rbp), %ecx
leaq -0xf0(%rbp), %rdi
callq 0xaea0
jmp 0xb3aa
movq -0x110(%rbp), %rdi
movq -0xb8(%rbp), %rsi
movl -0xf4(%rbp), %edx
callq 0x77c0
jmp 0xb3c5
movq -0x110(%rbp), %rax
movq %rax, -0x158(%rbp)
cmpq $0x0, %rax
je 0xb3f6
movq -0x158(%rbp), %rdi
callq 0x6910
movq -0x158(%rbp), %rdi
movl $0x20, %esi
callq 0x3300
movq -0x118(%rbp), %rax
movq %rax, %rsp
leaq -0xf0(%rbp), %rdi
callq 0x6910
leaq -0x40(%rbp), %rdi
callq 0xb510
leaq -0x28(%rbp), %rdi
callq 0xb570
movq %rbp, %rsp
popq %rbp
retq
movq -0x148(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
movl $0x20, %esi
callq 0x3300
leaq -0xf0(%rbp), %rdi
callq 0x6910
leaq -0x40(%rbp), %rdi
callq 0xb510
leaq -0x28(%rbp), %rdi
callq 0xb570
movq -0x80(%rbp), %rdi
callq 0x3560
nopw (%rax,%rax)