// File: /workspace/github_c_makefile_star2_O3/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
movl %r9d, %r13d
movl %r8d, %ebp
movl %ecx, %ebx
movl %edx, %r12d
movq %rsi, 0x18(%rsp)
movq %rdi, 0x8(%rsp)
movq 0x500(%rsp), %r15
movl %r8d, %edi
callq 0x5b92
imull %r13d, %eax
movl %r12d, %ecx
shrl $0x3, %ecx
imulq %rax, %rcx
andl $0x7, %r12d
imull %eax, %r12d
addl $0x7, %r12d
shrl $0x3, %r12d
leaq (%rcx,%r12), %r14
leal 0x7(%rax), %r8d
shrl $0x3, %r8d
movl 0x38(%r15), %edx
cmpl $0x0, 0x34(%r15)
je 0xe00a
cmpl $0x3, %ebp
sete %sil
cmpl $0x8, %r13d
setb %dil
orb %sil, %dil
je 0xe00a
xorl %edx, %edx
testl %eax, %eax
movq 0x8(%rsp), %r13
jne 0xe018
jmp 0xe06e
testl %eax, %eax
je 0xe06e
cmpl $0x4, %edx
ja 0xe078
movq 0x8(%rsp), %r13
testl %ebx, %ebx
je 0xe067
movl %ebx, %r15d
incq %r13
leaq (%r12,%rcx), %rax
incq %rax
movq %rax, 0x10(%rsp)
movzbl %dl, %ebp
xorl %edx, %edx
movq 0x18(%rsp), %rax
movq %rax, %rbx
movb %bpl, -0x1(%r13)
movq %r13, %rdi
movq %rax, %rsi
movq %r14, %rcx
movq %r8, %r12
movl %ebp, %r9d
callq 0xe6c5
movq %r12, %r8
addq 0x10(%rsp), %r13
leaq (%rbx,%r14), %rax
movq %rbx, %rdx
decq %r15
jne 0xe038
xorl %eax, %eax
jmp 0xe6b3
movl $0x1f, %eax
jmp 0xe6b3
addl $-0x5, %edx
cmpl $0x3, %edx
movq 0x8(%rsp), %rbp
ja 0xe6ae
leaq (%rcx,%r12), %rax
incq %rax
movq %rax, 0x40(%rsp)
leaq 0x42c8(%rip), %rax      # 0x12364
movslq (%rax,%rdx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movl %ebx, %r12d
movq %r8, 0x10(%rsp)
xorl %ebx, %ebx
movl $0x53, %ebp
xorl %r15d, %r15d
movq %r14, %rdi
callq 0x1140
movq %rax, 0xc0(%rsp,%rbx,8)
testq %rax, %rax
cmovel %ebp, %r15d
incq %rbx
cmpq $0x5, %rbx
jne 0xe0b7
movq %r15, 0x28(%rsp)
testl %r15d, %r15d
setne %al
testl %r12d, %r12d
sete %cl
orb %al, %cl
movq 0x18(%rsp), %rax
jne 0xe229
movl %r12d, %ecx
movq %rcx, 0x30(%rsp)
xorl %edi, %edi
movq 0x8(%rsp), %r8
movq $0x0, (%rsp)
xorl %r15d, %r15d
xorl %ebx, %ebx
movq %r8, 0x20(%rsp)
movq (%rsp), %r13
movq %r14, %rcx
movq %rdi, 0x38(%rsp)
imulq %rdi, %rcx
addq %rax, %rcx
movq %rcx, (%rsp)
xorl %r12d, %r12d
movq 0xc0(%rsp,%r12,8), %rbp
movzbl %r12b, %r9d
movq %rbp, %rdi
movq (%rsp), %rsi
movq %r13, %rdx
movq %r14, %rcx
movq 0x10(%rsp), %r8
callq 0xe6c5
testq %r12, %r12
je 0xe182
testq %r14, %r14
je 0xe19f
xorl %ecx, %ecx
xorl %eax, %eax
movzbl (%rbp,%rcx), %edx
movl %edx, %esi
xorl $0xff, %esi
testb %dl, %dl
cmovnsl %edx, %esi
addq %rsi, %rax
incq %rcx
movl %ecx, %edx
cmpq %rdx, %r14
jne 0xe161
jmp 0xe1a1
testq %r14, %r14
je 0xe19f
xorl %ecx, %ecx
xorl %eax, %eax
movzbl (%rbp,%rcx), %edx
addq %rdx, %rax
incq %rcx
movl %ecx, %edx
cmpq %rdx, %r14
jne 0xe18b
jmp 0xe1a1
xorl %eax, %eax
testq %r12, %r12
sete %cl
cmpq %rbx, %rax
setb %dl
orb %cl, %dl
cmovneq %rax, %rbx
movzbl %r12b, %eax
movzbl %r15b, %r15d
cmovnel %eax, %r15d
incq %r12
cmpq $0x5, %r12
jne 0xe130
movq 0x40(%rsp), %rsi
movq %rsi, %rax
movq 0x38(%rsp), %rdi
imulq %rdi, %rax
movq 0x8(%rsp), %rcx
movb %r15b, (%rcx,%rax)
testq %r14, %r14
movq 0x20(%rsp), %r8
je 0xe213
movzbl %r15b, %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, %r14
jne 0xe201
incq %rdi
addq %rsi, %r8
cmpq 0x30(%rsp), %rdi
movq 0x18(%rsp), %rax
jne 0xe111
xorl %ebx, %ebx
movq 0xc0(%rsp,%rbx,8), %rdi
callq 0x1030
incq %rbx
cmpq $0x5, %rbx
jne 0xe22b
jmp 0xe6a7
movl %ebx, %r12d
movq %r8, 0x10(%rsp)
movups (%r15), %xmm0
movups 0x10(%r15), %xmm1
movups 0x20(%r15), %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, %ebp
xorl %r15d, %r15d
movq %r14, %rdi
callq 0x1140
movq %rax, 0x90(%rsp,%rbx,8)
testq %rax, %rax
cmovel %ebp, %r15d
incq %rbx
cmpq $0x5, %rbx
jne 0xe294
movq %r15, 0x28(%rsp)
testl %r15d, %r15d
setne %al
testl %r12d, %r12d
sete %cl
orb %al, %cl
movq 0x18(%rsp), %rax
jne 0xe420
movl %r14d, %ecx
movq %rcx, 0x20(%rsp)
movl %r12d, %ecx
movq %rcx, 0x50(%rsp)
movq 0x8(%rsp), %rdi
xorl %r8d, %r8d
xorl %r12d, %r12d
xorl %r15d, %r15d
movq $0x0, (%rsp)
movq %rdi, 0x30(%rsp)
movq (%rsp), %rcx
movq %rcx, 0x38(%rsp)
movq %r14, %rcx
movq %r8, 0x58(%rsp)
imulq %r8, %rcx
addq %rax, %rcx
movq %rcx, (%rsp)
xorl %r13d, %r13d
xorl %ebp, %ebp
movq 0x90(%rsp,%rbp,8), %rbx
movzbl %bpl, %r9d
movq %rbx, %rdi
movq (%rsp), %rsi
movq 0x38(%rsp), %rdx
movq %r14, %rcx
movq 0x10(%rsp), %r8
callq 0xe6c5
leaq (%rsp,%r13), %rsi
addq $0x60, %rsi
xorl %eax, %eax
movq %rax, 0x60(%rsp,%rbp,8)
movq %rax, 0x48(%rsp)
movq 0xd8(%rsp), %rax
leaq 0x48(%rsp), %rdi
movq %rbx, %rdx
testq %rax, %rax
je 0xe37d
movq 0x20(%rsp), %rcx
leaq 0xc0(%rsp), %r8
callq *%rax
jmp 0xe38f
movq 0x20(%rsp), %rcx
leaq 0xc0(%rsp), %r8
callq 0x53d7
movq 0x48(%rsp), %rdi
callq 0x1030
testq %rbp, %rbp
sete %al
movq 0x60(%rsp,%rbp,8), %rcx
cmpq %r15, %rcx
setb %dl
orb %al, %dl
cmovneq %rcx, %r15
cmovnel %ebp, %r12d
incq %rbp
addq $0x8, %r13
cmpq $0x5, %rbp
jne 0xe31e
movq 0x40(%rsp), %rsi
movq %rsi, %rax
movq 0x58(%rsp), %r8
imulq %r8, %rax
movq 0x8(%rsp), %rcx
movb %r12b, (%rcx,%rax)
testq %r14, %r14
movq 0x30(%rsp), %rdi
je 0xe40a
movl %r12d, %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, %r14
jne 0xe3f9
incq %r8
addq %rsi, %rdi
cmpq 0x50(%rsp), %r8
movq 0x18(%rsp), %rax
jne 0xe2f8
xorl %ebx, %ebx
movq 0x90(%rsp,%rbx,8), %rdi
callq 0x1030
incq %rbx
cmpq $0x5, %rbx
jne 0xe422
jmp 0xe6a7
testl %ebx, %ebx
je 0xe067
movl %ebx, %eax
movq %rax, 0x10(%rsp)
incq %rbp
xorl %r13d, %r13d
xorl %edx, %edx
movq %r8, %r12
movq 0x18(%rsp), %rax
movq %rax, %rbx
movq 0x40(%r15), %rax
movzbl (%rax,%r13), %r9d
movb %r9b, -0x1(%rbp)
movq %rbp, %rdi
movq %rbx, %rsi
movq %r14, %rcx
movq %r12, %r8
callq 0xe6c5
incq %r13
addq 0x40(%rsp), %rbp
leaq (%rbx,%r14), %rax
movq %rbx, %rdx
cmpq %r13, 0x10(%rsp)
jne 0xe45c
jmp 0xe067
movl %ebx, %r12d
movq %r8, 0x10(%rsp)
xorl %ebx, %ebx
movl $0x53, %ebp
xorl %r15d, %r15d
movq %r14, %rdi
callq 0x1140
movq %rax, 0x60(%rsp,%rbx,8)
testq %rax, %rax
cmovel %ebp, %r15d
incq %rbx
cmpq $0x5, %rbx
jne 0xe4aa
movq %r15, 0x28(%rsp)
testl %r15d, %r15d
setne %al
testl %r12d, %r12d
sete %cl
orb %al, %cl
movq 0x18(%rsp), %rax
jne 0xe692
movl %r12d, %ecx
movq %rcx, 0x30(%rsp)
xorl %edi, %edi
movq 0x8(%rsp), %r8
movq $0x0, (%rsp)
xorl %ebx, %ebx
xorl %r15d, %r15d
movq %r8, 0x20(%rsp)
movq (%rsp), %r12
movq %r14, %rcx
movq %rdi, 0x38(%rsp)
imulq %rdi, %rcx
addq %rax, %rcx
movq %rcx, (%rsp)
xorl %ebp, %ebp
movq 0x60(%rsp,%rbp,8), %r13
movzbl %bpl, %r9d
movq %r13, %rdi
movq (%rsp), %rsi
movq %r12, %rdx
movq %r14, %rcx
movq 0x10(%rsp), %r8
callq 0xe6c5
movl $0x400, %edx            # imm = 0x400
leaq 0xc0(%rsp), %rdi
xorl %esi, %esi
callq 0x10e0
testq %r14, %r14
je 0xe571
xorl %eax, %eax
movzbl (%r13,%rax), %ecx
incl 0xc0(%rsp,%rcx,4)
incq %rax
movl %eax, %ecx
cmpq %rcx, %r14
jne 0xe55a
incl 0xc0(%rsp,%rbp,4)
xorl %edx, %edx
xorl %eax, %eax
movl 0xc0(%rsp,%rdx,4), %esi
testq %rsi, %rsi
je 0xe604
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 0xe606
xorl %ecx, %ecx
addq %rcx, %rax
incq %rdx
cmpq $0x100, %rdx            # imm = 0x100
jne 0xe57c
testq %rbp, %rbp
sete %cl
cmpq %r15, %rax
seta %dl
orb %cl, %dl
cmovneq %rax, %r15
cmovnel %ebp, %ebx
incq %rbp
cmpq $0x5, %rbp
jne 0xe51f
movq 0x40(%rsp), %rsi
movq %rsi, %rax
movq 0x38(%rsp), %rdi
imulq %rdi, %rax
movq 0x8(%rsp), %rcx
movb %bl, (%rcx,%rax)
testq %r14, %r14
movq 0x20(%rsp), %r8
je 0xe67c
movl %ebx, %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, %r14
jne 0xe66a
incq %rdi
addq %rsi, %r8
cmpq 0x30(%rsp), %rdi
movq 0x18(%rsp), %rax
jne 0xe501
xorl %ebx, %ebx
movq 0x60(%rsp,%rbx,8), %rdi
callq 0x1030
incq %rbx
cmpq $0x5, %rbx
jne 0xe694
movq 0x28(%rsp), %rax
jmp 0xe6b3
movl $0x58, %eax
addq $0x4c8, %rsp            # imm = 0x4C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq