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 |