// File: /workspace/github_cpp_makefile_star2_O1/mhe[P]raytracerframework_cpp/lodepng.cpp
// Function: filter(unsigned char*, unsigned char const*, unsigned int, unsigned int, LodePNG_InfoColor const*)
static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, const LodePNG_InfoColor* info)
{
  /*
  For PNG filter method 0
  out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are the scanlines with 1 extra byte per scanline
  
  There is a nice heuristic described here: http://www.cs.toronto.edu/~cosmin/pngtech/optipng.html. It says:
   *  If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. use fixed filtering, with the filter None).
   * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply all five filters and select the filter that produces the smallest sum of absolute values per row.
  
  Here the above method is used mostly. Note though that it appears to be better to use the adaptive filtering on the plasma 8-bit palette example, but that image isn't the best reference for palette images in general.
  */
  
  unsigned bpp = LodePNG_InfoColor_getBpp(info);
  size_t linebytes = (w * bpp + 7) / 8; /*the width of a scanline in bytes, not including the filter type*/
  size_t bytewidth = (bpp + 7) / 8; /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
  const unsigned char* prevline = 0;
  unsigned x, y;
  unsigned heuristic;
  unsigned error = 0;
  
  if(bpp == 0) return 31; /*invalid color type*/
  
  /*choose heuristic as described above*/
  if(info->colorType == 3 || info->bitDepth < 8) heuristic = 0;
  else heuristic = 1;
  
  if(heuristic == 0) /*None filtertype for everything*/
  {
    for(y = 0; y < h; y++)
    {
      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
      size_t inindex = linebytes * y;
      const unsigned TYPE = 0;
      out[outindex] = TYPE; /*filter type byte*/
      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, TYPE);
      prevline = &in[inindex];
    }
  }
  else if(heuristic == 1) /*adaptive filtering*/
  {
    size_t sum[5];
    ucvector attempt[5]; /*five filtering attempts, one for each filter type*/
    size_t smallest = 0;
    unsigned type, bestType = 0;
    
    for(type = 0; type < 5; type++) ucvector_init(&attempt[type]);
    for(type = 0; type < 5; type++)
    {
      if(!ucvector_resize(&attempt[type], linebytes)) { error = 9949; break; }
    }
    
    if(!error)
    {
      for(y = 0; y < h; y++)
      {
        /*try the 5 filter types*/
        for(type = 0; type < 5; type++)
        {
          filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type);
          
          /*calculate the sum of the result*/
          sum[type] = 0;
          for(x = 0; x < attempt[type].size; x+=3) sum[type] += attempt[type].data[x]; /*note that not all pixels are checked to speed this up while still having probably the best choice*/
        
          /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
          if(type == 0 || sum[type] < smallest)
          {
            bestType = type;
            smallest = sum[type];
          }
        }
        
        prevline = &in[y * linebytes];
    
        /*now fill the out values*/
        out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
        for(x = 0; x < linebytes; x++) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x];
      }
    }
    
    for(type = 0; type < 5; type++) ucvector_cleanup(&attempt[type]);
  }
  #if 0 /*deflate the scanline with a fixed tree after every filter attempt to see which one deflates best. This is slow, and _does not work as expected_: the heuristic gives smaller result!*/
  else if(heuristic == 2) /*adaptive filtering by using deflate*/
  {
    size_t size[5];
    ucvector attempt[5]; /*five filtering attempts, one for each filter type*/
    size_t smallest;
    unsigned type = 0, bestType = 0;
    unsigned char* dummy;
    LodeZlib_DeflateSettings deflatesettings = LodeZlib_defaultDeflateSettings;
    deflatesettings.btype = 1; /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, to simulate the true case where the tree is the same for the whole image*/
    for(type = 0; type < 5; type++) { ucvector_init(&attempt[type]); ucvector_resize(&attempt[type], linebytes); }
    for(y = 0; y < h; y++) /*try the 5 filter types*/
    {
      for(type = 0; type < 5; type++)
      {
        filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type);
        size[type] = 0; dummy = 0;
        LodePNG_compress(&dummy, &size[type], attempt[type].data, attempt[type].size, &deflatesettings);
        free(dummy);
        /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/
        if(type == 0 || size[type] < smallest) { bestType = type; smallest = size[type]; }
      }
      prevline = &in[y * linebytes];
      out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
      for(x = 0; x < linebytes; x++) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x];
    }
    for(type = 0; type < 5; type++) ucvector_cleanup(&attempt[type]);
  }
  #endif
  
  return error;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x138, %rsp            # imm = 0x138
