// File: tomfunkhouser[P]gaps/pkgs/jpeg/jcsample.c
// Function: fullsize_smooth_downsample
METHODDEF(void)
fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
			    JSAMPARRAY input_data, JSAMPARRAY output_data)
{
  int outrow;
  JDIMENSION colctr;
  JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
  register JSAMPROW inptr, above_ptr, below_ptr, outptr;
  INT32 membersum, neighsum, memberscale, neighscale;
  int colsum, lastcolsum, nextcolsum;

  /* Expand input data enough to let all the output samples be generated
   * by the standard loop.  Special-casing padded output would be more
   * efficient.
   */
  expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
		    cinfo->image_width, output_cols);

  /* Each of the eight neighbor pixels contributes a fraction SF to the
   * smoothed pixel, while the main pixel contributes (1-8*SF).  In order
   * to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
   * Also recall that SF = smoothing_factor / 1024.
   */

  memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
  neighscale = cinfo->smoothing_factor * 64; /* scaled SF */

  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
    outptr = output_data[outrow];
    inptr = input_data[outrow];
    above_ptr = input_data[outrow-1];
    below_ptr = input_data[outrow+1];

    /* Special case for first column */
    colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
	     GETJSAMPLE(*inptr);
    membersum = GETJSAMPLE(*inptr++);
    nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
		 GETJSAMPLE(*inptr);
    neighsum = colsum + (colsum - membersum) + nextcolsum;
    membersum = membersum * memberscale + neighsum * neighscale;
    *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
    lastcolsum = colsum; colsum = nextcolsum;

    for (colctr = output_cols - 2; colctr > 0; colctr--) {
      membersum = GETJSAMPLE(*inptr++);
      above_ptr++; below_ptr++;
      nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
		   GETJSAMPLE(*inptr);
      neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
      membersum = membersum * memberscale + neighsum * neighscale;
      *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
      lastcolsum = colsum; colsum = nextcolsum;
    }

    /* Special case for last column */
    membersum = GETJSAMPLE(*inptr);
    neighsum = lastcolsum + (colsum - membersum) + colsum;
    membersum = membersum * memberscale + neighsum * neighscale;
    *outptr = (JSAMPLE) ((membersum + 32768) >> 16);

  }
}

// Assembly:
subq $0x88, %rsp
movq %rdi, 0x80(%rsp)
movq %rsi, 0x78(%rsp)
movq %rdx, 0x70(%rsp)
movq %rcx, 0x68(%rsp)
movq 0x78(%rsp), %rax
movl 0x1c(%rax), %eax
shll $0x3, %eax
movl %eax, 0x5c(%rsp)
movq 0x70(%rsp), %rdi
addq $-0x8, %rdi
movq 0x80(%rsp), %rax
movl 0x13c(%rax), %esi
addl $0x2, %esi
movq 0x80(%rsp), %rax
movl 0x30(%rax), %edx
movl 0x5c(%rsp), %ecx
callq 0xdd370
movq 0x80(%rsp), %rax
movslq 0x110(%rax), %rcx
shlq $0x9, %rcx
movl $0x10000, %eax          # imm = 0x10000
subq %rcx, %rax
movq %rax, 0x20(%rsp)
movq 0x80(%rsp), %rax
movl 0x110(%rax), %eax
shll $0x6, %eax
cltq
movq %rax, 0x18(%rsp)
movl $0x0, 0x64(%rsp)
movl 0x64(%rsp), %eax
movq 0x78(%rsp), %rcx
cmpl 0xc(%rcx), %eax
jge 0xdc9a9
movq 0x68(%rsp), %rax
movslq 0x64(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x38(%rsp)
movq 0x70(%rsp), %rax
movslq 0x64(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x50(%rsp)
movq 0x70(%rsp), %rax
movl 0x64(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x48(%rsp)
movq 0x70(%rsp), %rax
movl 0x64(%rsp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x40(%rsp)
movq 0x48(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x48(%rsp)
movzbl (%rax), %eax
movq 0x40(%rsp), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, 0x40(%rsp)
movzbl (%rcx), %ecx
addl %ecx, %eax
movq 0x50(%rsp), %rcx
movzbl (%rcx), %ecx
addl %ecx, %eax
movl %eax, 0x14(%rsp)
movq 0x50(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x50(%rsp)
movzbl (%rax), %eax
cltq
movq %rax, 0x30(%rsp)
movq 0x48(%rsp), %rax
movzbl (%rax), %eax
movq 0x40(%rsp), %rcx
movzbl (%rcx), %ecx
addl %ecx, %eax
movq 0x50(%rsp), %rcx
movzbl (%rcx), %ecx
addl %ecx, %eax
movl %eax, 0xc(%rsp)
movslq 0x14(%rsp), %rax
movslq 0x14(%rsp), %rcx
subq 0x30(%rsp), %rcx
addq %rcx, %rax
movslq 0xc(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %rax
imulq 0x20(%rsp), %rax
movq 0x28(%rsp), %rcx
imulq 0x18(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rax
addq $0x8000, %rax           # imm = 0x8000
sarq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x38(%rsp)
movb %cl, (%rax)
movl 0x14(%rsp), %eax
movl %eax, 0x10(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x14(%rsp)
movl 0x5c(%rsp), %eax
subl $0x2, %eax
movl %eax, 0x60(%rsp)
cmpl $0x0, 0x60(%rsp)
jbe 0xdc935
movq 0x50(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x50(%rsp)
movzbl (%rax), %eax
cltq
movq %rax, 0x30(%rsp)
movq 0x48(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x48(%rsp)
movq 0x40(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x40(%rsp)
movq 0x48(%rsp), %rax
movzbl (%rax), %eax
movq 0x40(%rsp), %rcx
movzbl (%rcx), %ecx
addl %ecx, %eax
movq 0x50(%rsp), %rcx
movzbl (%rcx), %ecx
addl %ecx, %eax
movl %eax, 0xc(%rsp)
movslq 0x10(%rsp), %rax
movslq 0x14(%rsp), %rcx
subq 0x30(%rsp), %rcx
addq %rcx, %rax
movslq 0xc(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %rax
imulq 0x20(%rsp), %rax
movq 0x28(%rsp), %rcx
imulq 0x18(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rax
addq $0x8000, %rax           # imm = 0x8000
sarq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, 0x38(%rsp)
movb %cl, (%rax)
movl 0x14(%rsp), %eax
movl %eax, 0x10(%rsp)
movl 0xc(%rsp), %eax
movl %eax, 0x14(%rsp)
movl 0x60(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x60(%rsp)
jmp 0xdc852
movq 0x50(%rsp), %rax
movzbl (%rax), %eax
cltq
movq %rax, 0x30(%rsp)
movslq 0x10(%rsp), %rax
movslq 0x14(%rsp), %rcx
subq 0x30(%rsp), %rcx
addq %rcx, %rax
movslq 0x14(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %rax
imulq 0x20(%rsp), %rax
movq 0x28(%rsp), %rcx
imulq 0x18(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rax
addq $0x8000, %rax           # imm = 0x8000
sarq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, (%rax)
movl 0x64(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x64(%rsp)
jmp 0xdc6fb
addq $0x88, %rsp
retq
nopw %cs:(%rax,%rax)