| 5078 | } |
| 5079 | |
| 5080 | static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, |
| 5081 | const LodePNGColorMode* info, const LodePNGEncoderSettings* settings) |
| 5082 | { |
| 5083 | /* |
| 5084 | For PNG filter method 0 |
| 5085 | out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are |
| 5086 | the scanlines with 1 extra byte per scanline |
| 5087 | */ |
| 5088 | |
| 5089 | unsigned bpp = lodepng_get_bpp(info); |
| 5090 | /*the width of a scanline in bytes, not including the filter type*/ |
| 5091 | size_t linebytes = (w * bpp + 7) / 8; |
| 5092 | /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ |
| 5093 | size_t bytewidth = (bpp + 7) / 8; |
| 5094 | const unsigned char* prevline = 0; |
| 5095 | unsigned x, y; |
| 5096 | unsigned error = 0; |
| 5097 | LodePNGFilterStrategy strategy = settings->filter_strategy; |
| 5098 | |
| 5099 | /* |
| 5100 | There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard: |
| 5101 | * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. |
| 5102 | use fixed filtering, with the filter None). |
| 5103 | * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is |
| 5104 | not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply |
| 5105 | all five filters and select the filter that produces the smallest sum of absolute values per row. |
| 5106 | This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true. |
| 5107 | |
| 5108 | If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed, |
| 5109 | but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum |
| 5110 | heuristic is used. |
| 5111 | */ |
| 5112 | if(settings->filter_palette_zero && |
| 5113 | (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO; |
| 5114 | |
| 5115 | if(bpp == 0) return 31; /*error: invalid color type*/ |
| 5116 | |
| 5117 | if(strategy == LFS_ZERO) |
| 5118 | { |
| 5119 | for(y = 0; y < h; y++) |
| 5120 | { |
| 5121 | size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ |
| 5122 | size_t inindex = linebytes * y; |
| 5123 | out[outindex] = 0; /*filter type byte*/ |
| 5124 | filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, 0); |
| 5125 | prevline = &in[inindex]; |
| 5126 | } |
| 5127 | } |
| 5128 | else if(strategy == LFS_MINSUM) |
| 5129 | { |
| 5130 | /*adaptive filtering*/ |
| 5131 | size_t sum[5]; |
| 5132 | ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ |
| 5133 | size_t smallest = 0; |
| 5134 | unsigned char type, bestType = 0; |
| 5135 | |
| 5136 | for(type = 0; type < 5; type++) |
| 5137 | { |
no test coverage detected