movl %ecx, %r15d
movq %rsi, %r14
movq %rdi, %rbx
movl (%r8), %ecx
movl 0x4(%r8), %eax
xorl %esi, %esi
cmpq $0x6, %rcx
ja 0x2527b
leaq 0xc904(%rip), %rsi      # 0x31b7c
movl (%rsi,%rcx,4), %esi
imull %eax, %esi
testl %esi, %esi
je 0x25329
imull %esi, %edx
addl $0x7, %edx
movl %edx, -0x2c(%rbp)
movl %edx, %r12d
shrl $0x3, %r12d
cmpl $0x3, %ecx
sete %cl
cmpl $0x8, %eax
setb %al
orb %cl, %al
cmpb $0x1, %al
jne 0x25333
testl %r15d, %r15d
je 0x25322
leaq 0x1(%r12), %rax
movl %r15d, %ecx
leaq 0x1(%rbx), %rdx
xorl %esi, %esi
movq %r14, %rdi
xorl %r8d, %r8d
movq %rax, %r9
imulq %rsi, %r9
movb $0x0, (%rbx,%r9)
testq %r8, %r8
je 0x252f1
cmpl $0x8, -0x2c(%rbp)
jb 0x2530a
xorl %r8d, %r8d
movb (%rdi,%r8), %r9b
movb %r9b, (%rdx,%r8)
incq %r8
cmpq %r8, %r12
jne 0x252df
jmp 0x2530a
cmpl $0x8, -0x2c(%rbp)
jb 0x2530a
xorl %r8d, %r8d
movb (%rdi,%r8), %r9b
movb %r9b, (%rdx,%r8)
incq %r8
cmpq %r8, %r12
jne 0x252fa
movq %rsi, %r8
imulq %r12, %r8
addq %r14, %r8
incq %rsi
addq %rax, %rdx
addq %r12, %rdi
cmpq %rcx, %rsi
jne 0x252c5
xorl %eax, %eax
jmp 0x25893
movl $0x1f, %eax
jmp 0x25893
movl %esi, -0x30(%rbp)
xorps %xmm0, %xmm0
leaq -0x160(%rbp), %rdi
movaps %xmm0, 0x60(%rdi)
movaps %xmm0, 0x50(%rdi)
movaps %xmm0, 0x40(%rdi)
movaps %xmm0, 0x30(%rdi)
movaps %xmm0, 0x20(%rdi)
movaps %xmm0, 0x10(%rdi)
movaps %xmm0, (%rdi)
movq $0x0, 0x70(%rdi)
movq %r12, %rsi
callq 0x1bb2f
testl %eax, %eax
je 0x253c0
movl %r15d, -0x48(%rbp)
movq %rbx, %r15
leaq -0x148(%rbp), %r13
movq $0x0, -0x50(%rbp)
xorl %ecx, %ecx
movq %rcx, %rbx
cmpq $0x4, %rcx
je 0x253b0
movq %r13, %rdi
movq %r12, %rsi
callq 0x1bb2f
addq $0x18, %r13
leaq 0x1(%rbx), %rcx
testl %eax, %eax
jne 0x25387
movl $0x26dd, %eax           # imm = 0x26DD
movq %rax, -0x50(%rbp)
cmpq $0x4, %rbx
setae %al
movq %r15, %rbx
movl -0x48(%rbp), %r15d
jmp 0x253cb
movl $0x26dd, %eax           # imm = 0x26DD
movq %rax, -0x50(%rbp)
xorl %eax, %eax
testl %r15d, %r15d
sete %cl
xorb $0x1, %al
orb %cl, %al
jne 0x2585f
movl -0x30(%rbp), %eax
addl $0x7, %eax
movl %eax, -0x30(%rbp)
movl %eax, %esi
shrl $0x3, %esi
leaq 0x1(%r12), %rax
movq %rax, -0x68(%rbp)
cmpl $0x2, %r12d
movl $0x1, %eax
cmovael %r12d, %eax
movq %rax, -0x80(%rbp)
movl %r15d, %eax
movq %rax, -0x78(%rbp)
movq %r12, %r15
subq %rsi, %r15
leaq 0x1(%rbx), %rax
movq %rax, -0x60(%rbp)
movq $0x0, -0x58(%rbp)
movq %r14, %rdx
movl $0x0, -0x3c(%rbp)
movq $0x0, -0x70(%rbp)
xorl %r13d, %r13d
movq %rsi, -0x38(%rbp)
movq %r14, -0x90(%rbp)
movq %rbx, -0x88(%rbp)
leaq (%rdx,%rsi), %r9
leaq (%rsi,%r13), %rax
movq %rax, -0xa8(%rbp)
xorl %r10d, %r10d
movq %rdx, %rbx
movq %rdx, -0x48(%rbp)
movq %r9, -0xb0(%rbp)
leaq (%r10,%r10,2), %rdx
movq -0x160(%rbp,%rdx,8), %r14
movzbl %r10b, %eax
leaq 0xc402(%rip), %rcx      # 0x31880
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
movq %r10, -0xa0(%rbp)
movq %rdx, -0x98(%rbp)
jmpq *%rax
testq %r13, %r13
je 0x25706
cmpl $0x8, -0x2c(%rbp)
jb 0x25758
xorl %eax, %eax
movb (%rbx,%rax), %dl
movb %dl, (%r14,%rax)
incq %rax
cmpq %rax, %r12
jne 0x254aa
jmp 0x25758
testq %r13, %r13
je 0x25665
cmpl $0x8, -0x30(%rbp)
jb 0x254e3
xorl %eax, %eax
movb (%rbx,%rax), %dl
subb (%r13,%rax), %dl
movb %dl, (%r14,%rax)
incq %rax
cmpq %rax, %rsi
jne 0x254cf
cmpl %r12d, %esi
jae 0x25758
xorl %r8d, %r8d
movq -0x38(%rbp), %rax
movq %r15, %r9
movq %r12, %rsi
movzbl (%rbx,%r8), %r10d
movzbl (%r13,%rax), %r15d
movq %r13, %r11
movzbl (%r13,%r8), %r13d
leal (%r15,%r10), %r12d
subl %r13d, %r12d
movl %r12d, %ecx
subl %r10d, %ecx
movl %ecx, %edx
negl %edx
cmovsl %ecx, %edx
movl %r12d, %ecx
subl %r15d, %ecx
movl %ecx, %edi
negl %edi
cmovsl %ecx, %edi
subl %r13d, %r12d
movl %r12d, %ecx
negl %ecx
cmovsl %r12d, %ecx
cmpl %ecx, %edi
ja 0x25541
movl %r15d, %r13d
movq -0x48(%rbp), %rbx
movb (%rbx,%rax), %r15b
cmpl %ecx, %edx
cmoval %r13d, %r10d
cmpl %edi, %edx
cmoval %r13d, %r10d
subb %r10b, %r15b
movb %r15b, (%r14,%rax)
incq %rax
incq %r8
movq %rsi, %r12
cmpq %rax, %rsi
movq %r9, %r15
movq %r11, %r13
movq -0xb0(%rbp), %r9
jne 0x254f3
jmp 0x25758
testq %r13, %r13
je 0x256a5
cmpl $0x8, -0x2c(%rbp)
jb 0x25758
xorl %eax, %eax
movb (%rbx,%rax), %dl
subb (%r13,%rax), %dl
movb %dl, (%r14,%rax)
incq %rax
cmpq %rax, %r12
jne 0x25595
jmp 0x25758
testq %r13, %r13
je 0x256c5
cmpl $0x8, -0x30(%rbp)
jb 0x255d9
xorl %eax, %eax
movb (%rbx,%rax), %dl
movb (%r13,%rax), %dil
shrb %dil
subb %dil, %dl
movb %dl, (%r14,%rax)
incq %rax
cmpq %rax, %rsi
jne 0x255bf
cmpl %r12d, %esi
jae 0x25758
movq -0x38(%rbp), %rax
addq %r14, %rax
xorl %edx, %edx
movb (%r9,%rdx), %dil
movzbl (%rbx,%rdx), %r8d
movq -0xa8(%rbp), %rcx
movzbl (%rcx,%rdx), %r10d
addl %r8d, %r10d
shrl %r10d
subb %r10b, %dil
movb %dil, (%rax,%rdx)
incq %rdx
cmpq %rdx, %r15
jne 0x255eb
jmp 0x25758
testq %r13, %r13
je 0x2571f
cmpl $0x8, -0x30(%rbp)
jb 0x2563a
xorl %eax, %eax
movb (%rbx,%rax), %dl
movb %dl, (%r14,%rax)
incq %rax
cmpq %rax, %rsi
jne 0x2562b
cmpl %r12d, %esi
jae 0x25758
movq -0x38(%rbp), %rax
addq %r14, %rax
xorl %edx, %edx
movb (%r9,%rdx), %dil
subb (%rbx,%rdx), %dil
movb %dil, (%rax,%rdx)
incq %rdx
cmpq %rdx, %r15
jne 0x2564c
jmp 0x25758
cmpl $0x8, -0x30(%rbp)
jb 0x2567c
xorl %eax, %eax
movb (%rbx,%rax), %cl
movb %cl, (%r14,%rax)
incq %rax
cmpq %rax, %rsi
jne 0x2566d
cmpl %r12d, %esi
jae 0x25758
movq -0x38(%rbp), %rax
addq %r14, %rax
xorl %edx, %edx
movb (%r9,%rdx), %cl
subb (%rbx,%rdx), %cl
movb %cl, (%rax,%rdx)
incq %rdx
cmpq %rdx, %r15
jne 0x2568e
jmp 0x25758
cmpl $0x8, -0x2c(%rbp)
jb 0x25758
xorl %eax, %eax
movb (%rbx,%rax), %dl
movb %dl, (%r14,%rax)
incq %rax
cmpq %rax, %r12
jne 0x256b1
jmp 0x25758
cmpl $0x8, -0x2c(%rbp)
jb 0x256dc
xorl %eax, %eax
movb (%rbx,%rax), %dl
movb %dl, (%r14,%rax)
incq %rax
cmpq %rax, %r12
jne 0x256cd
cmpl %r12d, %esi
jae 0x25758
movq -0x38(%rbp), %rax
addq %r14, %rax
xorl %edx, %edx
movb (%r9,%rdx), %dil
movb (%rbx,%rdx), %r8b
shrb %r8b
subb %r8b, %dil
movb %dil, (%rax,%rdx)
incq %rdx
cmpq %rdx, %r15
jne 0x256ea
jmp 0x25758
cmpl $0x8, -0x2c(%rbp)
jb 0x25758
xorl %eax, %eax
movb (%rbx,%rax), %dl
movb %dl, (%r14,%rax)
incq %rax
cmpq %rax, %r12
jne 0x2570e
jmp 0x25758
cmpl $0x8, -0x30(%rbp)
jb 0x25736
xorl %eax, %eax
movb (%rbx,%rax), %dl
movb %dl, (%r14,%rax)
incq %rax
cmpq %rax, %rsi
jne 0x25727
cmpl %r12d, %esi
jae 0x25758
movq -0x38(%rbp), %rax
addq %r14, %rax
xorl %edx, %edx
movb (%r9,%rdx), %dil
subb (%rbx,%rdx), %dil
movb %dil, (%rax,%rdx)
incq %rdx
cmpq %rdx, %r15
jne 0x25744
movq -0x98(%rbp), %rax
leaq -0x160(,%rax,8), %rax
addq %rbp, %rax
movq -0xa0(%rbp), %r10
movq $0x0, -0xe0(%rbp,%r10,8)
movq 0x8(%rax), %rax
testq %rax, %rax
je 0x257b2
movq -0xe0(%rbp,%r10,8), %rdx
movl $0x3, %r8d
xorl %edi, %edi
movzbl (%r14,%rdi), %ecx
addq %rcx, %rdx
movl %r8d, %edi
addl $0x3, %r8d
cmpq %rdi, %rax
ja 0x25796
movq %rdx, -0xe0(%rbp,%r10,8)
testq %r10, %r10
je 0x257c5
movq -0x70(%rbp), %rax
cmpq %rax, -0xe0(%rbp,%r10,8)
jae 0x257d5
movq -0xe0(%rbp,%r10,8), %rax
movq %rax, -0x70(%rbp)
movl %r10d, -0x3c(%rbp)
incq %r10
cmpq $0x5, %r10
movq -0x38(%rbp), %rsi
jne 0x25467
movq -0x68(%rbp), %rax
imulq -0x58(%rbp), %rax
movq -0x88(%rbp), %rbx
movl -0x3c(%rbp), %ecx
movb %cl, (%rbx,%rax)
cmpl $0x8, -0x2c(%rbp)
movq -0x80(%rbp), %rdi
movq -0x60(%rbp), %r8
jb 0x2582a
movl -0x3c(%rbp), %eax
leaq (%rax,%rax,2), %rax
movq -0x160(%rbp,%rax,8), %rax
xorl %ecx, %ecx
movb (%rax,%rcx), %dl
movb %dl, (%r8,%rcx)
incq %rcx
cmpq %rcx, %rdi
jne 0x2581b
movq -0x58(%rbp), %rcx
movq %rcx, %r13
imulq %r12, %r13
movq -0x90(%rbp), %r14
addq %r14, %r13
incq %rcx
movq -0x48(%rbp), %rdx
addq %r12, %rdx
addq -0x68(%rbp), %r8
movq %r8, -0x60(%rbp)
movq %rcx, -0x58(%rbp)
cmpq -0x78(%rbp), %rcx
jne 0x25447
xorl %ebx, %ebx
xorps %xmm0, %xmm0
movups %xmm0, -0x158(%rbp,%rbx)
movq -0x160(%rbp,%rbx), %rdi
callq 0x5390
movq $0x0, -0x160(%rbp,%rbx)
addq $0x18, %rbx
cmpq $0x78, %rbx
jne 0x25861
movq -0x50(%rbp), %rax
addq $0x138, %rsp            # imm = 0x138
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop