OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <math.h> | 5 #include <math.h> |
6 #include <stddef.h> | 6 #include <stddef.h> |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 if (a.empty()) | 81 if (a.empty()) |
82 return 0; // prevent divide by 0 below | 82 return 0; // prevent divide by 0 below |
83 | 83 |
84 double acc = 0.0; | 84 double acc = 0.0; |
85 for (size_t i = 0; i < a.size(); i++) | 85 for (size_t i = 0; i < a.size(); i++) |
86 acc += fabs(static_cast<double>(a[i]) - static_cast<double>(b[i])); | 86 acc += fabs(static_cast<double>(a[i]) - static_cast<double>(b[i])); |
87 | 87 |
88 return acc / static_cast<double>(a.size()); | 88 return acc / static_cast<double>(a.size()); |
89 } | 89 } |
90 | 90 |
91 static void MakeRGBImage(int w, int h, std::vector<unsigned char>* dat) { | 91 static void MakeRGBAImage(int w, int h, std::vector<unsigned char>* dat) { |
92 dat->resize(w * h * 3); | 92 dat->resize(w * h * 4); |
93 for (int y = 0; y < h; y++) { | 93 for (int y = 0; y < h; y++) { |
94 for (int x = 0; x < w; x++) { | 94 for (int x = 0; x < w; x++) { |
95 unsigned char* org_px = &(*dat)[(y * w + x) * 3]; | 95 unsigned char* org_px = &(*dat)[(y * w + x) * 4]; |
96 org_px[0] = x * 3; // r | 96 org_px[0] = x * 3; // r |
97 org_px[1] = x * 3 + 1; // g | 97 org_px[1] = x * 3 + 1; // g |
98 org_px[2] = x * 3 + 2; // b | 98 org_px[2] = x * 3 + 2; // b |
| 99 org_px[3] = 0xFF; // a |
99 } | 100 } |
100 } | 101 } |
101 } | 102 } |
102 | 103 |
103 TEST(JPEGCodec, EncodeDecodeRGB) { | |
104 int w = 20, h = 20; | |
105 | |
106 // create an image with known values | |
107 std::vector<unsigned char> original; | |
108 MakeRGBImage(w, h, &original); | |
109 | |
110 // encode, making sure it was compressed some | |
111 std::vector<unsigned char> encoded; | |
112 EXPECT_TRUE(JPEGCodec::Encode(&original[0], JPEGCodec::FORMAT_RGB, w, h, | |
113 w * 3, jpeg_quality, &encoded)); | |
114 EXPECT_GT(original.size(), encoded.size()); | |
115 | |
116 // decode, it should have the same size as the original | |
117 std::vector<unsigned char> decoded; | |
118 int outw, outh; | |
119 EXPECT_TRUE(JPEGCodec::Decode(&encoded[0], encoded.size(), | |
120 JPEGCodec::FORMAT_RGB, &decoded, | |
121 &outw, &outh)); | |
122 ASSERT_EQ(w, outw); | |
123 ASSERT_EQ(h, outh); | |
124 ASSERT_EQ(original.size(), decoded.size()); | |
125 | |
126 // Images must be approximately equal (compression will have introduced some | |
127 // minor artifacts). | |
128 ASSERT_GE(jpeg_equality_threshold, AveragePixelDelta(original, decoded)); | |
129 } | |
130 | |
131 TEST(JPEGCodec, EncodeDecodeRGBA) { | 104 TEST(JPEGCodec, EncodeDecodeRGBA) { |
132 int w = 20, h = 20; | 105 int w = 20, h = 20; |
133 | 106 |
134 // create an image with known values, a must be opaque because it will be | 107 // create an image with known values, a must be opaque because it will be |
135 // lost during compression | 108 // lost during compression |
136 std::vector<unsigned char> original; | 109 std::vector<unsigned char> original; |
137 original.resize(w * h * 4); | 110 MakeRGBAImage(w, h, &original); |
138 for (int y = 0; y < h; y++) { | |
139 for (int x = 0; x < w; x++) { | |
140 unsigned char* org_px = &original[(y * w + x) * 4]; | |
141 org_px[0] = x * 3; // r | |
142 org_px[1] = x * 3 + 1; // g | |
143 org_px[2] = x * 3 + 2; // b | |
144 org_px[3] = 0xFF; // a (opaque) | |
145 } | |
146 } | |
147 | 111 |
148 // encode, making sure it was compressed some | 112 // encode, making sure it was compressed some |
149 std::vector<unsigned char> encoded; | 113 std::vector<unsigned char> encoded; |
150 EXPECT_TRUE(JPEGCodec::Encode(&original[0], JPEGCodec::FORMAT_RGBA, w, h, | 114 EXPECT_TRUE(JPEGCodec::Encode(&original[0], kRGBA_8888_SkColorType, w, h, |
151 w * 4, jpeg_quality, &encoded)); | 115 w * 4, jpeg_quality, &encoded)); |
152 EXPECT_GT(original.size(), encoded.size()); | 116 EXPECT_GT(original.size(), encoded.size()); |
153 | 117 |
154 // decode, it should have the same size as the original | 118 // decode, it should have the same size as the original |
155 std::vector<unsigned char> decoded; | 119 std::vector<unsigned char> decoded; |
156 int outw, outh; | 120 int outw, outh; |
157 EXPECT_TRUE(JPEGCodec::Decode(&encoded[0], encoded.size(), | 121 EXPECT_TRUE(JPEGCodec::Decode(&encoded[0], encoded.size(), |
158 JPEGCodec::FORMAT_RGBA, &decoded, | 122 JPEGCodec::FORMAT_RGBA, &decoded, |
159 &outw, &outh)); | 123 &outw, &outh)); |
160 ASSERT_EQ(w, outw); | 124 ASSERT_EQ(w, outw); |
161 ASSERT_EQ(h, outh); | 125 ASSERT_EQ(h, outh); |
162 ASSERT_EQ(original.size(), decoded.size()); | 126 ASSERT_EQ(original.size(), decoded.size()); |
163 | 127 |
164 // Images must be approximately equal (compression will have introduced some | 128 // Images must be approximately equal (compression will have introduced some |
165 // minor artifacts). | 129 // minor artifacts). |
166 ASSERT_GE(jpeg_equality_threshold, AveragePixelDelta(original, decoded)); | 130 ASSERT_GE(jpeg_equality_threshold, AveragePixelDelta(original, decoded)); |
167 } | 131 } |
168 | 132 |
169 // Test that corrupted data decompression causes failures. | 133 // Test that corrupted data decompression causes failures. |
170 TEST(JPEGCodec, DecodeCorrupted) { | 134 TEST(JPEGCodec, DecodeCorrupted) { |
171 int w = 20, h = 20; | 135 int w = 20, h = 20; |
172 | 136 |
173 // some random data (an uncompressed image) | 137 // some random data (an uncompressed image) |
174 std::vector<unsigned char> original; | 138 std::vector<unsigned char> original; |
175 MakeRGBImage(w, h, &original); | 139 MakeRGBAImage(w, h, &original); |
176 | 140 |
177 // it should fail when given non-JPEG compressed data | 141 // it should fail when given non-JPEG compressed data |
178 std::vector<unsigned char> output; | 142 std::vector<unsigned char> output; |
179 int outw, outh; | 143 int outw, outh; |
180 ASSERT_FALSE(JPEGCodec::Decode(&original[0], original.size(), | 144 ASSERT_FALSE(JPEGCodec::Decode(&original[0], original.size(), |
181 JPEGCodec::FORMAT_RGB, &output, | 145 JPEGCodec::FORMAT_RGBA, &output, &outw, |
182 &outw, &outh)); | 146 &outh)); |
183 | 147 |
184 // make some compressed data | 148 // make some compressed data |
185 std::vector<unsigned char> compressed; | 149 std::vector<unsigned char> compressed; |
186 ASSERT_TRUE(JPEGCodec::Encode(&original[0], JPEGCodec::FORMAT_RGB, w, h, | 150 ASSERT_TRUE(JPEGCodec::Encode(&original[0], kRGBA_8888_SkColorType, w, h, |
187 w * 3, jpeg_quality, &compressed)); | 151 w * 4, jpeg_quality, &compressed)); |
188 | 152 |
189 // try decompressing a truncated version | 153 // try decompressing a truncated version |
190 ASSERT_FALSE(JPEGCodec::Decode(&compressed[0], compressed.size() / 2, | 154 ASSERT_FALSE(JPEGCodec::Decode(&compressed[0], compressed.size() / 2, |
191 JPEGCodec::FORMAT_RGB, &output, | 155 JPEGCodec::FORMAT_RGBA, &output, &outw, |
192 &outw, &outh)); | 156 &outh)); |
193 | 157 |
194 // corrupt it and try decompressing that | 158 // corrupt it and try decompressing that |
195 for (int i = 10; i < 30; i++) | 159 for (int i = 10; i < 30; i++) |
196 compressed[i] = i; | 160 compressed[i] = i; |
197 ASSERT_FALSE(JPEGCodec::Decode(&compressed[0], compressed.size(), | 161 ASSERT_FALSE(JPEGCodec::Decode(&compressed[0], compressed.size(), |
198 JPEGCodec::FORMAT_RGB, &output, | 162 JPEGCodec::FORMAT_RGBA, &output, &outw, |
199 &outw, &outh)); | 163 &outh)); |
200 } | 164 } |
201 | 165 |
202 // Test that we can decode JPEG images without invalid-read errors on valgrind. | 166 // Test that we can decode JPEG images without invalid-read errors on valgrind. |
203 // This test decodes a 1x1 JPEG image and writes the decoded RGB (or RGBA) pixel | 167 // This test decodes a 1x1 JPEG image and writes the decoded RGB (or RGBA) pixel |
204 // to the output buffer without OOB reads. | 168 // to the output buffer without OOB reads. |
205 TEST(JPEGCodec, InvalidRead) { | 169 TEST(JPEGCodec, InvalidRead) { |
206 std::vector<unsigned char> output; | 170 std::vector<unsigned char> output; |
207 int outw, outh; | 171 int outw, outh; |
208 JPEGCodec::Decode(kTopSitesMigrationTestImage, | 172 JPEGCodec::Decode(kTopSitesMigrationTestImage, |
209 arraysize(kTopSitesMigrationTestImage), | 173 arraysize(kTopSitesMigrationTestImage), |
210 JPEGCodec::FORMAT_RGB, &output, | |
211 &outw, &outh); | |
212 | |
213 JPEGCodec::Decode(kTopSitesMigrationTestImage, | |
214 arraysize(kTopSitesMigrationTestImage), | |
215 JPEGCodec::FORMAT_RGBA, &output, | 174 JPEGCodec::FORMAT_RGBA, &output, |
216 &outw, &outh); | 175 &outw, &outh); |
217 } | 176 } |
218 | 177 |
219 } // namespace gfx | 178 } // namespace gfx |
OLD | NEW |