// File: /workspace/github_c_makefile_star2_O2/tditlu[P]shadetabler/src/lodepng/lodepng.c
// Function: filter
static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h,
                       const LodePNGColorMode* color, const LodePNGEncoderSettings* settings) {
  /*
  For PNG filter method 0
  out must be a buffer with as size: h + (w * h * bpp + 7u) / 8u, because there are
  the scanlines with 1 extra byte per scanline
  */

  unsigned bpp = lodepng_get_bpp(color);
  /*the width of a scanline in bytes, not including the filter type*/
  size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u;

  /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
  size_t bytewidth = (bpp + 7u) / 8u;
  const unsigned char* prevline = 0;
  unsigned x, y;
  unsigned error = 0;
  LodePNGFilterStrategy strategy = settings->filter_strategy;

  /*
  There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard:
   *  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.
  This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true.

  If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed,
  but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum
  heuristic is used.
  */
  if(settings->filter_palette_zero &&
     (color->colortype == LCT_PALETTE || color->bitdepth < 8)) strategy = LFS_ZERO;

  if(bpp == 0) return 31; /*error: invalid color type*/

  if(strategy >= LFS_ZERO && strategy <= LFS_FOUR) {
    unsigned char type = (unsigned char)strategy;
    for(y = 0; y != h; ++y) {
      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
      size_t inindex = linebytes * y;
      out[outindex] = type; /*filter type byte*/
      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);
      prevline = &in[inindex];
    }
  } else if(strategy == LFS_MINSUM) {
    /*adaptive filtering*/
    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
    size_t smallest = 0;
    unsigned char type, bestType = 0;

    for(type = 0; type != 5; ++type) {
      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
      if(!attempt[type]) error = 83; /*alloc fail*/
    }

    if(!error) {
      for(y = 0; y != h; ++y) {
        /*try the 5 filter types*/
        for(type = 0; type != 5; ++type) {
          size_t sum = 0;
          filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);

          /*calculate the sum of the result*/
          if(type == 0) {
            for(x = 0; x != linebytes; ++x) sum += (unsigned char)(attempt[type][x]);
          } else {
            for(x = 0; x != linebytes; ++x) {
              /*For differences, each byte should be treated as signed, values above 127 are negative
              (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there.
              This means filtertype 0 is almost never chosen, but that is justified.*/
              unsigned char s = attempt[type][x];
              sum += s < 128 ? s : (255U - s);
            }
          }

          /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
          if(type == 0 || sum < smallest) {
            bestType = type;
            smallest = sum;
          }
        }

        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][x];
      }
    }

    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
  } else if(strategy == LFS_ENTROPY) {
    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
    size_t bestSum = 0;
    unsigned type, bestType = 0;
    unsigned count[256];

    for(type = 0; type != 5; ++type) {
      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
      if(!attempt[type]) error = 83; /*alloc fail*/
    }

    if(!error) {
      for(y = 0; y != h; ++y) {
        /*try the 5 filter types*/
        for(type = 0; type != 5; ++type) {
          size_t sum = 0;
          filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
          lodepng_memset(count, 0, 256 * sizeof(*count));
          for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]];
          ++count[type]; /*the filter type itself is part of the scanline*/
          for(x = 0; x != 256; ++x) {
            sum += ilog2i(count[x]);
          }
          /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
          if(type == 0 || sum > bestSum) {
            bestType = type;
            bestSum = sum;
          }
        }

        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][x];
      }
    }

    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
  } else if(strategy == LFS_PREDEFINED) {
    for(y = 0; y != h; ++y) {
      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
      size_t inindex = linebytes * y;
      unsigned char type = settings->predefined_filters[y];
      out[outindex] = type; /*filter type byte*/
      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);
      prevline = &in[inindex];
    }
  } else if(strategy == LFS_BRUTE_FORCE) {
    /*brute force filter chooser.
    deflate the scanline after every filter attempt to see which one deflates best.
    This is very slow and gives only slightly smaller, sometimes even larger, result*/
    size_t size[5];
    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
    size_t smallest = 0;
    unsigned type = 0, bestType = 0;
    unsigned char* dummy;
    LodePNGCompressSettings zlibsettings;
    lodepng_memcpy(&zlibsettings, &settings->zlibsettings, sizeof(LodePNGCompressSettings));
    /*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. Sometimes it gives
    better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare
    cases better compression. It does make this a bit less slow, so it's worth doing this.*/
    zlibsettings.btype = 1;
    /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG
    images only, so disable it*/
    zlibsettings.custom_zlib = 0;
    zlibsettings.custom_deflate = 0;
    for(type = 0; type != 5; ++type) {
      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
      if(!attempt[type]) error = 83; /*alloc fail*/
    }
    if(!error) {
      for(y = 0; y != h; ++y) /*try the 5 filter types*/ {
        for(type = 0; type != 5; ++type) {
          unsigned testsize = (unsigned)linebytes;
          /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/

          filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
          size[type] = 0;
          dummy = 0;
          zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings);
          lodepng_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][x];
      }
    }
    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
  }
  else return 88; /* unknown filter strategy */

  return error;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4c8, %rsp            # imm = 0x4C8
