// File: /workspace/github_cpp_makefile_star2_O3/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 $0xf8, %rsp
movl %ecx, %r13d
xorl %r10d, %r10d
cmpl $0x6, %r8d
ja 0x23d98
movl %r8d, %eax
leaq 0xcdf8(%rip), %rcx      # 0x30b8c
movl (%rcx,%rax,4), %r10d
imull %r9d, %r10d
testl %r10d, %r10d
je 0x23e52
imull %r10d, %edx
addl $0x7, %edx
movl %edx, -0x2c(%rbp)
movl %edx, %eax
shrl $0x3, %eax
movq %rax, -0x50(%rbp)
cmpl $0x3, %r8d
sete %al
cmpl $0x8, %r9d
setb %cl
orb %al, %cl
cmpb $0x1, %cl
jne 0x23e5c
testl %r13d, %r13d
je 0x23e4b
movq -0x50(%rbp), %rbx
leaq 0x1(%rbx), %rax
movl %r13d, %ecx
leaq 0x1(%rdi), %rdx
xorl %r10d, %r10d
movq %rsi, %r11
xorl %r8d, %r8d
movq %rax, %r9
imulq %r10, %r9
movb $0x0, (%rdi,%r9)
testq %r8, %r8
je 0x23e1a
cmpl $0x8, -0x2c(%rbp)
jb 0x23e33
xorl %r8d, %r8d
movb (%r11,%r8), %r9b
movb %r9b, (%rdx,%r8)
incq %r8
cmpq %r8, %rbx
jne 0x23e08
jmp 0x23e33
cmpl $0x8, -0x2c(%rbp)
jb 0x23e33
xorl %r8d, %r8d
movb (%r11,%r8), %r9b
movb %r9b, (%rdx,%r8)
incq %r8
cmpq %r8, %rbx
jne 0x23e23
movq %r10, %r8
imulq %rbx, %r8
addq %rsi, %r8
incq %r10
addq %rax, %rdx
addq %rbx, %r11
cmpq %rcx, %r10
jne 0x23dee
xorl %ebx, %ebx
jmp 0x2436f
movl $0x1f, %ebx
jmp 0x2436f
movq %rdi, -0x58(%rbp)
movq %rsi, -0x60(%rbp)
addl $0x7, %r10d
movl %r10d, -0x30(%rbp)
movl %r10d, %r14d
shrl $0x3, %r14d
xorps %xmm0, %xmm0
movaps %xmm0, -0xc0(%rbp)
movaps %xmm0, -0xd0(%rbp)
movaps %xmm0, -0xe0(%rbp)
movaps %xmm0, -0xf0(%rbp)
movaps %xmm0, -0x100(%rbp)
movaps %xmm0, -0x110(%rbp)
movaps %xmm0, -0x120(%rbp)
movq $0x0, -0xb0(%rbp)
xorl %ebx, %ebx
leaq (%rbx,%rbp), %rdi
addq $-0x120, %rdi           # imm = 0xFEE0
movq -0x50(%rbp), %rsi
callq 0x1ab3c
testl %eax, %eax
je 0x24338
addq $0x18, %rbx
cmpq $0x78, %rbx
jne 0x23eb4
testl %r13d, %r13d
je 0x24334
movq -0x50(%rbp), %rcx
leaq 0x1(%rcx), %rsi
cmpl $0x2, %ecx
movl $0x1, %edi
cmovael %ecx, %edi
movl %r13d, %eax
movq %rcx, %r13
movq %rax, -0x70(%rbp)
movq %rcx, %r11
subq %r14, %r11
movq -0x58(%rbp), %rax
leaq 0x1(%rax), %r8
xorl %r9d, %r9d
movq -0x60(%rbp), %rax
movq %rax, %r10
xorl %r15d, %r15d
xorl %r12d, %r12d
xorl %edx, %edx
movq %r14, -0x38(%rbp)
movq %rsi, -0x80(%rbp)
movq %rdi, -0x78(%rbp)
movq %r8, -0x98(%rbp)
movq %r9, -0x90(%rbp)
imulq %r13, %r9
addq %rax, %r9
movq %r9, -0x88(%rbp)
leaq (%r10,%r14), %rax
movq %rax, -0x40(%rbp)
leaq (%rdx,%r14), %rax
movq %rax, -0xa8(%rbp)
xorl %ebx, %ebx
leaq (%rbx,%rbx,2), %rdi
movq -0x120(%rbp,%rdi,8), %rcx
movzbl %bl, %eax
leaq 0xc929(%rip), %rsi      # 0x3089c
movslq (%rsi,%rax,4), %rax
addq %rsi, %rax
movl %r15d, -0x44(%rbp)
movq %r12, -0x68(%rbp)
movq %rdi, -0xa0(%rbp)
jmpq *%rax
testq %rdx, %rdx
je 0x241fc
cmpl $0x8, -0x2c(%rbp)
jb 0x24254
xorl %eax, %eax
movb (%r10,%rax), %sil
movb %sil, (%rcx,%rax)
incq %rax
cmpq %rax, %r13
jne 0x23fa0
jmp 0x24254
testq %rdx, %rdx
je 0x2414e
cmpl $0x8, -0x30(%rbp)
jb 0x23fd8
xorl %esi, %esi
movb (%r10,%rsi), %al
subb (%rdx,%rsi), %al
movb %al, (%rcx,%rsi)
incq %rsi
cmpq %rsi, %r14
jne 0x23fc6
cmpl %r13d, %r14d
jae 0x24254
xorl %edi, %edi
movq -0x38(%rbp), %r15
movq %r11, %r12
movzbl (%r10,%rdi), %r8d
movzbl (%rdx,%r15), %r11d
movzbl (%rdx,%rdi), %r9d
leal (%r11,%r8), %eax
subl %r9d, %eax
movl %eax, %esi
subl %r8d, %esi
movl %esi, %r13d
negl %r13d
cmovsl %esi, %r13d
movl %eax, %r14d
subl %r11d, %r14d
movl %r14d, %esi
negl %esi
cmovsl %r14d, %esi
subl %r9d, %eax
movl %eax, %r14d
negl %r14d
cmovsl %eax, %r14d
cmpl %r14d, %esi
ja 0x24033
movl %r11d, %r9d
movb (%r10,%r15), %al
cmpl %r14d, %r13d
cmoval %r9d, %r8d
cmpl %esi, %r13d
cmoval %r9d, %r8d
subb %r8b, %al
movb %al, (%rcx,%r15)
incq %r15
incq %rdi
movq -0x50(%rbp), %r13
cmpq %r15, %r13
movq %r12, %r11
jne 0x23fe7
jmp 0x24254
testq %rdx, %rdx
je 0x24195
cmpl $0x8, -0x2c(%rbp)
jb 0x24254
xorl %esi, %esi
movb (%r10,%rsi), %al
subb (%rdx,%rsi), %al
movb %al, (%rcx,%rsi)
incq %rsi
cmpq %rsi, %r13
jne 0x24078
jmp 0x24254
testq %rdx, %rdx
je 0x241b6
cmpl $0x8, -0x30(%rbp)
jb 0x240b9
xorl %esi, %esi
movb (%r10,%rsi), %al
movb (%rdx,%rsi), %dil
shrb %dil
subb %dil, %al
movb %al, (%rcx,%rsi)
incq %rsi
cmpq %rsi, %r14
jne 0x240a0
cmpl %r13d, %r14d
movq -0x40(%rbp), %r14
jae 0x24254
movq -0x38(%rbp), %rax
leaq (%rcx,%rax), %rdi
xorl %esi, %esi
movb (%r14,%rsi), %al
movzbl (%r10,%rsi), %r8d
movq -0xa8(%rbp), %r9
movzbl (%r9,%rsi), %r9d
addl %r8d, %r9d
shrl %r9d
subb %r9b, %al
movb %al, (%rdi,%rsi)
incq %rsi
cmpq %rsi, %r11
jne 0x240d0
jmp 0x24254
testq %rdx, %rdx
je 0x24216
cmpl $0x8, -0x30(%rbp)
jb 0x2411f
xorl %eax, %eax
movb (%r10,%rax), %sil
movb %sil, (%rcx,%rax)
incq %rax
cmpq %rax, %r14
jne 0x2410f
cmpl %r13d, %r14d
movq -0x40(%rbp), %r8
jae 0x24254
movq -0x38(%rbp), %rax
leaq (%rcx,%rax), %rsi
xorl %edi, %edi
movb (%r8,%rdi), %al
subb (%r10,%rdi), %al
movb %al, (%rsi,%rdi)
incq %rdi
cmpq %rdi, %r11
jne 0x24136
jmp 0x24254
cmpl $0x8, -0x30(%rbp)
jb 0x24166
xorl %eax, %eax
movb (%r10,%rax), %sil
movb %sil, (%rcx,%rax)
incq %rax
cmpq %rax, %r14
jne 0x24156
cmpl %r13d, %r14d
movq -0x40(%rbp), %r8
jae 0x24254
movq -0x38(%rbp), %rax
leaq (%rcx,%rax), %rsi
xorl %edi, %edi
movb (%r8,%rdi), %al
subb (%r10,%rdi), %al
movb %al, (%rsi,%rdi)
incq %rdi
cmpq %rdi, %r11
jne 0x2417d
jmp 0x24254
cmpl $0x8, -0x2c(%rbp)
jb 0x24254
xorl %eax, %eax
movb (%r10,%rax), %sil
movb %sil, (%rcx,%rax)
incq %rax
cmpq %rax, %r13
jne 0x241a1
jmp 0x24254
cmpl $0x8, -0x2c(%rbp)
jb 0x241ce
xorl %eax, %eax
movb (%r10,%rax), %sil
movb %sil, (%rcx,%rax)
incq %rax
cmpq %rax, %r13
jne 0x241be
cmpl %r13d, %r14d
movq -0x40(%rbp), %r9
jae 0x24254
movq -0x38(%rbp), %rax
leaq (%rcx,%rax), %rsi
xorl %edi, %edi
movb (%r9,%rdi), %al
movb (%r10,%rdi), %r8b
shrb %r8b
subb %r8b, %al
movb %al, (%rsi,%rdi)
incq %rdi
cmpq %rdi, %r11
jne 0x241e1
jmp 0x24254
cmpl $0x8, -0x2c(%rbp)
jb 0x24254
xorl %eax, %eax
movb (%r10,%rax), %sil
movb %sil, (%rcx,%rax)
incq %rax
cmpq %rax, %r13
jne 0x24204
jmp 0x24254
cmpl $0x8, -0x30(%rbp)
jb 0x2422e
xorl %eax, %eax
movb (%r10,%rax), %sil
movb %sil, (%rcx,%rax)
incq %rax
cmpq %rax, %r14
jne 0x2421e
cmpl %r13d, %r14d
movq -0x40(%rbp), %r8
jae 0x24254
movq -0x38(%rbp), %rax
leaq (%rcx,%rax), %rsi
xorl %edi, %edi
movb (%r8,%rdi), %al
subb (%r10,%rdi), %al
movb %al, (%rsi,%rdi)
incq %rdi
cmpq %rdi, %r11
jne 0x24241
movq -0xa0(%rbp), %rax
leaq -0x120(,%rax,8), %rax
addq %rbp, %rax
movq 0x8(%rax), %r8
testq %r8, %r8
je 0x2429a
movl $0x3, %r9d
xorl %edi, %edi
xorl %esi, %esi
movq -0x38(%rbp), %r14
movl -0x44(%rbp), %r15d
movq -0x68(%rbp), %r12
movzbl (%rcx,%rsi), %eax
addq %rax, %rdi
movl %r9d, %esi
addl $0x3, %r9d
cmpq %rsi, %r8
ja 0x24285
jmp 0x242a8
xorl %edi, %edi
movq -0x38(%rbp), %r14
movl -0x44(%rbp), %r15d
movq -0x68(%rbp), %r12
testq %rbx, %rbx
sete %al
cmpq %r12, %rdi
setb %cl
orb %al, %cl
cmovneq %rdi, %r12
cmovnel %ebx, %r15d
incq %rbx
cmpq $0x5, %rbx
jne 0x23f5d
movq -0x80(%rbp), %rsi
movq %rsi, %rax
movq -0x90(%rbp), %r9
imulq %r9, %rax
movq -0x58(%rbp), %rcx
movb %r15b, (%rcx,%rax)
cmpl $0x8, -0x2c(%rbp)
movq -0x78(%rbp), %rdi
movq -0x98(%rbp), %r8
jb 0x24316
movl %r15d, %eax
leaq (%rax,%rax,2), %rax
movq -0x120(%rbp,%rax,8), %rax
xorl %ecx, %ecx
movb (%rax,%rcx), %dl
movb %dl, (%r8,%rcx)
incq %rcx
cmpq %rcx, %rdi
jne 0x24307
incq %r9
addq %r13, %r10
addq %rsi, %r8
cmpq -0x70(%rbp), %r9
movq -0x60(%rbp), %rax
movq -0x88(%rbp), %rdx
jne 0x23f2c
xorl %ebx, %ebx
jmp 0x2433d
movl $0x26dd, %ebx           # imm = 0x26DD
xorl %r14d, %r14d
xorps %xmm0, %xmm0
movups %xmm0, -0x118(%rbp,%r14)
movq -0x120(%rbp,%r14), %rdi
callq 0x4380
movq $0x0, -0x120(%rbp,%r14)
addq $0x18, %r14
cmpq $0x78, %r14
jne 0x24340
movl %ebx, %eax
addq $0xf8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop