// File: brianwu02[P]ImageProcessing/briansFunctions.cpp
// Function: padImage(imageS*, int, imageS*)
void padImage(imageP I1, int sz, imageP paddedImg) {
    /* PIXEL REPLICATION PADDING
     * takes I1 as input image, I1 and applies pixel replication technique
     * to paddedImg using kernel size sz * sz.
     *   Pixel Replcation Example:
     *                             leftIdx         rightIdx
     *   AA|ABCDEFGH|HH                    x x x x
     *   AA|ABCDEFGH|HH        region0  |  region1  |  region2   y
     *   --------------        -------------------------------  topIdx
     *   AA|ABCDEFGH|HH        region3  |           |  region5   y
     *   II|IJKLMNOP|PP        region3  |  region4  |  region5   y
     *   QQ|QRSTUVWX|XX        region3  |  orig img |  region5   y
     *   YY|YZabcdef|ff        region3  |           |  region5   y
     *   gg|ghijklmn|nn        -------------------------------  botIdx
     *   oo|opqrstuv|vv        region6  | region 7  | region 8   y
     *   --------------
     *   oo|opqrstuv|vv       
     *   oo|opqrstuv|vv
     *   
     *   region0 = x <  leftIdx  and y <  topIdx
     *   region1 = x >= leftIdx  and x <  rightIdx and y <  topIdx 
     *   region2 = x >= rightIdx and y <  topIdx
     *   region3 = x <  leftIdx  and y >= topIdx   and y <  botIdx
     *   region4 = x >= leftIdx  and x <  rightIdx and y >= topIdx and y < botIdx
     *   region5 = x >= rightIdx and y >= topIdx   and y <  botIdx
     *   region6 = x <  leftIdx  and y >= botIdx
     *   region7 = x >= leftIdx  and x <  rightIdx and y >= botIdx
     *   region8 = x >= rightIdx and y >= botIdx
     *
     */

    int n = (sz - 1) / 2;
    int m = (sz - 1) / 2;
    unsigned char *in, *paddedOut;

    int total = I1->width * I1->height;
    int w = I1->width;
    int h = I1->height;

    paddedImg->width = (w + 2*m);
    paddedImg->height = (h + 2*n);

    int paddedTotal = paddedImg->height * paddedImg->width;
    paddedImg->image = (unsigned char*) malloc(paddedTotal);
    paddedOut = paddedImg->image;
    in = I1->image;

    int paddedHeight = paddedImg->height;
    int paddedWidth = paddedImg->width;

    // vertical indices that represent padding columns
    int leftIdx = n;
    int rightIdx = w + n;

    // horizontal indices that represent padding rows
    int topIdx = m;
    int botIdx = h + m;


    for (int y=0; y < paddedHeight; y++) {
        for (int x=0; x < paddedWidth; x++) {

            // this condition comes first since it will occur most frequent.
            // dont need the branch predictor working so hard.
            if (x >= leftIdx and x < rightIdx and y >= topIdx and y < botIdx) {
                // we are in region 4.
                paddedOut[y*paddedWidth+x] = in[(y-n) * w + (x-m)];

            } else if (x < leftIdx and y < topIdx) {
                // we are in region 0.
                // assign padded pixel as upper left original pixel value.
                paddedOut[y*paddedWidth+x] = in[0]; 

            } else if (x >= leftIdx and x < rightIdx and y < topIdx) {
                // we are in region 1.
                // assign pixel values to be top row of original image.
                paddedOut[y*paddedWidth+x] = in[(x-m)]; 
                
            } else if (x >= rightIdx and y < topIdx) {
                // we are in region 2.
                // assign padded pixels as upper right original pixel value.
                paddedOut[y*paddedWidth+x] = in[w-1];

            } else if (x < leftIdx and y >= topIdx and y < botIdx) {
                // we are in region 3.
                // assigned padded pixel as left most pixel of current row.
                paddedOut[y*paddedWidth+x] = in[(y - n) * w];

            } else if (x >= rightIdx and y >= topIdx and y < botIdx) {
                // we are in region 5
                // assign padded pixel as right most pixel of current row
                paddedOut[y*paddedWidth+x] = in[(y - n) * w + (w-1) ];

            } else if (x < leftIdx and y >= botIdx) {
                // we are in region 6
                // assign padded pixel as bottom left original pixel value.
                paddedOut[y*paddedWidth+x] = in[w*(h-1)];
            
            } else if (x >= leftIdx and x < rightIdx and y >= botIdx) {
                // we are in region 7
                // assign padded pixel to be bottom-most row of original input img.
                paddedOut[y*paddedWidth+x] = in[(h-1) * w + (x-m)];
            
            } else if (x >= rightIdx and y >= botIdx) {
                // we are in region 8
                // assign padded pixel as bottom right original pixel value.
                paddedOut[y*paddedWidth+x] = in[w*h-1];
            
            } else {
                // this should never happen since this will only occur if we have
                // not handled a certain x,y coordinate.
                cerr << "unhandled condition, something bad" << endl;
                cerr << "x is: " << x << " y is: " << y << endl;
            }
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movl -0xc(%rbp), %eax
subl $0x1, %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, -0x1c(%rbp)
movl -0xc(%rbp), %eax
subl $0x1, %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movl (%rax), %eax
movq -0x8(%rbp), %rcx
imull 0x4(%rcx), %eax
movl %eax, -0x34(%rbp)
movq -0x8(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x38(%rbp)
movq -0x8(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x3c(%rbp)
movl -0x38(%rbp), %ecx
movl -0x20(%rbp), %eax
shll %eax
addl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, (%rax)
movl -0x3c(%rbp), %ecx
movl -0x1c(%rbp), %eax
shll %eax
addl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x18(%rbp), %rax
movl 0x4(%rax), %eax
movq -0x18(%rbp), %rcx
imull (%rcx), %eax
movl %eax, -0x40(%rbp)
movslq -0x40(%rbp), %rdi
callq 0x1120
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x44(%rbp)
movq -0x18(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x48(%rbp)
movl -0x1c(%rbp), %eax
movl %eax, -0x4c(%rbp)
movl -0x38(%rbp), %eax
addl -0x1c(%rbp), %eax
movl %eax, -0x50(%rbp)
movl -0x20(%rbp), %eax
movl %eax, -0x54(%rbp)
movl -0x3c(%rbp), %eax
addl -0x20(%rbp), %eax
movl %eax, -0x58(%rbp)
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x44(%rbp), %eax
jge 0x24dd
movl $0x0, -0x60(%rbp)
movl -0x60(%rbp), %eax
cmpl -0x48(%rbp), %eax
jge 0x24cd
movl -0x60(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jl 0x2243
movl -0x60(%rbp), %eax
cmpl -0x50(%rbp), %eax
jge 0x2243
movl -0x5c(%rbp), %eax
cmpl -0x54(%rbp), %eax
jl 0x2243
movl -0x5c(%rbp), %eax
cmpl -0x58(%rbp), %eax
jge 0x2243
movq -0x28(%rbp), %rax
movl -0x5c(%rbp), %ecx
subl -0x1c(%rbp), %ecx
imull -0x38(%rbp), %ecx
movl -0x60(%rbp), %edx
subl -0x20(%rbp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %dl
movq -0x30(%rbp), %rax
movl -0x5c(%rbp), %ecx
imull -0x48(%rbp), %ecx
addl -0x60(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x24bd
movl -0x60(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0x2272
movl -0x5c(%rbp), %eax
cmpl -0x54(%rbp), %eax
jge 0x2272
movq -0x28(%rbp), %rax
movb (%rax), %dl
movq -0x30(%rbp), %rax
movl -0x5c(%rbp), %ecx
imull -0x48(%rbp), %ecx
addl -0x60(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x24bb
movl -0x60(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jl 0x22b3
movl -0x60(%rbp), %eax
cmpl -0x50(%rbp), %eax
jge 0x22b3
movl -0x5c(%rbp), %eax
cmpl -0x54(%rbp), %eax
jge 0x22b3
movq -0x28(%rbp), %rax
movl -0x60(%rbp), %ecx
subl -0x20(%rbp), %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %dl
movq -0x30(%rbp), %rax
movl -0x5c(%rbp), %ecx
imull -0x48(%rbp), %ecx
addl -0x60(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x24b9
movl -0x60(%rbp), %eax
cmpl -0x50(%rbp), %eax
jl 0x22ec
movl -0x5c(%rbp), %eax
cmpl -0x54(%rbp), %eax
jge 0x22ec
movq -0x28(%rbp), %rax
movl -0x38(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %dl
movq -0x30(%rbp), %rax
movl -0x5c(%rbp), %ecx
imull -0x48(%rbp), %ecx
addl -0x60(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x24b7
movl -0x60(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0x2331
movl -0x5c(%rbp), %eax
cmpl -0x54(%rbp), %eax
jl 0x2331
movl -0x5c(%rbp), %eax
cmpl -0x58(%rbp), %eax
jge 0x2331
movq -0x28(%rbp), %rax
movl -0x5c(%rbp), %ecx
subl -0x1c(%rbp), %ecx
imull -0x38(%rbp), %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %dl
movq -0x30(%rbp), %rax
movl -0x5c(%rbp), %ecx
imull -0x48(%rbp), %ecx
addl -0x60(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x24b5
movl -0x60(%rbp), %eax
cmpl -0x50(%rbp), %eax
jl 0x237e
movl -0x5c(%rbp), %eax
cmpl -0x54(%rbp), %eax
jl 0x237e
movl -0x5c(%rbp), %eax
cmpl -0x58(%rbp), %eax
jge 0x237e
movq -0x28(%rbp), %rax
movl -0x5c(%rbp), %ecx
subl -0x1c(%rbp), %ecx
imull -0x38(%rbp), %ecx
movl -0x38(%rbp), %edx
subl $0x1, %edx
addl %edx, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %dl
movq -0x30(%rbp), %rax
movl -0x5c(%rbp), %ecx
imull -0x48(%rbp), %ecx
addl -0x60(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x24b3
movl -0x60(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jge 0x23bd
movl -0x5c(%rbp), %eax
cmpl -0x58(%rbp), %eax
jl 0x23bd
movq -0x28(%rbp), %rax
movl -0x38(%rbp), %ecx
movl -0x3c(%rbp), %edx
subl $0x1, %edx
imull %edx, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %dl
movq -0x30(%rbp), %rax
movl -0x5c(%rbp), %ecx
imull -0x48(%rbp), %ecx
addl -0x60(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x24b1
movl -0x60(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jl 0x240a
movl -0x60(%rbp), %eax
cmpl -0x50(%rbp), %eax
jge 0x240a
movl -0x5c(%rbp), %eax
cmpl -0x58(%rbp), %eax
jl 0x240a
movq -0x28(%rbp), %rax
movl -0x3c(%rbp), %ecx
subl $0x1, %ecx
imull -0x38(%rbp), %ecx
movl -0x60(%rbp), %edx
subl -0x20(%rbp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %dl
movq -0x30(%rbp), %rax
movl -0x5c(%rbp), %ecx
imull -0x48(%rbp), %ecx
addl -0x60(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x24af
movl -0x60(%rbp), %eax
cmpl -0x50(%rbp), %eax
jl 0x2444
movl -0x5c(%rbp), %eax
cmpl -0x58(%rbp), %eax
jl 0x2444
movq -0x28(%rbp), %rax
movl -0x38(%rbp), %ecx
imull -0x3c(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %dl
movq -0x30(%rbp), %rax
movl -0x5c(%rbp), %ecx
imull -0x48(%rbp), %ecx
addl -0x60(%rbp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
jmp 0x24ad
movq 0x2ba5(%rip), %rdi      # 0x4ff0
leaq 0xc96(%rip), %rsi       # 0x30e8
callq 0x10a0
movq %rax, %rdi
movq 0x2b5f(%rip), %rsi      # 0x4fc0
callq 0x10b0
movq 0x2b83(%rip), %rdi      # 0x4ff0
leaq 0xc97(%rip), %rsi       # 0x310b
callq 0x10a0
movq %rax, %rdi
movl -0x60(%rbp), %esi
callq 0x1170
movq %rax, %rdi
leaq 0xc84(%rip), %rsi       # 0x3112
callq 0x10a0
movq %rax, %rdi
movl -0x5c(%rbp), %esi
callq 0x1170
movq %rax, %rdi
movq 0x2b18(%rip), %rsi      # 0x4fc0
callq 0x10b0
jmp 0x24af
jmp 0x24b1
jmp 0x24b3
jmp 0x24b5
jmp 0x24b7
jmp 0x24b9
jmp 0x24bb
jmp 0x24bd
jmp 0x24bf
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x21e2
jmp 0x24cf
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x21cf
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)