| 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 2379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2390 return (sum); | 2390 return (sum); |
| 2391 } | 2391 } |
| 2392 #endif /* WRITE_FILTER */ | 2392 #endif /* WRITE_FILTER */ |
| 2393 | 2393 |
| 2394 void /* PRIVATE */ | 2394 void /* PRIVATE */ |
| 2395 png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) | 2395 png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) |
| 2396 { | 2396 { |
| 2397 #ifndef PNG_WRITE_FILTER_SUPPORTED | 2397 #ifndef PNG_WRITE_FILTER_SUPPORTED |
| 2398 png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); | 2398 png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); |
| 2399 #else | 2399 #else |
| 2400 png_byte filter_to_do = png_ptr->do_filter; | 2400 unsigned int filter_to_do = png_ptr->do_filter; |
| 2401 png_bytep row_buf; | 2401 png_bytep row_buf; |
| 2402 png_bytep best_row; | 2402 png_bytep best_row; |
| 2403 png_uint_32 bpp; | 2403 png_uint_32 bpp; |
| 2404 png_size_t mins; | 2404 png_size_t mins; |
| 2405 png_size_t row_bytes = row_info->rowbytes; | 2405 png_size_t row_bytes = row_info->rowbytes; |
| 2406 | 2406 |
| 2407 png_debug(1, "in png_write_find_filter"); | 2407 png_debug(1, "in png_write_find_filter"); |
| 2408 | 2408 |
| 2409 /* Find out how many bytes offset each pixel is */ | 2409 /* Find out how many bytes offset each pixel is */ |
| 2410 bpp = (row_info->pixel_depth + 7) >> 3; | 2410 bpp = (row_info->pixel_depth + 7) >> 3; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2436 * (2) minimum sum of squared differences from zero or running average | 2436 * (2) minimum sum of squared differences from zero or running average |
| 2437 * (i.e., ~ root-mean-square approach) | 2437 * (i.e., ~ root-mean-square approach) |
| 2438 */ | 2438 */ |
| 2439 | 2439 |
| 2440 | 2440 |
| 2441 /* We don't need to test the 'no filter' case if this is the only filter | 2441 /* 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. | 2442 * that has been chosen, as it doesn't actually do anything to the data. |
| 2443 */ | 2443 */ |
| 2444 best_row = png_ptr->row_buf; | 2444 best_row = png_ptr->row_buf; |
| 2445 | 2445 |
| 2446 | 2446 if (PNG_SIZE_MAX/128 <= row_bytes) |
| 2447 if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE) | |
| 2448 { | 2447 { |
| 2448 /* Overflow can occur in the calculation, just select the lowest set |
| 2449 * filter. |
| 2450 */ |
| 2451 filter_to_do &= -filter_to_do; |
| 2452 } |
| 2453 else if ((filter_to_do & PNG_FILTER_NONE) != 0 && |
| 2454 filter_to_do != PNG_FILTER_NONE) |
| 2455 { |
| 2456 /* Overflow not possible and multiple filters in the list, including the |
| 2457 * 'none' filter. |
| 2458 */ |
| 2449 png_bytep rp; | 2459 png_bytep rp; |
| 2450 png_size_t sum = 0; | 2460 png_size_t sum = 0; |
| 2451 png_size_t i; | 2461 png_size_t i; |
| 2452 int v; | 2462 int v; |
| 2453 | 2463 |
| 2454 if (PNG_SIZE_MAX/128 <= row_bytes) | |
| 2455 { | 2464 { |
| 2456 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) | 2465 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) |
| 2457 { | 2466 { |
| 2458 /* Check for overflow */ | |
| 2459 if (sum > PNG_SIZE_MAX/128 - 256) | |
| 2460 break; | |
| 2461 | |
| 2462 v = *rp; | |
| 2463 sum += (v < 128) ? v : 256 - v; | |
| 2464 } | |
| 2465 } | |
| 2466 else /* Overflow is not possible */ | |
| 2467 { | |
| 2468 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) | |
| 2469 { | |
| 2470 v = *rp; | 2467 v = *rp; |
| 2471 sum += (v < 128) ? v : 256 - v; | 2468 sum += (v < 128) ? v : 256 - v; |
| 2472 } | 2469 } |
| 2473 } | 2470 } |
| 2474 | 2471 |
| 2475 mins = sum; | 2472 mins = sum; |
| 2476 } | 2473 } |
| 2477 | 2474 |
| 2478 /* Sub filter */ | 2475 /* Sub filter */ |
| 2479 if (filter_to_do == PNG_FILTER_SUB) | 2476 if (filter_to_do == PNG_FILTER_SUB) |
| 2480 /* It's the only filter so no testing is needed */ | 2477 /* It's the only filter so no testing is needed */ |
| 2481 { | 2478 { |
| 2482 (void) png_setup_sub_row(png_ptr, bpp, row_bytes, mins); | 2479 /* Passing PNG_SIZE_MAX here and below prevents the 'setup' function |
| 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; | 2483 best_row = png_ptr->try_row; |
| 2484 } | 2484 } |
| 2485 | 2485 |
| 2486 else if ((filter_to_do & PNG_FILTER_SUB) != 0) | 2486 else if ((filter_to_do & PNG_FILTER_SUB) != 0) |
| 2487 { | 2487 { |
| 2488 png_size_t sum; | 2488 png_size_t sum; |
| 2489 png_size_t lmins = mins; | 2489 png_size_t lmins = mins; |
| 2490 | 2490 |
| 2491 sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); | 2491 sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); |
| 2492 | 2492 |
| 2493 if (sum < mins) | 2493 if (sum < mins) |
| 2494 { | 2494 { |
| 2495 mins = sum; | 2495 mins = sum; |
| 2496 best_row = png_ptr->try_row; | 2496 best_row = png_ptr->try_row; |
| 2497 if (png_ptr->tst_row != NULL) | 2497 if (png_ptr->tst_row != NULL) |
| 2498 { | 2498 { |
| 2499 png_ptr->try_row = png_ptr->tst_row; | 2499 png_ptr->try_row = png_ptr->tst_row; |
| 2500 png_ptr->tst_row = best_row; | 2500 png_ptr->tst_row = best_row; |
| 2501 } | 2501 } |
| 2502 } | 2502 } |
| 2503 } | 2503 } |
| 2504 | 2504 |
| 2505 /* Up filter */ | 2505 /* Up filter */ |
| 2506 if (filter_to_do == PNG_FILTER_UP) | 2506 if (filter_to_do == PNG_FILTER_UP) |
| 2507 { | 2507 { |
| 2508 (void) png_setup_up_row(png_ptr, row_bytes, mins); | 2508 (void) png_setup_up_row(png_ptr, row_bytes, PNG_SIZE_MAX); |
| 2509 best_row = png_ptr->try_row; | 2509 best_row = png_ptr->try_row; |
| 2510 } | 2510 } |
| 2511 | 2511 |
| 2512 else if ((filter_to_do & PNG_FILTER_UP) != 0) | 2512 else if ((filter_to_do & PNG_FILTER_UP) != 0) |
| 2513 { | 2513 { |
| 2514 png_size_t sum; | 2514 png_size_t sum; |
| 2515 png_size_t lmins = mins; | 2515 png_size_t lmins = mins; |
| 2516 | 2516 |
| 2517 sum = png_setup_up_row(png_ptr, row_bytes, lmins); | 2517 sum = png_setup_up_row(png_ptr, row_bytes, lmins); |
| 2518 | 2518 |
| 2519 if (sum < mins) | 2519 if (sum < mins) |
| 2520 { | 2520 { |
| 2521 mins = sum; | 2521 mins = sum; |
| 2522 best_row = png_ptr->try_row; | 2522 best_row = png_ptr->try_row; |
| 2523 if (png_ptr->tst_row != NULL) | 2523 if (png_ptr->tst_row != NULL) |
| 2524 { | 2524 { |
| 2525 png_ptr->try_row = png_ptr->tst_row; | 2525 png_ptr->try_row = png_ptr->tst_row; |
| 2526 png_ptr->tst_row = best_row; | 2526 png_ptr->tst_row = best_row; |
| 2527 } | 2527 } |
| 2528 } | 2528 } |
| 2529 } | 2529 } |
| 2530 | 2530 |
| 2531 /* Avg filter */ | 2531 /* Avg filter */ |
| 2532 if (filter_to_do == PNG_FILTER_AVG) | 2532 if (filter_to_do == PNG_FILTER_AVG) |
| 2533 { | 2533 { |
| 2534 (void) png_setup_avg_row(png_ptr, bpp, row_bytes, mins); | 2534 (void) png_setup_avg_row(png_ptr, bpp, row_bytes, PNG_SIZE_MAX); |
| 2535 best_row = png_ptr->try_row; | 2535 best_row = png_ptr->try_row; |
| 2536 } | 2536 } |
| 2537 | 2537 |
| 2538 else if ((filter_to_do & PNG_FILTER_AVG) != 0) | 2538 else if ((filter_to_do & PNG_FILTER_AVG) != 0) |
| 2539 { | 2539 { |
| 2540 png_size_t sum; | 2540 png_size_t sum; |
| 2541 png_size_t lmins = mins; | 2541 png_size_t lmins = mins; |
| 2542 | 2542 |
| 2543 sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); | 2543 sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); |
| 2544 | 2544 |
| 2545 if (sum < mins) | 2545 if (sum < mins) |
| 2546 { | 2546 { |
| 2547 mins = sum; | 2547 mins = sum; |
| 2548 best_row = png_ptr->try_row; | 2548 best_row = png_ptr->try_row; |
| 2549 if (png_ptr->tst_row != NULL) | 2549 if (png_ptr->tst_row != NULL) |
| 2550 { | 2550 { |
| 2551 png_ptr->try_row = png_ptr->tst_row; | 2551 png_ptr->try_row = png_ptr->tst_row; |
| 2552 png_ptr->tst_row = best_row; | 2552 png_ptr->tst_row = best_row; |
| 2553 } | 2553 } |
| 2554 } | 2554 } |
| 2555 } | 2555 } |
| 2556 | 2556 |
| 2557 /* Paeth filter */ | 2557 /* Paeth filter */ |
| 2558 if ((filter_to_do == PNG_FILTER_PAETH) != 0) | 2558 if ((filter_to_do == PNG_FILTER_PAETH) != 0) |
| 2559 { | 2559 { |
| 2560 (void) png_setup_paeth_row(png_ptr, bpp, row_bytes, mins); | 2560 (void) png_setup_paeth_row(png_ptr, bpp, row_bytes, PNG_SIZE_MAX); |
| 2561 best_row = png_ptr->try_row; | 2561 best_row = png_ptr->try_row; |
| 2562 } | 2562 } |
| 2563 | 2563 |
| 2564 else if ((filter_to_do & PNG_FILTER_PAETH) != 0) | 2564 else if ((filter_to_do & PNG_FILTER_PAETH) != 0) |
| 2565 { | 2565 { |
| 2566 png_size_t sum; | 2566 png_size_t sum; |
| 2567 png_size_t lmins = mins; | 2567 png_size_t lmins = mins; |
| 2568 | 2568 |
| 2569 sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); | 2569 sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); |
| 2570 | 2570 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2616 png_ptr->flush_rows++; | 2616 png_ptr->flush_rows++; |
| 2617 | 2617 |
| 2618 if (png_ptr->flush_dist > 0 && | 2618 if (png_ptr->flush_dist > 0 && |
| 2619 png_ptr->flush_rows >= png_ptr->flush_dist) | 2619 png_ptr->flush_rows >= png_ptr->flush_dist) |
| 2620 { | 2620 { |
| 2621 png_write_flush(png_ptr); | 2621 png_write_flush(png_ptr); |
| 2622 } | 2622 } |
| 2623 #endif /* WRITE_FLUSH */ | 2623 #endif /* WRITE_FLUSH */ |
| 2624 } | 2624 } |
| 2625 #endif /* WRITE */ | 2625 #endif /* WRITE */ |
| OLD | NEW |