| 5276 | } |
| 5277 | |
| 5278 | static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, |
| 5279 | const LodePNGColorMode* info, const LodePNGEncoderSettings* settings) |
| 5280 | { |
| 5281 | /* |
| 5282 | For PNG filter method 0 |
| 5283 | out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are |
| 5284 | the scanlines with 1 extra byte per scanline |
| 5285 | */ |
| 5286 | |
| 5287 | unsigned bpp = lodepng_get_bpp(info); |
| 5288 | /*the width of a scanline in bytes, not including the filter type*/ |
| 5289 | size_t linebytes = (w * bpp + 7) / 8; |
| 5290 | /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ |
| 5291 | size_t bytewidth = (bpp + 7) / 8; |
| 5292 | const unsigned char* prevline = 0; |
| 5293 | unsigned x, y; |
| 5294 | unsigned error = 0; |
| 5295 | LodePNGFilterStrategy strategy = settings->filter_strategy; |
| 5296 | |
| 5297 | /* |
| 5298 | There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard: |
| 5299 | * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. |
| 5300 | use fixed filtering, with the filter None). |
| 5301 | * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is |
| 5302 | not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply |
| 5303 | all five filters and select the filter that produces the smallest sum of absolute values per row. |
| 5304 | This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true. |
| 5305 | |
| 5306 | If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed, |
| 5307 | but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum |
| 5308 | heuristic is used. |
| 5309 | */ |
| 5310 | if(settings->filter_palette_zero && |
| 5311 | (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO; |
| 5312 | |
| 5313 | if(bpp == 0) return 31; /*error: invalid color type*/ |
| 5314 | |
| 5315 | if(strategy == LFS_ZERO) |
| 5316 | { |
| 5317 | for(y = 0; y != h; ++y) |
| 5318 | { |
| 5319 | size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ |
| 5320 | size_t inindex = linebytes * y; |
| 5321 | out[outindex] = 0; /*filter type byte*/ |
| 5322 | filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, 0); |
| 5323 | prevline = &in[inindex]; |
| 5324 | } |
| 5325 | } |
| 5326 | else if(strategy == LFS_MINSUM) |
| 5327 | { |
| 5328 | /*adaptive filtering*/ |
| 5329 | size_t sum[5]; |
| 5330 | unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ |
| 5331 | size_t smallest = 0; |
| 5332 | unsigned char type, bestType = 0; |
| 5333 | |
| 5334 | for(type = 0; type != 5; ++type) |
| 5335 | { |
no test coverage detected