// File: /workspace/github_c_makefile_star2_O1/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, %rbx
movl %ecx, %ebp
movl %edx, %r15d
movq %rsi, 0x10(%rsp)
movq %rdi, 0x8(%rsp)
movl (%r8), %r14d
movl 0x4(%r8), %r12d
movl %r14d, %edi
callq 0x58b3
imull %r12d, %eax
movl 0x38(%rbx), %ecx
xorl %edx, %edx
cmpl $0x8, %r12d
movl %ecx, %esi
cmovbl %edx, %esi
cmpl $0x3, %r14d
cmovel %edx, %esi
cmpl $0x0, 0x34(%rbx)
cmovel %ecx, %esi
testl %eax, %eax
je 0xe2a1
movl %r15d, %ecx
shrl $0x3, %ecx
imulq %rax, %rcx
andl $0x7, %r15d
imull %eax, %r15d
addl $0x7, %r15d
shrl $0x3, %r15d
leaq (%rcx,%r15), %r13
leaq (%rcx,%r15), %rdx
incq %rdx
addl $0x7, %eax
shrl $0x3, %eax
movq %rax, 0x40(%rsp)
cmpl $0x4, %esi
ja 0xe2ab
testl %ebp, %ebp
je 0xe29a
movl %ebp, %r15d
movq %rdx, 0x20(%rsp)
movq 0x8(%rsp), %r12
incq %r12
movzbl %sil, %ebx
xorl %edx, %edx
movq 0x40(%rsp), %rbp
movq 0x10(%rsp), %rax
movq %rax, %r14
movb %bl, -0x1(%r12)
movq %r12, %rdi
movq %rax, %rsi
movq %r13, %rcx
movq %rbp, %r8
movl %ebx, %r9d
callq 0xe8c9
addq 0x20(%rsp), %r12
leaq (%r14,%r13), %rax
movq %r14, %rdx
decq %r15
jne 0xe26d
xorl %eax, %eax
jmp 0xe8b7
movl $0x1f, %eax
jmp 0xe8b7
addl $-0x5, %esi
cmpl $0x3, %esi
ja 0xe8b2
leaq 0x3fa6(%rip), %rcx      # 0x12264
movslq (%rcx,%rsi,4), %rax
addq %rcx, %rax
movq %rdx, 0x20(%rsp)
jmpq *%rax
xorl %ebx, %ebx
movl $0x53, %r14d
xorl %r15d, %r15d
movq %r13, %rdi
callq 0x1140
movq %rax, 0xc0(%rsp,%rbx,8)
testq %rax, %rax
cmovel %r14d, %r15d
incq %rbx
cmpq $0x5, %rbx
jne 0xe2d7
movq %r15, 0x30(%rsp)
testl %r15d, %r15d
setne %al
testl %ebp, %ebp
sete %cl
orb %al, %cl
movq 0x10(%rsp), %rax
jne 0xe443
movl %ebp, %ecx
movq %rcx, 0x38(%rsp)
xorl %edi, %edi
movq 0x8(%rsp), %r8
movq $0x0, (%rsp)
xorl %ebp, %ebp
xorl %r14d, %r14d
movq %r8, 0x18(%rsp)
movq (%rsp), %rbx
movq %r13, %rcx
movq %rdi, 0x28(%rsp)
imulq %rdi, %rcx
addq %rax, %rcx
movq %rcx, (%rsp)
xorl %r15d, %r15d
movq 0xc0(%rsp,%r15,8), %r12
movzbl %r15b, %r9d
movq %r12, %rdi
movq (%rsp), %rsi
movq %rbx, %rdx
movq %r13, %rcx
movq 0x40(%rsp), %r8
callq 0xe8c9
testq %r15, %r15
je 0xe3a0
testq %r13, %r13
je 0xe3bd
xorl %ecx, %ecx
xorl %eax, %eax
movzbl (%r12,%rcx), %edx
movl %edx, %esi
xorl $0xff, %esi
testb %dl, %dl
cmovnsl %edx, %esi
addq %rsi, %rax
incq %rcx
movl %ecx, %edx
cmpq %rdx, %r13
jne 0xe37f
jmp 0xe3bf
testq %r13, %r13
je 0xe3bd
xorl %ecx, %ecx
xorl %eax, %eax
movzbl (%r12,%rcx), %edx
addq %rdx, %rax
incq %rcx
movl %ecx, %edx
cmpq %rdx, %r13
jne 0xe3a9
jmp 0xe3bf
xorl %eax, %eax
testq %r15, %r15
sete %cl
cmpq %r14, %rax
setb %dl
orb %cl, %dl
cmovneq %rax, %r14
movzbl %bpl, %ebp
cmovnel %r15d, %ebp
incq %r15
cmpq $0x5, %r15
jne 0xe34e
movq 0x20(%rsp), %rsi
movq %rsi, %rax
movq 0x28(%rsp), %rdi
imulq %rdi, %rax
movq 0x8(%rsp), %rcx
movb %bpl, (%rcx,%rax)
testq %r13, %r13
movq 0x18(%rsp), %r8
je 0xe42d
movzbl %bpl, %eax
movq 0xc0(%rsp,%rax,8), %rax
movl $0x1, %ecx
movb -0x1(%rax,%rcx), %dl
movb %dl, (%r8,%rcx)
movl %ecx, %edx
incq %rcx
cmpq %rdx, %r13
jne 0xe41b
incq %rdi
addq %rsi, %r8
cmpq 0x38(%rsp), %rdi
movq 0x10(%rsp), %rax
jne 0xe32f
xorl %ebx, %ebx
movq 0xc0(%rsp,%rbx,8), %rdi
callq 0x1030
incq %rbx
cmpq $0x5, %rbx
jne 0xe445
jmp 0xe8ab
movups (%rbx), %xmm0
movups 0x10(%rbx), %xmm1
movups 0x20(%rbx), %xmm2
movaps %xmm0, 0xc0(%rsp)
movaps %xmm2, 0xe0(%rsp)
movaps %xmm1, 0xd0(%rsp)
movl $0x1, 0xc0(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, 0xd8(%rsp)
xorl %ebx, %ebx
movl $0x53, %r14d
xorl %r15d, %r15d
movq %r13, %rdi
callq 0x1140
movq %rax, 0x90(%rsp,%rbx,8)
testq %rax, %rax
cmovel %r14d, %r15d
incq %rbx
cmpq $0x5, %rbx
jne 0xe4a4
movq %r15, 0x30(%rsp)
testl %r15d, %r15d
setne %al
testl %ebp, %ebp
sete %cl
orb %al, %cl
movq 0x10(%rsp), %rax
jne 0xe626
movl %r13d, %ecx
movq %rcx, 0x28(%rsp)
movl %ebp, %ecx
movq %rcx, 0x50(%rsp)
movq 0x8(%rsp), %rdi
xorl %r8d, %r8d
movl $0x0, 0x18(%rsp)
xorl %r15d, %r15d
movq $0x0, (%rsp)
movq %rdi, 0x38(%rsp)
movq (%rsp), %rbx
movq %r13, %rcx
movq %r8, 0x58(%rsp)
imulq %r8, %rcx
addq %rax, %rcx
movq %rcx, (%rsp)
leaq 0x60(%rsp), %rbp
xorl %r12d, %r12d
movq 0x90(%rsp,%r12,8), %r14
movzbl %r12b, %r9d
movq %r14, %rdi
movq (%rsp), %rsi
movq %rbx, %rdx
movq %r13, %rcx
movq 0x40(%rsp), %r8
callq 0xe8c9
xorl %eax, %eax
movq %rax, (%rbp)
movq %rax, 0x48(%rsp)
movq 0xd8(%rsp), %rax
leaq 0x48(%rsp), %rdi
movq %rbp, %rsi
movq %r14, %rdx
testq %rax, %rax
je 0xe586
movq 0x28(%rsp), %rcx
leaq 0xc0(%rsp), %r8
callq *%rax
jmp 0xe598
movq 0x28(%rsp), %rcx
leaq 0xc0(%rsp), %r8
callq 0x5071
movq 0x48(%rsp), %rdi
callq 0x1030
testq %r12, %r12
je 0xe5ad
cmpq %r15, (%rbp)
jae 0xe5b6
movq (%rbp), %r15
movl %r12d, 0x18(%rsp)
incq %r12
addq $0x8, %rbp
cmpq $0x5, %r12
jne 0xe52f
movq 0x20(%rsp), %rsi
movq %rsi, %rax
movq 0x58(%rsp), %r8
imulq %r8, %rax
movq 0x8(%rsp), %rcx
movl 0x18(%rsp), %edx
movb %dl, (%rcx,%rax)
testq %r13, %r13
movq 0x38(%rsp), %rdi
je 0xe610
movl 0x18(%rsp), %eax
movq 0x90(%rsp,%rax,8), %rax
movl $0x1, %ecx
movb -0x1(%rax,%rcx), %dl
movb %dl, (%rdi,%rcx)
movl %ecx, %edx
incq %rcx
cmpq %rdx, %r13
jne 0xe5ff
incq %r8
addq %rsi, %rdi
cmpq 0x50(%rsp), %r8
movq 0x10(%rsp), %rax
jne 0xe50b
xorl %ebx, %ebx
movq 0x90(%rsp,%rbx,8), %rdi
callq 0x1030
incq %rbx
cmpq $0x5, %rbx
jne 0xe628
jmp 0xe8ab
testl %ebp, %ebp
je 0xe29a
movl %ebp, %eax
movq %rax, (%rsp)
movq 0x8(%rsp), %rbp
incq %rbp
xorl %r12d, %r12d
xorl %edx, %edx
movq 0x40(%rsp), %r15
movq 0x10(%rsp), %rax
movq %rax, %r14
movq 0x40(%rbx), %rax
movzbl (%rax,%r12), %r9d
movb %r9b, -0x1(%rbp)
movq %rbp, %rdi
movq %r14, %rsi
movq %r13, %rcx
movq %r15, %r8
callq 0xe8c9
incq %r12
addq 0x20(%rsp), %rbp
leaq (%r14,%r13), %rax
movq %r14, %rdx
cmpq %r12, (%rsp)
jne 0xe668
jmp 0xe29a
xorl %ebx, %ebx
movl $0x53, %r14d
xorl %r15d, %r15d
movq %r13, %rdi
callq 0x1140
movq %rax, 0x60(%rsp,%rbx,8)
testq %rax, %rax
cmovel %r14d, %r15d
incq %rbx
cmpq $0x5, %rbx
jne 0xe6ae
movq %r15, 0x30(%rsp)
testl %r15d, %r15d
setne %al
testl %ebp, %ebp
sete %cl
orb %al, %cl
movq 0x10(%rsp), %rax
jne 0xe896
movl %ebp, %ecx
movq %rcx, 0x38(%rsp)
xorl %edi, %edi
movq 0x8(%rsp), %r8
movq $0x0, (%rsp)
xorl %ebp, %ebp
xorl %r14d, %r14d
movq %r8, 0x18(%rsp)
movq (%rsp), %r12
movq %r13, %rcx
movq %rdi, 0x28(%rsp)
imulq %rdi, %rcx
addq %rax, %rcx
movq %rcx, (%rsp)
xorl %r15d, %r15d
movq 0x60(%rsp,%r15,8), %rbx
movzbl %r15b, %r9d
movq %rbx, %rdi
movq (%rsp), %rsi
movq %r12, %rdx
movq %r13, %rcx
movq 0x40(%rsp), %r8
callq 0xe8c9
movl $0x400, %edx            # imm = 0x400
leaq 0xc0(%rsp), %rdi
xorl %esi, %esi
callq 0x10e0
testq %r13, %r13
je 0xe772
xorl %eax, %eax
movzbl (%rbx,%rax), %ecx
incl 0xc0(%rsp,%rcx,4)
incq %rax
movl %eax, %ecx
cmpq %rcx, %r13
jne 0xe75d
incl 0xc0(%rsp,%r15,4)
xorl %edx, %edx
xorl %eax, %eax
movl 0xc0(%rsp,%rdx,4), %esi
testq %rsi, %rsi
je 0xe806
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 $0x1, %edi
shll %cl, %edi
imulq %rsi, %rcx
subq %rdi, %rsi
leaq (%rcx,%rsi,2), %rcx
jmp 0xe808
xorl %ecx, %ecx
addq %rcx, %rax
incq %rdx
cmpq $0x100, %rdx            # imm = 0x100
jne 0xe77e
testq %r15, %r15
sete %cl
cmpq %r14, %rax
seta %dl
orb %cl, %dl
cmovneq %rax, %r14
cmovnel %r15d, %ebp
incq %r15
cmpq $0x5, %r15
jne 0xe722
movq 0x20(%rsp), %rsi
movq %rsi, %rax
movq 0x28(%rsp), %rdi
imulq %rdi, %rax
movq 0x8(%rsp), %rcx
movb %bpl, (%rcx,%rax)
testq %r13, %r13
movq 0x18(%rsp), %r8
je 0xe880
movl %ebp, %eax
movq 0x60(%rsp,%rax,8), %rax
movl $0x1, %ecx
movb -0x1(%rax,%rcx), %dl
movb %dl, (%r8,%rcx)
movl %ecx, %edx
incq %rcx
cmpq %rdx, %r13
jne 0xe86e
incq %rdi
addq %rsi, %r8
cmpq 0x38(%rsp), %rdi
movq 0x10(%rsp), %rax
jne 0xe703
xorl %ebx, %ebx
movq 0x60(%rsp,%rbx,8), %rdi
callq 0x1030
incq %rbx
cmpq $0x5, %rbx
jne 0xe898
movq 0x30(%rsp), %rax
jmp 0xe8b7
movl $0x58, %eax
addq $0x4c8, %rsp            # imm = 0x4C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq