| 5442 | } |
| 5443 | |
| 5444 | static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, |
| 5445 | const LodePNGColorMode* color, const LodePNGEncoderSettings* settings) { |
| 5446 | /* |
| 5447 | For PNG filter method 0 |
| 5448 | out must be a buffer with as size: h + (w * h * bpp + 7u) / 8u, because there are |
| 5449 | the scanlines with 1 extra byte per scanline |
| 5450 | */ |
| 5451 | |
| 5452 | unsigned bpp = lodepng_get_bpp(color); |
| 5453 | /*the width of a scanline in bytes, not including the filter type*/ |
| 5454 | size_t linebytes = lodepng_get_raw_size_idat(w, 1, bpp) - 1u; |
| 5455 | |
| 5456 | /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ |
| 5457 | size_t bytewidth = (bpp + 7u) / 8u; |
| 5458 | const unsigned char* prevline = 0; |
| 5459 | unsigned x, y; |
| 5460 | unsigned error = 0; |
| 5461 | LodePNGFilterStrategy strategy = settings->filter_strategy; |
| 5462 | |
| 5463 | /* |
| 5464 | There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard: |
| 5465 | * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. |
| 5466 | use fixed filtering, with the filter None). |
| 5467 | * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is |
| 5468 | not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply |
| 5469 | all five filters and select the filter that produces the smallest sum of absolute values per row. |
| 5470 | This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true. |
| 5471 | |
| 5472 | If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed, |
| 5473 | but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum |
| 5474 | heuristic is used. |
| 5475 | */ |
| 5476 | if(settings->filter_palette_zero && |
| 5477 | (color->colortype == LCT_PALETTE || color->bitdepth < 8)) strategy = LFS_ZERO; |
| 5478 | |
| 5479 | if(bpp == 0) return 31; /*error: invalid color type*/ |
| 5480 | |
| 5481 | if(strategy >= LFS_ZERO && strategy <= LFS_FOUR) { |
| 5482 | unsigned char type = (unsigned char)strategy; |
| 5483 | for(y = 0; y != h; ++y) { |
| 5484 | size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ |
| 5485 | size_t inindex = linebytes * y; |
| 5486 | out[outindex] = type; /*filter type byte*/ |
| 5487 | filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); |
| 5488 | prevline = &in[inindex]; |
| 5489 | } |
| 5490 | } else if(strategy == LFS_MINSUM) { |
| 5491 | /*adaptive filtering*/ |
| 5492 | unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ |
| 5493 | size_t smallest = 0; |
| 5494 | unsigned char type, bestType = 0; |
| 5495 | |
| 5496 | for(type = 0; type != 5; ++type) { |
| 5497 | attempt[type] = (unsigned char*)lodepng_malloc(linebytes); |
| 5498 | if(!attempt[type]) error = 83; /*alloc fail*/ |
| 5499 | } |
| 5500 | |
| 5501 | if(!error) { |
no test coverage detected