| OLD | NEW |
| 1 | 1 |
| 2 /* pngwutil.c - utilities to write a PNG file | 2 /* pngwutil.c - utilities to write a PNG file |
| 3 * | 3 * |
| 4 * Last changed in libpng 1.6.22 [May 26, 2016] | 4 * Last changed in libpng 1.6.22 [May 26, 2016] |
| 5 * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson | 5 * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson |
| 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
| 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
| 8 * | 8 * |
| 9 * This code is released under the libpng license. | 9 * This code is released under the libpng license. |
| 10 * For conditions of distribution and use, see the disclaimer | 10 * For conditions of distribution and use, see the disclaimer |
| (...skipping 2260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2271 v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); | 2271 v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); |
| 2272 sum += (v < 128) ? v : 256 - v; | 2272 sum += (v < 128) ? v : 256 - v; |
| 2273 | 2273 |
| 2274 if (sum > lmins) /* We are already worse, don't continue. */ | 2274 if (sum > lmins) /* We are already worse, don't continue. */ |
| 2275 break; | 2275 break; |
| 2276 } | 2276 } |
| 2277 | 2277 |
| 2278 return (sum); | 2278 return (sum); |
| 2279 } | 2279 } |
| 2280 | 2280 |
| 2281 static void /* PRIVATE */ |
| 2282 png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp, |
| 2283 const png_size_t row_bytes) |
| 2284 { |
| 2285 png_bytep rp, dp, lp; |
| 2286 png_size_t i; |
| 2287 |
| 2288 png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; |
| 2289 |
| 2290 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp; |
| 2291 i++, rp++, dp++) |
| 2292 { |
| 2293 *dp = *rp; |
| 2294 } |
| 2295 |
| 2296 for (lp = png_ptr->row_buf + 1; i < row_bytes; |
| 2297 i++, rp++, lp++, dp++) |
| 2298 { |
| 2299 *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); |
| 2300 } |
| 2301 } |
| 2302 |
| 2281 static png_size_t /* PRIVATE */ | 2303 static png_size_t /* PRIVATE */ |
| 2282 png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, | 2304 png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, |
| 2283 const png_size_t lmins) | 2305 const png_size_t lmins) |
| 2284 { | 2306 { |
| 2285 png_bytep rp, dp, pp; | 2307 png_bytep rp, dp, pp; |
| 2286 png_size_t i; | 2308 png_size_t i; |
| 2287 png_size_t sum = 0; | 2309 png_size_t sum = 0; |
| 2288 int v; | 2310 int v; |
| 2289 | 2311 |
| 2290 png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; | 2312 png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; |
| 2291 | 2313 |
| 2292 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, | 2314 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, |
| 2293 pp = png_ptr->prev_row + 1; i < row_bytes; | 2315 pp = png_ptr->prev_row + 1; i < row_bytes; |
| 2294 i++, rp++, pp++, dp++) | 2316 i++, rp++, pp++, dp++) |
| 2295 { | 2317 { |
| 2296 v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); | 2318 v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); |
| 2297 sum += (v < 128) ? v : 256 - v; | 2319 sum += (v < 128) ? v : 256 - v; |
| 2298 | 2320 |
| 2299 if (sum > lmins) /* We are already worse, don't continue. */ | 2321 if (sum > lmins) /* We are already worse, don't continue. */ |
| 2300 break; | 2322 break; |
| 2301 } | 2323 } |
| 2302 | 2324 |
| 2303 return (sum); | 2325 return (sum); |
| 2304 } | 2326 } |
| 2327 static void /* PRIVATE */ |
| 2328 png_setup_up_row_only(png_structrp png_ptr, const png_size_t row_bytes) |
| 2329 { |
| 2330 png_bytep rp, dp, pp; |
| 2331 png_size_t i; |
| 2332 |
| 2333 png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; |
| 2334 |
| 2335 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, |
| 2336 pp = png_ptr->prev_row + 1; i < row_bytes; |
| 2337 i++, rp++, pp++, dp++) |
| 2338 { |
| 2339 *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); |
| 2340 } |
| 2341 } |
| 2305 | 2342 |
| 2306 static png_size_t /* PRIVATE */ | 2343 static png_size_t /* PRIVATE */ |
| 2307 png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, | 2344 png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, |
| 2308 const png_size_t row_bytes, const png_size_t lmins) | 2345 const png_size_t row_bytes, const png_size_t lmins) |
| 2309 { | 2346 { |
| 2310 png_bytep rp, dp, pp, lp; | 2347 png_bytep rp, dp, pp, lp; |
| 2311 png_uint_32 i; | 2348 png_uint_32 i; |
| 2312 png_size_t sum = 0; | 2349 png_size_t sum = 0; |
| 2313 int v; | 2350 int v; |
| 2314 | 2351 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2328 & 0xff); | 2365 & 0xff); |
| 2329 | 2366 |
| 2330 sum += (v < 128) ? v : 256 - v; | 2367 sum += (v < 128) ? v : 256 - v; |
| 2331 | 2368 |
| 2332 if (sum > lmins) /* We are already worse, don't continue. */ | 2369 if (sum > lmins) /* We are already worse, don't continue. */ |
| 2333 break; | 2370 break; |
| 2334 } | 2371 } |
| 2335 | 2372 |
| 2336 return (sum); | 2373 return (sum); |
| 2337 } | 2374 } |
| 2375 static void /* PRIVATE */ |
| 2376 png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, |
| 2377 const png_size_t row_bytes) |
| 2378 { |
| 2379 png_bytep rp, dp, pp, lp; |
| 2380 png_uint_32 i; |
| 2381 |
| 2382 png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; |
| 2383 |
| 2384 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, |
| 2385 pp = png_ptr->prev_row + 1; i < bpp; i++) |
| 2386 { |
| 2387 *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); |
| 2388 } |
| 2389 |
| 2390 for (lp = png_ptr->row_buf + 1; i < row_bytes; i++) |
| 2391 { |
| 2392 *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) |
| 2393 & 0xff); |
| 2394 } |
| 2395 } |
| 2338 | 2396 |
| 2339 static png_size_t /* PRIVATE */ | 2397 static png_size_t /* PRIVATE */ |
| 2340 png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, | 2398 png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, |
| 2341 const png_size_t row_bytes, const png_size_t lmins) | 2399 const png_size_t row_bytes, const png_size_t lmins) |
| 2342 { | 2400 { |
| 2343 png_bytep rp, dp, pp, cp, lp; | 2401 png_bytep rp, dp, pp, cp, lp; |
| 2344 png_size_t i; | 2402 png_size_t i; |
| 2345 png_size_t sum = 0; | 2403 png_size_t sum = 0; |
| 2346 int v; | 2404 int v; |
| 2347 | 2405 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2382 v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); | 2440 v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); |
| 2383 | 2441 |
| 2384 sum += (v < 128) ? v : 256 - v; | 2442 sum += (v < 128) ? v : 256 - v; |
| 2385 | 2443 |
| 2386 if (sum > lmins) /* We are already worse, don't continue. */ | 2444 if (sum > lmins) /* We are already worse, don't continue. */ |
| 2387 break; | 2445 break; |
| 2388 } | 2446 } |
| 2389 | 2447 |
| 2390 return (sum); | 2448 return (sum); |
| 2391 } | 2449 } |
| 2450 static void /* PRIVATE */ |
| 2451 png_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp, |
| 2452 const png_size_t row_bytes) |
| 2453 { |
| 2454 png_bytep rp, dp, pp, cp, lp; |
| 2455 png_size_t i; |
| 2456 |
| 2457 png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; |
| 2458 |
| 2459 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, |
| 2460 pp = png_ptr->prev_row + 1; i < bpp; i++) |
| 2461 { |
| 2462 *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); |
| 2463 } |
| 2464 |
| 2465 for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; |
| 2466 i++) |
| 2467 { |
| 2468 int a, b, c, pa, pb, pc, p; |
| 2469 |
| 2470 b = *pp++; |
| 2471 c = *cp++; |
| 2472 a = *lp++; |
| 2473 |
| 2474 p = b - c; |
| 2475 pc = a - c; |
| 2476 |
| 2477 #ifdef PNG_USE_ABS |
| 2478 pa = abs(p); |
| 2479 pb = abs(pc); |
| 2480 pc = abs(p + pc); |
| 2481 #else |
| 2482 pa = p < 0 ? -p : p; |
| 2483 pb = pc < 0 ? -pc : pc; |
| 2484 pc = (p + pc) < 0 ? -(p + pc) : p + pc; |
| 2485 #endif |
| 2486 |
| 2487 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; |
| 2488 |
| 2489 *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); |
| 2490 } |
| 2491 } |
| 2392 #endif /* WRITE_FILTER */ | 2492 #endif /* WRITE_FILTER */ |
| 2393 | 2493 |
| 2394 void /* PRIVATE */ | 2494 void /* PRIVATE */ |
| 2395 png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) | 2495 png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) |
| 2396 { | 2496 { |
| 2397 #ifndef PNG_WRITE_FILTER_SUPPORTED | 2497 #ifndef PNG_WRITE_FILTER_SUPPORTED |
| 2398 png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); | 2498 png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); |
| 2399 #else | 2499 #else |
| 2400 unsigned int filter_to_do = png_ptr->do_filter; | 2500 unsigned int filter_to_do = png_ptr->do_filter; |
| 2401 png_bytep row_buf; | 2501 png_bytep row_buf; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2438 */ | 2538 */ |
| 2439 | 2539 |
| 2440 | 2540 |
| 2441 /* We don't need to test the 'no filter' case if this is the only filter | 2541 /* We don't need to test the 'no filter' case if this is the only filter |
| 2442 * that has been chosen, as it doesn't actually do anything to the data. | 2542 * that has been chosen, as it doesn't actually do anything to the data. |
| 2443 */ | 2543 */ |
| 2444 best_row = png_ptr->row_buf; | 2544 best_row = png_ptr->row_buf; |
| 2445 | 2545 |
| 2446 if (PNG_SIZE_MAX/128 <= row_bytes) | 2546 if (PNG_SIZE_MAX/128 <= row_bytes) |
| 2447 { | 2547 { |
| 2448 /* Overflow can occur in the calculation, just select the lowest set | 2548 /* Overflow can occur in the calculation, just select the lowest set |
| 2449 * filter. | 2549 * filter. |
| 2450 */ | 2550 */ |
| 2451 filter_to_do &= -filter_to_do; | 2551 filter_to_do &= -filter_to_do; |
| 2452 } | 2552 } |
| 2453 else if ((filter_to_do & PNG_FILTER_NONE) != 0 && | 2553 else if ((filter_to_do & PNG_FILTER_NONE) != 0 && |
| 2454 filter_to_do != PNG_FILTER_NONE) | 2554 filter_to_do != PNG_FILTER_NONE) |
| 2455 { | 2555 { |
| 2456 /* Overflow not possible and multiple filters in the list, including the | 2556 /* Overflow not possible and multiple filters in the list, including the |
| 2457 * 'none' filter. | 2557 * 'none' filter. |
| 2458 */ | 2558 */ |
| 2459 png_bytep rp; | 2559 png_bytep rp; |
| 2460 png_size_t sum = 0; | 2560 png_size_t sum = 0; |
| 2461 png_size_t i; | 2561 png_size_t i; |
| 2462 int v; | 2562 int v; |
| 2463 | 2563 |
| 2464 { | 2564 { |
| 2465 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) | 2565 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) |
| 2466 { | 2566 { |
| 2467 v = *rp; | 2567 v = *rp; |
| 2468 sum += (v < 128) ? v : 256 - v; | 2568 sum += (v < 128) ? v : 256 - v; |
| 2469 } | 2569 } |
| 2470 } | 2570 } |
| 2471 | 2571 |
| 2472 mins = sum; | 2572 mins = sum; |
| 2473 } | 2573 } |
| 2474 | 2574 |
| 2475 /* Sub filter */ | 2575 /* Sub filter */ |
| 2476 if (filter_to_do == PNG_FILTER_SUB) | 2576 if (filter_to_do == PNG_FILTER_SUB) |
| 2477 /* It's the only filter so no testing is needed */ | 2577 /* It's the only filter so no testing is needed */ |
| 2478 { | 2578 { |
| 2479 /* Passing PNG_SIZE_MAX here and below prevents the 'setup' function | 2579 png_setup_sub_row_only(png_ptr, bpp, row_bytes); |
| 2480 * breaking out of the loop when lmins is exceeded. | |
| 2481 */ | |
| 2482 (void) png_setup_sub_row(png_ptr, bpp, row_bytes, PNG_SIZE_MAX); | |
| 2483 best_row = png_ptr->try_row; | 2580 best_row = png_ptr->try_row; |
| 2484 } | 2581 } |
| 2485 | 2582 |
| 2486 else if ((filter_to_do & PNG_FILTER_SUB) != 0) | 2583 else if ((filter_to_do & PNG_FILTER_SUB) != 0) |
| 2487 { | 2584 { |
| 2488 png_size_t sum; | 2585 png_size_t sum; |
| 2489 png_size_t lmins = mins; | 2586 png_size_t lmins = mins; |
| 2490 | 2587 |
| 2491 sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); | 2588 sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); |
| 2492 | 2589 |
| 2493 if (sum < mins) | 2590 if (sum < mins) |
| 2494 { | 2591 { |
| 2495 mins = sum; | 2592 mins = sum; |
| 2496 best_row = png_ptr->try_row; | 2593 best_row = png_ptr->try_row; |
| 2497 if (png_ptr->tst_row != NULL) | 2594 if (png_ptr->tst_row != NULL) |
| 2498 { | 2595 { |
| 2499 png_ptr->try_row = png_ptr->tst_row; | 2596 png_ptr->try_row = png_ptr->tst_row; |
| 2500 png_ptr->tst_row = best_row; | 2597 png_ptr->tst_row = best_row; |
| 2501 } | 2598 } |
| 2502 } | 2599 } |
| 2503 } | 2600 } |
| 2504 | 2601 |
| 2505 /* Up filter */ | 2602 /* Up filter */ |
| 2506 if (filter_to_do == PNG_FILTER_UP) | 2603 if (filter_to_do == PNG_FILTER_UP) |
| 2507 { | 2604 { |
| 2508 (void) png_setup_up_row(png_ptr, row_bytes, PNG_SIZE_MAX); | 2605 png_setup_up_row_only(png_ptr, row_bytes); |
| 2509 best_row = png_ptr->try_row; | 2606 best_row = png_ptr->try_row; |
| 2510 } | 2607 } |
| 2511 | 2608 |
| 2512 else if ((filter_to_do & PNG_FILTER_UP) != 0) | 2609 else if ((filter_to_do & PNG_FILTER_UP) != 0) |
| 2513 { | 2610 { |
| 2514 png_size_t sum; | 2611 png_size_t sum; |
| 2515 png_size_t lmins = mins; | 2612 png_size_t lmins = mins; |
| 2516 | 2613 |
| 2517 sum = png_setup_up_row(png_ptr, row_bytes, lmins); | 2614 sum = png_setup_up_row(png_ptr, row_bytes, lmins); |
| 2518 | 2615 |
| 2519 if (sum < mins) | 2616 if (sum < mins) |
| 2520 { | 2617 { |
| 2521 mins = sum; | 2618 mins = sum; |
| 2522 best_row = png_ptr->try_row; | 2619 best_row = png_ptr->try_row; |
| 2523 if (png_ptr->tst_row != NULL) | 2620 if (png_ptr->tst_row != NULL) |
| 2524 { | 2621 { |
| 2525 png_ptr->try_row = png_ptr->tst_row; | 2622 png_ptr->try_row = png_ptr->tst_row; |
| 2526 png_ptr->tst_row = best_row; | 2623 png_ptr->tst_row = best_row; |
| 2527 } | 2624 } |
| 2528 } | 2625 } |
| 2529 } | 2626 } |
| 2530 | 2627 |
| 2531 /* Avg filter */ | 2628 /* Avg filter */ |
| 2532 if (filter_to_do == PNG_FILTER_AVG) | 2629 if (filter_to_do == PNG_FILTER_AVG) |
| 2533 { | 2630 { |
| 2534 (void) png_setup_avg_row(png_ptr, bpp, row_bytes, PNG_SIZE_MAX); | 2631 png_setup_avg_row_only(png_ptr, bpp, row_bytes); |
| 2535 best_row = png_ptr->try_row; | 2632 best_row = png_ptr->try_row; |
| 2536 } | 2633 } |
| 2537 | 2634 |
| 2538 else if ((filter_to_do & PNG_FILTER_AVG) != 0) | 2635 else if ((filter_to_do & PNG_FILTER_AVG) != 0) |
| 2539 { | 2636 { |
| 2540 png_size_t sum; | 2637 png_size_t sum; |
| 2541 png_size_t lmins = mins; | 2638 png_size_t lmins = mins; |
| 2542 | 2639 |
| 2543 sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); | 2640 sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); |
| 2544 | 2641 |
| 2545 if (sum < mins) | 2642 if (sum < mins) |
| 2546 { | 2643 { |
| 2547 mins = sum; | 2644 mins = sum; |
| 2548 best_row = png_ptr->try_row; | 2645 best_row = png_ptr->try_row; |
| 2549 if (png_ptr->tst_row != NULL) | 2646 if (png_ptr->tst_row != NULL) |
| 2550 { | 2647 { |
| 2551 png_ptr->try_row = png_ptr->tst_row; | 2648 png_ptr->try_row = png_ptr->tst_row; |
| 2552 png_ptr->tst_row = best_row; | 2649 png_ptr->tst_row = best_row; |
| 2553 } | 2650 } |
| 2554 } | 2651 } |
| 2555 } | 2652 } |
| 2556 | 2653 |
| 2557 /* Paeth filter */ | 2654 /* Paeth filter */ |
| 2558 if ((filter_to_do == PNG_FILTER_PAETH) != 0) | 2655 if ((filter_to_do == PNG_FILTER_PAETH) != 0) |
| 2559 { | 2656 { |
| 2560 (void) png_setup_paeth_row(png_ptr, bpp, row_bytes, PNG_SIZE_MAX); | 2657 png_setup_paeth_row_only(png_ptr, bpp, row_bytes); |
| 2561 best_row = png_ptr->try_row; | 2658 best_row = png_ptr->try_row; |
| 2562 } | 2659 } |
| 2563 | 2660 |
| 2564 else if ((filter_to_do & PNG_FILTER_PAETH) != 0) | 2661 else if ((filter_to_do & PNG_FILTER_PAETH) != 0) |
| 2565 { | 2662 { |
| 2566 png_size_t sum; | 2663 png_size_t sum; |
| 2567 png_size_t lmins = mins; | 2664 png_size_t lmins = mins; |
| 2568 | 2665 |
| 2569 sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); | 2666 sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); |
| 2570 | 2667 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2616 png_ptr->flush_rows++; | 2713 png_ptr->flush_rows++; |
| 2617 | 2714 |
| 2618 if (png_ptr->flush_dist > 0 && | 2715 if (png_ptr->flush_dist > 0 && |
| 2619 png_ptr->flush_rows >= png_ptr->flush_dist) | 2716 png_ptr->flush_rows >= png_ptr->flush_dist) |
| 2620 { | 2717 { |
| 2621 png_write_flush(png_ptr); | 2718 png_write_flush(png_ptr); |
| 2622 } | 2719 } |
| 2623 #endif /* WRITE_FLUSH */ | 2720 #endif /* WRITE_FLUSH */ |
| 2624 } | 2721 } |
| 2625 #endif /* WRITE */ | 2722 #endif /* WRITE */ |
| OLD | NEW |