OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stddef.h> | 5 #include <stddef.h> |
6 #include <stdint.h> | 6 #include <stdint.h> |
7 | 7 |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 28 matching lines...) Loading... |
39 std::vector<unsigned char> v(data, data + size); | 39 std::vector<unsigned char> v(data, data + size); |
40 if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) { | 40 if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) { |
41 // not a PNG. | 41 // not a PNG. |
42 return 0; | 42 return 0; |
43 } | 43 } |
44 | 44 |
45 png_structp png_ptr = png_create_read_struct | 45 png_structp png_ptr = png_create_read_struct |
46 (PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); | 46 (PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); |
47 assert(png_ptr); | 47 assert(png_ptr); |
48 | 48 |
49 png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; | 49 png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); |
50 png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_IGNORE; | |
51 | |
52 png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; | |
53 png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; | |
54 | 50 |
55 png_infop info_ptr = png_create_info_struct(png_ptr); | 51 png_infop info_ptr = png_create_info_struct(png_ptr); |
56 assert(info_ptr); | 52 assert(info_ptr); |
57 | 53 |
58 base::ScopedClosureRunner struct_deleter(base::Bind( | 54 base::ScopedClosureRunner struct_deleter(base::Bind( |
59 &png_destroy_read_struct, &png_ptr, &info_ptr, nullptr)); | 55 &png_destroy_read_struct, &png_ptr, &info_ptr, nullptr)); |
60 | 56 |
61 // Setting up reading from buffer. | 57 // Setting up reading from buffer. |
62 std::unique_ptr<BufState> buf_state(new BufState()); | 58 std::unique_ptr<BufState> buf_state(new BufState()); |
63 buf_state->data = data + kPngHeaderSize; | 59 buf_state->data = data + kPngHeaderSize; |
64 buf_state->bytes_left = size - kPngHeaderSize; | 60 buf_state->bytes_left = size - kPngHeaderSize; |
65 png_set_read_fn(png_ptr, buf_state.get(), user_read_data); | 61 png_set_read_fn(png_ptr, buf_state.get(), user_read_data); |
66 png_set_sig_bytes(png_ptr, kPngHeaderSize); | 62 png_set_sig_bytes(png_ptr, kPngHeaderSize); |
67 | 63 |
68 // libpng error handling. | 64 // libpng error handling. |
69 if (setjmp(png_ptr->jmpbuf)) { | 65 if (setjmp(png_jmpbuf(png_ptr))) { |
70 return 0; | 66 return 0; |
71 } | 67 } |
72 | 68 |
73 // Reading. | 69 // Reading. |
74 png_read_info(png_ptr, info_ptr); | 70 png_read_info(png_ptr, info_ptr); |
75 png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); | 71 png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); |
76 base::ScopedClosureRunner png_deleter(base::Bind( | 72 base::ScopedClosureRunner png_deleter(base::Bind( |
77 &png_free, png_ptr, row)); | 73 &png_free, png_ptr, row)); |
78 | 74 |
79 // reset error handler to put png_deleter into scope. | 75 // reset error handler to put png_deleter into scope. |
80 if (setjmp(png_ptr->jmpbuf)) { | 76 if (setjmp(png_jmpbuf(png_ptr))) { |
81 return 0; | 77 return 0; |
82 } | 78 } |
83 | 79 |
84 png_uint_32 width, height; | 80 png_uint_32 width, height; |
85 int bit_depth, color_type, interlace_type, compression_type; | 81 int bit_depth, color_type, interlace_type, compression_type; |
86 int filter_type; | 82 int filter_type; |
87 | 83 |
88 if (!png_get_IHDR(png_ptr, info_ptr, &width, &height, | 84 if (!png_get_IHDR(png_ptr, info_ptr, &width, &height, |
89 &bit_depth, &color_type, &interlace_type, | 85 &bit_depth, &color_type, &interlace_type, |
90 &compression_type, &filter_type)) { | 86 &compression_type, &filter_type)) { |
91 return 0; | 87 return 0; |
92 } | 88 } |
93 | 89 |
94 // This is going to be too slow. | 90 // This is going to be too slow. |
95 if (width && height > 100000000 / width) | 91 if (width && height > 100000000 / width) |
96 return 0; | 92 return 0; |
97 | 93 |
98 int passes = png_set_interlace_handling(png_ptr); | 94 int passes = png_set_interlace_handling(png_ptr); |
99 png_start_read_image(png_ptr); | 95 png_start_read_image(png_ptr); |
100 | 96 |
101 for (int pass = 0; pass < passes; ++pass) { | 97 for (int pass = 0; pass < passes; ++pass) { |
102 for (png_uint_32 y = 0; y < height; ++y) { | 98 for (png_uint_32 y = 0; y < height; ++y) { |
103 png_read_row(png_ptr, static_cast<png_bytep>(row), NULL); | 99 png_read_row(png_ptr, static_cast<png_bytep>(row), NULL); |
104 } | 100 } |
105 } | 101 } |
106 | 102 |
107 return 0; | 103 return 0; |
108 } | 104 } |
OLD | NEW |