movq %r9, %r14
movq %r8, %r13
movl %ecx, %ebp
movl %edx, %r12d
movq %rsi, 0x20(%rsp)
movq %rdi, 0x18(%rsp)
movq %r8, %rdi
callq 0x4b2b
movl %r12d, %ecx
shrl $0x3, %ecx
movl %eax, %edx
imulq %rcx, %rdx
andl $0x7, %r12d
imull %eax, %r12d
addl $0x7, %r12d
shrl $0x3, %r12d
leaq (%rdx,%r12), %r15
leaq (%rdx,%r12), %rcx
incq %rcx
movq %rcx, 0x38(%rsp)
leal 0x7(%rax), %ecx
shrl $0x3, %ecx
movq %rcx, 0x40(%rsp)
movl 0x38(%r14), %ecx
cmpl $0x0, 0x34(%r14)
pushq $0x1f
popq %r12
je 0xc1a2
cmpl $0x3, (%r13)
je 0xc197
cmpl $0x8, 0x4(%r13)
jae 0xc1a2
xorl %ecx, %ecx
testl %eax, %eax
jne 0xc1af
jmp 0xc330
testl %eax, %eax
je 0xc330
cmpl $0x4, %ecx
ja 0xc1f9
movl %ebp, %ebx
movq 0x18(%rsp), %r12
incq %r12
movzbl %cl, %ebp
xorl %edx, %edx
movq 0x20(%rsp), %rax
subq $0x1, %rbx
jb 0xc32d
movq %rax, %r14
movb %bpl, -0x1(%r12)
movq %r12, %rdi
movq %rax, %rsi
movq %r15, %rcx
movq 0x40(%rsp), %r8
movl %ebp, %r9d
callq 0xc7b2
addq 0x38(%rsp), %r12
leaq (%r14,%r15), %rax
movq %r14, %rdx
jmp 0xc1c3
addl $-0x5, %ecx
cmpl $0x3, %ecx
ja 0xc3c9
leaq 0x3068(%rip), %rax      # 0xf274
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
xorl %ebx, %ebx
pushq $0x53
popq %r14
xorl %r12d, %r12d
cmpq $0x5, %rbx
je 0xc36d
movq %r15, %rdi
callq 0x1130
movq %rax, 0xc0(%rsp,%rbx,8)
testq %rax, %rax
cmovel %r14d, %r12d
incq %rbx
jmp 0xc21e
leaq 0xc0(%rsp), %r13
pushq $0x30
popq %rdx
movq %r13, %rdi
movq %r14, %rsi
callq 0x4a33
movl $0x1, (%r13)
xorps %xmm0, %xmm0
movups %xmm0, 0x18(%r13)
xorl %ebx, %ebx
pushq $0x53
popq %r14
movq $0x0, 0x8(%rsp)
movq 0x18(%rsp), %r12
cmpq $0x5, %rbx
je 0xc2aa
movq %r15, %rdi
callq 0x1130
movq %rax, 0x90(%rsp,%rbx,8)
testq %rax, %rax
movq 0x8(%rsp), %rax
cmovel %r14d, %eax
movq %rax, 0x8(%rsp)
incq %rbx
jmp 0xc27e
cmpl $0x0, 0x8(%rsp)
movq 0x20(%rsp), %rax
je 0xc3d2
xorl %ebx, %ebx
movq 0x8(%rsp), %r12
cmpq $0x5, %rbx
je 0xc330
movq 0x90(%rsp,%rbx,8), %rdi
callq 0x1030
incq %rbx
jmp 0xc2c1
movl %ebp, %ebx
incq 0x18(%rsp)
xorl %r12d, %r12d
xorl %edx, %edx
movq 0x20(%rsp), %rax
cmpq %r12, %rbx
je 0xc32d
movq %rax, %r13
movq 0x40(%r14), %rax
movzbl (%rax,%r12), %r9d
movq 0x18(%rsp), %rbp
movb %r9b, -0x1(%rbp)
movq %rbp, %rdi
movq %r13, %rsi
movq %r15, %rcx
movq 0x40(%rsp), %r8
callq 0xc7b2
incq %r12
addq 0x38(%rsp), %rbp
movq %rbp, 0x18(%rsp)
leaq (%r15,%r13), %rax
movq %r13, %rdx
jmp 0xc2ea
xorl %r12d, %r12d
movl %r12d, %eax
addq $0x4c8, %rsp            # imm = 0x4C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %ebx, %ebx
pushq $0x53
popq %r14
xorl %r12d, %r12d
cmpq $0x5, %rbx
je 0xc395
movq %r15, %rdi
callq 0x1130
movq %rax, 0x60(%rsp,%rbx,8)
testq %rax, %rax
cmovel %r14d, %r12d
incq %rbx
jmp 0xc34e
movq %r12, 0x8(%rsp)
testl %r12d, %r12d
je 0xc4f7
xorl %ebx, %ebx
cmpq $0x5, %rbx
je 0xc3bf
movq 0xc0(%rsp,%rbx,8), %rdi
callq 0x1030
incq %rbx
jmp 0xc37d
movq %r12, 0x8(%rsp)
testl %r12d, %r12d
movq 0x20(%rsp), %rax
je 0xc601
xorl %ebx, %ebx
cmpq $0x5, %rbx
je 0xc3bf
movq 0x60(%rsp,%rbx,8), %rdi
callq 0x1030
incq %rbx
jmp 0xc3aa
movq 0x8(%rsp), %r12
jmp 0xc330
pushq $0x58
popq %r12
jmp 0xc330
movl %r15d, %ecx
movq %rcx, 0x30(%rsp)
movl %ebp, %ecx
movq %rcx, 0x58(%rsp)
xorl %edi, %edi
movq $0x0, 0x28(%rsp)
xorl %ebx, %ebx
xorl %r14d, %r14d
cmpq 0x58(%rsp), %rdi
je 0xc2ba
movq %r15, %rcx
movq %rdi, 0x48(%rsp)
imulq %rdi, %rcx
addq %rax, %rcx
movq %rcx, 0x10(%rsp)
xorl %r13d, %r13d
xorl %ebp, %ebp
cmpq $0x5, %rbp
je 0xc4a9
movq 0x90(%rsp,%rbp,8), %r12
movzbl %bpl, %r9d
movq %r12, %rdi
movq 0x10(%rsp), %rsi
movq 0x28(%rsp), %rdx
movq %r15, %rcx
movq 0x40(%rsp), %r8
callq 0xc7b2
andq $0x0, 0x60(%rsp,%rbp,8)
leaq (%rsp,%r13), %rsi
addq $0x60, %rsi
andq $0x0, 0x50(%rsp)
leaq 0x50(%rsp), %rdi
movq %r12, %rdx
movq 0x18(%rsp), %r12
movq 0x30(%rsp), %rcx
leaq 0xc0(%rsp), %r8
callq 0xc9a9
movq 0x50(%rsp), %rdi
callq 0x1030
testq %r13, %r13
sete %al
movq 0x60(%rsp,%rbp,8), %rcx
cmpq %rbx, %rcx
setb %dl
orb %al, %dl
cmovneq %rcx, %rbx
cmovnel %ebp, %r14d
incq %rbp
addq $0x8, %r13
jmp 0xc415
movq 0x38(%rsp), %rcx
movq 0x48(%rsp), %rdi
imulq %rdi, %rcx
leaq (%r12,%rcx), %rax
movb %r14b, (%r12,%rcx)
movl %r14d, %ecx
xorl %edx, %edx
movl %edx, %edx
cmpq %rdx, %r15
je 0xc4e0
movq 0x90(%rsp,%rcx,8), %rsi
movb (%rsi,%rdx), %sil
movb %sil, 0x1(%rax,%rdx)
incl %edx
jmp 0xc4c4
incq %rdi
movq 0x10(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x20(%rsp), %rax
jmp 0xc3f1
movl %ebp, %eax
movq %rax, 0x30(%rsp)
xorl %edi, %edi
xorl %r12d, %r12d
xorl %eax, %eax
movq $0x0, 0x10(%rsp)
cmpq 0x30(%rsp), %rdi
je 0xc37b
movq %r15, %r14
movq %rdi, 0x28(%rsp)
imulq %rdi, %r14
addq 0x20(%rsp), %r14
xorl %ebp, %ebp
movzbl %al, %ebx
cmpq $0x5, %rbp
je 0xc5bc
movq 0xc0(%rsp,%rbp,8), %r13
movzbl %bpl, %r9d
movq %r13, %rdi
movq %r14, %rsi
movq 0x10(%rsp), %rdx
movq %r15, %rcx
movq 0x40(%rsp), %r8
callq 0xc7b2
xorl %eax, %eax
xorl %ecx, %ecx
testq %rbp, %rbp
je 0xc592
movl %ecx, %ecx
cmpq %rcx, %r15
je 0xc599
movzbl (%r13,%rcx), %edx
movl %edx, %esi
xorl $0xff, %esi
testb %dl, %dl
cmovnsl %edx, %esi
addq %rsi, %rax
incl %ecx
jmp 0xc566
movzbl (%r13,%rcx), %edx
addq %rdx, %rax
incl %ecx
movl %ecx, %ecx
cmpq %rcx, %r15
jne 0xc587
testq %rbp, %rbp
sete %cl
cmpq %r12, %rax
setb %dl
orb %cl, %dl
cmovneq %rax, %r12
movzbl %bpl, %eax
cmovnel %eax, %ebx
incq %rbp
movl %ebx, %eax
jmp 0xc52c
movq 0x38(%rsp), %rdx
movq 0x28(%rsp), %rdi
imulq %rdi, %rdx
movq 0x18(%rsp), %rsi
leaq (%rsi,%rdx), %rcx
movb %bl, (%rsi,%rdx)
xorl %edx, %edx
movl %edx, %edx
cmpq %rdx, %r15
je 0xc5f4
movq 0xc0(%rsp,%rbx,8), %rsi
movb (%rsi,%rdx), %sil
movb %sil, 0x1(%rcx,%rdx)
incl %edx
jmp 0xc5d8
incq %rdi
movq %r14, 0x10(%rsp)
jmp 0xc50e
movl %ebp, %ecx
movq %rcx, 0x48(%rsp)
xorl %edi, %edi
pushq $0x1
popq %r12
xorl %r14d, %r14d
xorl %ebp, %ebp
movq $0x0, 0x28(%rsp)
cmpq 0x48(%rsp), %rdi
je 0xc3a8
movq %r15, %rcx
movq %rdi, 0x30(%rsp)
imulq %rdi, %rcx
addq %rax, %rcx
movq %rcx, 0x10(%rsp)
xorl %ebx, %ebx
cmpq $0x5, %rbx
je 0xc763
movq 0x60(%rsp,%rbx,8), %r13
movzbl %bl, %r9d
movq %r13, %rdi
movq 0x10(%rsp), %rsi
movq 0x28(%rsp), %rdx
movq %r15, %rcx
movq 0x40(%rsp), %r8
callq 0xc7b2
xorl %eax, %eax
cmpq $0x400, %rax            # imm = 0x400
je 0xc681
movb $0x0, 0xc0(%rsp,%rax)
incq %rax
jmp 0xc66c
xorl %eax, %eax
movl %eax, %eax
cmpq %rax, %r15
je 0xc69b
movzbl (%r13,%rax), %ecx
incl 0xc0(%rsp,%rcx,4)
incl %eax
jmp 0xc683
incl 0xc0(%rsp,%rbx,4)
xorl %edx, %edx
xorl %eax, %eax
cmpq $0x100, %rdx            # imm = 0x100
je 0xc746
movl 0xc0(%rsp,%rdx,4), %esi
testq %rsi, %rsi
je 0xc739
movl %esi, %ecx
shrl $0x10, %ecx
xorl %edi, %edi
cmpl $0x10000, %esi          # imm = 0x10000
setae %dil
cmovbq %rsi, %rcx
shll $0x4, %edi
leaq 0x8(%rdi), %r8
movl %ecx, %r9d
shrl $0x8, %r9d
cmpq $0x100, %rcx            # imm = 0x100
cmovbq %rcx, %r9
cmovbq %rdi, %r8
leaq 0x4(%r8), %rdi
movl %r9d, %r10d
shrl $0x4, %r10d
cmpq $0x10, %r9
cmovbq %r9, %r10
cmovbq %r8, %rdi
leaq 0x2(%rdi), %rcx
movl %r10d, %r8d
shrl $0x2, %r8d
cmpq $0x4, %r10
cmovbq %r10, %r8
cmovbq %rdi, %rcx
cmpl $0x2, %r8d
sbbq $-0x1, %rcx
movl %r12d, %edi
shll %cl, %edi
imulq %rsi, %rcx
subq %rdi, %rsi
leaq (%rcx,%rsi,2), %rcx
jmp 0xc73b
xorl %ecx, %ecx
addq %rcx, %rax
incq %rdx
jmp 0xc6a6
testq %rbx, %rbx
sete %cl
cmpq %r14, %rax
seta %dl
orb %cl, %dl
cmovneq %rax, %r14
cmovnel %ebx, %ebp
incq %rbx
jmp 0xc63d
movq 0x38(%rsp), %rcx
movq 0x30(%rsp), %rdi
imulq %rdi, %rcx
movq 0x18(%rsp), %rdx
leaq (%rdx,%rcx), %rax
movb %bpl, (%rdx,%rcx)
movl %ebp, %ecx
xorl %edx, %edx
movl %edx, %edx
cmpq %rdx, %r15
je 0xc79b
movq 0x60(%rsp,%rcx,8), %rsi
movb (%rsi,%rdx), %sil
movb %sil, 0x1(%rax,%rdx)
incl %edx
jmp 0xc782
incq %rdi
movq 0x10(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x20(%rsp), %rax
jmp 0xc61c