Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(338)

Side by Side Diff: third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp

Issue 2930513004: [WIP] Move ImageDecoders to SkCodec
Patch Set: Adding check for decoder creation Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "platform/image-decoders/jpeg/JPEGImageDecoder.h"
32
33 #include <memory>
34 #include "platform/SharedBuffer.h"
35 #include "platform/image-decoders/ImageAnimation.h"
36 #include "platform/image-decoders/ImageDecoderTestHelpers.h"
37 #include "platform/wtf/PtrUtil.h"
38 #include "platform/wtf/typed_arrays/ArrayBuffer.h"
39 #include "public/platform/WebData.h"
40 #include "public/platform/WebSize.h"
41 #include "testing/gtest/include/gtest/gtest.h"
42
43 namespace blink {
44
45 static const size_t kLargeEnoughSize = 1000 * 1000;
46
47 namespace {
48
49 std::unique_ptr<ImageDecoder> CreateDecoder(size_t max_decoded_bytes) {
50 return WTF::WrapUnique(new JPEGImageDecoder(
51 ImageDecoder::kAlphaNotPremultiplied,
52 ColorBehavior::TransformToTargetForTesting(), max_decoded_bytes));
53 }
54
55 std::unique_ptr<ImageDecoder> CreateDecoder() {
56 return CreateDecoder(ImageDecoder::kNoDecodedImageByteLimit);
57 }
58
59 } // anonymous namespace
60
61 void Downsample(size_t max_decoded_bytes,
62 unsigned* output_width,
63 unsigned* output_height,
64 const char* image_file_path) {
65 RefPtr<SharedBuffer> data = ReadFile(image_file_path);
66 ASSERT_TRUE(data);
67
68 std::unique_ptr<ImageDecoder> decoder = CreateDecoder(max_decoded_bytes);
69 decoder->SetData(data.Get(), true);
70
71 ImageFrame* frame = decoder->FrameBufferAtIndex(0);
72 ASSERT_TRUE(frame);
73 *output_width = frame->Bitmap().width();
74 *output_height = frame->Bitmap().height();
75 EXPECT_EQ(IntSize(*output_width, *output_height), decoder->DecodedSize());
76 }
77
78 void ReadYUV(size_t max_decoded_bytes,
79 unsigned* output_y_width,
80 unsigned* output_y_height,
81 unsigned* output_uv_width,
82 unsigned* output_uv_height,
83 const char* image_file_path) {
84 RefPtr<SharedBuffer> data = ReadFile(image_file_path);
85 ASSERT_TRUE(data);
86
87 std::unique_ptr<ImageDecoder> decoder = CreateDecoder(max_decoded_bytes);
88 decoder->SetData(data.Get(), true);
89
90 // Setting a dummy ImagePlanes object signals to the decoder that we want to
91 // do YUV decoding.
92 std::unique_ptr<ImagePlanes> dummy_image_planes =
93 WTF::MakeUnique<ImagePlanes>();
94 decoder->SetImagePlanes(std::move(dummy_image_planes));
95
96 bool size_is_available = decoder->IsSizeAvailable();
97 ASSERT_TRUE(size_is_available);
98
99 IntSize size = decoder->DecodedSize();
100 IntSize y_size = decoder->DecodedYUVSize(0);
101 IntSize u_size = decoder->DecodedYUVSize(1);
102 IntSize v_size = decoder->DecodedYUVSize(2);
103
104 ASSERT_TRUE(size.Width() == y_size.Width());
105 ASSERT_TRUE(size.Height() == y_size.Height());
106 ASSERT_TRUE(u_size.Width() == v_size.Width());
107 ASSERT_TRUE(u_size.Height() == v_size.Height());
108
109 *output_y_width = y_size.Width();
110 *output_y_height = y_size.Height();
111 *output_uv_width = u_size.Width();
112 *output_uv_height = u_size.Height();
113
114 size_t row_bytes[3];
115 row_bytes[0] = decoder->DecodedYUVWidthBytes(0);
116 row_bytes[1] = decoder->DecodedYUVWidthBytes(1);
117 row_bytes[2] = decoder->DecodedYUVWidthBytes(2);
118
119 RefPtr<ArrayBuffer> buffer(ArrayBuffer::Create(
120 row_bytes[0] * y_size.Height() + row_bytes[1] * u_size.Height() +
121 row_bytes[2] * v_size.Height(),
122 1));
123 void* planes[3];
124 planes[0] = buffer->Data();
125 planes[1] = ((char*)planes[0]) + row_bytes[0] * y_size.Height();
126 planes[2] = ((char*)planes[1]) + row_bytes[1] * u_size.Height();
127
128 std::unique_ptr<ImagePlanes> image_planes =
129 WTF::MakeUnique<ImagePlanes>(planes, row_bytes);
130 decoder->SetImagePlanes(std::move(image_planes));
131
132 ASSERT_TRUE(decoder->DecodeToYUV());
133 }
134
135 // Tests failure on a too big image.
136 TEST(JPEGImageDecoderTest, tooBig) {
137 std::unique_ptr<ImageDecoder> decoder = CreateDecoder(100);
138 EXPECT_FALSE(decoder->SetSize(10000, 10000));
139 EXPECT_TRUE(decoder->Failed());
140 }
141
142 // Tests that the JPEG decoder can downsample image whose width and height are
143 // multiples of 8, to ensure we compute the correct DecodedSize and pass correct
144 // parameters to libjpeg to output the image with the expected size.
145 TEST(JPEGImageDecoderTest, downsampleImageSizeMultipleOf8) {
146 const char* jpeg_file = "/LayoutTests/images/resources/lenna.jpg"; // 256x256
147 unsigned output_width, output_height;
148
149 // 1/8 downsample.
150 Downsample(40 * 40 * 4, &output_width, &output_height, jpeg_file);
151 EXPECT_EQ(32u, output_width);
152 EXPECT_EQ(32u, output_height);
153
154 // 2/8 downsample.
155 Downsample(70 * 70 * 4, &output_width, &output_height, jpeg_file);
156 EXPECT_EQ(64u, output_width);
157 EXPECT_EQ(64u, output_height);
158
159 // 3/8 downsample.
160 Downsample(100 * 100 * 4, &output_width, &output_height, jpeg_file);
161 EXPECT_EQ(96u, output_width);
162 EXPECT_EQ(96u, output_height);
163
164 // 4/8 downsample.
165 Downsample(130 * 130 * 4, &output_width, &output_height, jpeg_file);
166 EXPECT_EQ(128u, output_width);
167 EXPECT_EQ(128u, output_height);
168
169 // 5/8 downsample.
170 Downsample(170 * 170 * 4, &output_width, &output_height, jpeg_file);
171 EXPECT_EQ(160u, output_width);
172 EXPECT_EQ(160u, output_height);
173
174 // 6/8 downsample.
175 Downsample(200 * 200 * 4, &output_width, &output_height, jpeg_file);
176 EXPECT_EQ(192u, output_width);
177 EXPECT_EQ(192u, output_height);
178
179 // 7/8 downsample.
180 Downsample(230 * 230 * 4, &output_width, &output_height, jpeg_file);
181 EXPECT_EQ(224u, output_width);
182 EXPECT_EQ(224u, output_height);
183 }
184
185 // Tests that JPEG decoder can downsample image whose width and height are not
186 // multiple of 8. Ensures that we round using the same algorithm as libjpeg.
187 TEST(JPEGImageDecoderTest, downsampleImageSizeNotMultipleOf8) {
188 const char* jpeg_file =
189 "/LayoutTests/images/resources/icc-v2-gbr.jpg"; // 275x207
190 unsigned output_width, output_height;
191
192 // 1/8 downsample.
193 Downsample(40 * 40 * 4, &output_width, &output_height, jpeg_file);
194 EXPECT_EQ(35u, output_width);
195 EXPECT_EQ(26u, output_height);
196
197 // 2/8 downsample.
198 Downsample(70 * 70 * 4, &output_width, &output_height, jpeg_file);
199 EXPECT_EQ(69u, output_width);
200 EXPECT_EQ(52u, output_height);
201
202 // 3/8 downsample.
203 Downsample(100 * 100 * 4, &output_width, &output_height, jpeg_file);
204 EXPECT_EQ(104u, output_width);
205 EXPECT_EQ(78u, output_height);
206
207 // 4/8 downsample.
208 Downsample(130 * 130 * 4, &output_width, &output_height, jpeg_file);
209 EXPECT_EQ(138u, output_width);
210 EXPECT_EQ(104u, output_height);
211
212 // 5/8 downsample.
213 Downsample(170 * 170 * 4, &output_width, &output_height, jpeg_file);
214 EXPECT_EQ(172u, output_width);
215 EXPECT_EQ(130u, output_height);
216
217 // 6/8 downsample.
218 Downsample(200 * 200 * 4, &output_width, &output_height, jpeg_file);
219 EXPECT_EQ(207u, output_width);
220 EXPECT_EQ(156u, output_height);
221
222 // 7/8 downsample.
223 Downsample(230 * 230 * 4, &output_width, &output_height, jpeg_file);
224 EXPECT_EQ(241u, output_width);
225 EXPECT_EQ(182u, output_height);
226 }
227
228 // Tests that upsampling is not allowed.
229 TEST(JPEGImageDecoderTest, upsample) {
230 const char* jpeg_file = "/LayoutTests/images/resources/lenna.jpg"; // 256x256
231 unsigned output_width, output_height;
232 Downsample(kLargeEnoughSize, &output_width, &output_height, jpeg_file);
233 EXPECT_EQ(256u, output_width);
234 EXPECT_EQ(256u, output_height);
235 }
236
237 TEST(JPEGImageDecoderTest, yuv) {
238 const char* jpeg_file =
239 "/LayoutTests/images/resources/lenna.jpg"; // 256x256, YUV 4:2:0
240 unsigned output_y_width, output_y_height, output_uv_width, output_uv_height;
241 ReadYUV(kLargeEnoughSize, &output_y_width, &output_y_height, &output_uv_width,
242 &output_uv_height, jpeg_file);
243 EXPECT_EQ(256u, output_y_width);
244 EXPECT_EQ(256u, output_y_height);
245 EXPECT_EQ(128u, output_uv_width);
246 EXPECT_EQ(128u, output_uv_height);
247
248 const char* jpeg_file_image_size_not_multiple_of8 =
249 "/LayoutTests/images/resources/cropped_mandrill.jpg"; // 439x154
250 ReadYUV(kLargeEnoughSize, &output_y_width, &output_y_height, &output_uv_width,
251 &output_uv_height, jpeg_file_image_size_not_multiple_of8);
252 EXPECT_EQ(439u, output_y_width);
253 EXPECT_EQ(154u, output_y_height);
254 EXPECT_EQ(220u, output_uv_width);
255 EXPECT_EQ(77u, output_uv_height);
256
257 // Make sure we revert to RGBA decoding when we're about to downscale,
258 // which can occur on memory-constrained android devices.
259 RefPtr<SharedBuffer> data = ReadFile(jpeg_file);
260 ASSERT_TRUE(data);
261
262 std::unique_ptr<ImageDecoder> decoder = CreateDecoder(230 * 230 * 4);
263 decoder->SetData(data.Get(), true);
264
265 std::unique_ptr<ImagePlanes> image_planes = WTF::MakeUnique<ImagePlanes>();
266 decoder->SetImagePlanes(std::move(image_planes));
267 ASSERT_TRUE(decoder->IsSizeAvailable());
268 ASSERT_FALSE(decoder->CanDecodeToYUV());
269 }
270
271 TEST(JPEGImageDecoderTest,
272 byteByByteBaselineJPEGWithColorProfileAndRestartMarkers) {
273 TestByteByByteDecode(&CreateDecoder,
274 "/LayoutTests/images/resources/"
275 "small-square-with-colorspin-profile.jpg",
276 1u, kAnimationNone);
277 }
278
279 TEST(JPEGImageDecoderTest, byteByByteProgressiveJPEG) {
280 TestByteByByteDecode(&CreateDecoder,
281 "/LayoutTests/images/resources/bug106024.jpg", 1u,
282 kAnimationNone);
283 }
284
285 TEST(JPEGImageDecoderTest, byteByByteRGBJPEGWithAdobeMarkers) {
286 TestByteByByteDecode(
287 &CreateDecoder,
288 "/LayoutTests/images/resources/rgb-jpeg-with-adobe-marker-only.jpg", 1u,
289 kAnimationNone);
290 }
291
292 // This test verifies that calling SharedBuffer::MergeSegmentsIntoBuffer() does
293 // not break JPEG decoding at a critical point: in between a call to decode the
294 // size (when JPEGImageDecoder stops while it may still have input data to
295 // read) and a call to do a full decode.
296 TEST(JPEGImageDecoderTest, mergeBuffer) {
297 const char* jpeg_file = "/LayoutTests/images/resources/lenna.jpg";
298 TestMergeBuffer(&CreateDecoder, jpeg_file);
299 }
300
301 // This tests decoding a JPEG with many progressive scans. Decoding should
302 // fail, but not hang (crbug.com/642462).
303 TEST(JPEGImageDecoderTest, manyProgressiveScans) {
304 RefPtr<SharedBuffer> test_data =
305 ReadFile(kDecodersTestingDir, "many-progressive-scans.jpg");
306 ASSERT_TRUE(test_data.Get());
307
308 std::unique_ptr<ImageDecoder> test_decoder = CreateDecoder();
309 test_decoder->SetData(test_data.Get(), true);
310 EXPECT_EQ(1u, test_decoder->FrameCount());
311 ASSERT_TRUE(test_decoder->FrameBufferAtIndex(0));
312 EXPECT_TRUE(test_decoder->Failed());
313 }
314
315 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698