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

Side by Side Diff: third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp

Issue 2522693002: Color correct ImageBitmap(HTMLImageElement*) constructor (Closed)
Patch Set: Created 4 years, 1 month 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
1 /* 1 /*
2 * Copyright (c) 2013, Google Inc. All rights reserved. 2 * Copyright (c) 2013, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 23 matching lines...) Expand all
34 #include "core/dom/Document.h" 34 #include "core/dom/Document.h"
35 #include "core/fetch/ImageResource.h" 35 #include "core/fetch/ImageResource.h"
36 #include "core/fetch/MemoryCache.h" 36 #include "core/fetch/MemoryCache.h"
37 #include "core/html/HTMLCanvasElement.h" 37 #include "core/html/HTMLCanvasElement.h"
38 #include "core/html/HTMLImageElement.h" 38 #include "core/html/HTMLImageElement.h"
39 #include "core/html/HTMLVideoElement.h" 39 #include "core/html/HTMLVideoElement.h"
40 #include "platform/graphics/StaticBitmapImage.h" 40 #include "platform/graphics/StaticBitmapImage.h"
41 #include "platform/graphics/skia/SkiaUtils.h" 41 #include "platform/graphics/skia/SkiaUtils.h"
42 #include "platform/heap/Handle.h" 42 #include "platform/heap/Handle.h"
43 #include "platform/network/ResourceRequest.h" 43 #include "platform/network/ResourceRequest.h"
44 #include "ui/gfx/color_space.h"
45 #include "ui/gfx/icc_profile.h"
44 #include "testing/gtest/include/gtest/gtest.h" 46 #include "testing/gtest/include/gtest/gtest.h"
45 #include "third_party/skia/include/core/SkCanvas.h" 47 #include "third_party/skia/include/core/SkCanvas.h"
48 #include "third_party/skia/include/core/SkColorSpaceXform.h"
46 #include "third_party/skia/include/core/SkImage.h" 49 #include "third_party/skia/include/core/SkImage.h"
47 #include "third_party/skia/include/core/SkSurface.h" 50 #include "third_party/skia/include/core/SkSurface.h"
48 51
49 namespace blink { 52 namespace blink {
50 53
51 class ImageBitmapTest : public ::testing::Test { 54 class ImageBitmapTest : public ::testing::Test {
52 protected: 55 protected:
53 virtual void SetUp() { 56 virtual void SetUp() {
54 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(10, 10); 57 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(10, 10);
55 surface->getCanvas()->clear(0xFFFFFFFF); 58 surface->getCanvas()->clear(0xFFFFFFFF);
56 m_image = surface->makeImageSnapshot(); 59 m_image = surface->makeImageSnapshot();
57 60
58 sk_sp<SkSurface> surface2 = SkSurface::MakeRasterN32Premul(5, 5); 61 sk_sp<SkSurface> surface2 = SkSurface::MakeRasterN32Premul(5, 5);
59 surface2->getCanvas()->clear(0xAAAAAAAA); 62 surface2->getCanvas()->clear(0xAAAAAAAA);
60 m_image2 = surface2->makeImageSnapshot(); 63 m_image2 = surface2->makeImageSnapshot();
61 64
62 // Save the global memory cache to restore it upon teardown. 65 // Save the global memory cache to restore it upon teardown.
63 m_globalMemoryCache = replaceMemoryCacheForTesting(MemoryCache::create()); 66 m_globalMemoryCache = replaceMemoryCacheForTesting(MemoryCache::create());
67
68 // Save the state of experimental canvas features and color correct
69 // rendering flags to restore them upon teardown.
70 experimentalCanvasFeatures =
71 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled();
72 colorCorrectRendering = RuntimeEnabledFeatures::colorCorrectRenderingEnabled ();
64 } 73 }
65 virtual void TearDown() { 74 virtual void TearDown() {
66 // Garbage collection is required prior to switching out the 75 // Garbage collection is required prior to switching out the
67 // test's memory cache; image resources are released, evicting 76 // test's memory cache; image resources are released, evicting
68 // them from the cache. 77 // them from the cache.
69 ThreadState::current()->collectGarbage(BlinkGC::NoHeapPointersOnStack, 78 ThreadState::current()->collectGarbage(BlinkGC::NoHeapPointersOnStack,
70 BlinkGC::GCWithSweep, 79 BlinkGC::GCWithSweep,
71 BlinkGC::ForcedGC); 80 BlinkGC::ForcedGC);
72 81
73 replaceMemoryCacheForTesting(m_globalMemoryCache.release()); 82 replaceMemoryCacheForTesting(m_globalMemoryCache.release());
83 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(experimentalCan vasFeatures);
84 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(colorCorrectRenderin g);
74 } 85 }
75 86
76 sk_sp<SkImage> m_image, m_image2; 87 sk_sp<SkImage> m_image, m_image2;
77 Persistent<MemoryCache> m_globalMemoryCache; 88 Persistent<MemoryCache> m_globalMemoryCache;
89 bool experimentalCanvasFeatures;
90 bool colorCorrectRendering;
78 }; 91 };
79 92
80 TEST_F(ImageBitmapTest, ImageResourceConsistency) { 93 TEST_F(ImageBitmapTest, ImageResourceConsistency) {
81 const ImageBitmapOptions defaultOptions; 94 const ImageBitmapOptions defaultOptions;
82 HTMLImageElement* imageElement = 95 HTMLImageElement* imageElement =
83 HTMLImageElement::create(*Document::create()); 96 HTMLImageElement::create(*Document::create());
84 ImageResource* image = 97 ImageResource* image =
85 ImageResource::create(StaticBitmapImage::create(m_image).get()); 98 ImageResource::create(StaticBitmapImage::create(m_image).get());
86 imageElement->setImageResource(image); 99 imageElement->setImageResource(image);
87 100
(...skipping 22 matching lines...) Expand all
110 imageElement->cachedImage()->getImage()->imageForCurrentFrame()); 123 imageElement->cachedImage()->getImage()->imageForCurrentFrame());
111 124
112 StaticBitmapImage* emptyImage = imageBitmapOutsideCrop->bitmapImage(); 125 StaticBitmapImage* emptyImage = imageBitmapOutsideCrop->bitmapImage();
113 ASSERT_NE(emptyImage->imageForCurrentFrame(), 126 ASSERT_NE(emptyImage->imageForCurrentFrame(),
114 imageElement->cachedImage()->getImage()->imageForCurrentFrame()); 127 imageElement->cachedImage()->getImage()->imageForCurrentFrame());
115 } 128 }
116 129
117 // Verifies that ImageBitmaps constructed from HTMLImageElements hold a 130 // Verifies that ImageBitmaps constructed from HTMLImageElements hold a
118 // reference to the original Image if the HTMLImageElement src is changed. 131 // reference to the original Image if the HTMLImageElement src is changed.
119 TEST_F(ImageBitmapTest, ImageBitmapSourceChanged) { 132 TEST_F(ImageBitmapTest, ImageBitmapSourceChanged) {
133 // For this test to work correctly, color correct rendering must be false.
134 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(false);
135 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(false);
136
120 HTMLImageElement* image = HTMLImageElement::create(*Document::create()); 137 HTMLImageElement* image = HTMLImageElement::create(*Document::create());
121 ImageResource* originalImageResource = 138 ImageResource* originalImageResource =
122 ImageResource::create(StaticBitmapImage::create(m_image).get()); 139 ImageResource::create(StaticBitmapImage::create(m_image).get());
123 image->setImageResource(originalImageResource); 140 image->setImageResource(originalImageResource);
124 141
125 const ImageBitmapOptions defaultOptions; 142 const ImageBitmapOptions defaultOptions;
126 Optional<IntRect> cropRect = 143 Optional<IntRect> cropRect =
127 IntRect(0, 0, m_image->width(), m_image->height()); 144 IntRect(0, 0, m_image->width(), m_image->height());
128 ImageBitmap* imageBitmap = ImageBitmap::create( 145 ImageBitmap* imageBitmap = ImageBitmap::create(
129 image, cropRect, &(image->document()), defaultOptions); 146 image, cropRect, &(image->document()), defaultOptions);
(...skipping 21 matching lines...) Expand all
151 newImageResource->getImage()->imageForCurrentFrame()); 168 newImageResource->getImage()->imageForCurrentFrame());
152 SkImage* image1 = imageBitmap->bitmapImage()->imageForCurrentFrame().get(); 169 SkImage* image1 = imageBitmap->bitmapImage()->imageForCurrentFrame().get();
153 ASSERT_NE(image1, nullptr); 170 ASSERT_NE(image1, nullptr);
154 SkImage* image2 = 171 SkImage* image2 =
155 newImageResource->getImage()->imageForCurrentFrame().get(); 172 newImageResource->getImage()->imageForCurrentFrame().get();
156 ASSERT_NE(image2, nullptr); 173 ASSERT_NE(image2, nullptr);
157 ASSERT_NE(image1, image2); 174 ASSERT_NE(image1, image2);
158 } 175 }
159 } 176 }
160 177
178 enum class ColorSpaceConversion : uint8_t {
179 NONE = 0,
180 // this is the only mode that is not color corrected
181 DEFAULT_NOT_COLOR_CORRECTED = 1,
182 DEFAULT_COLOR_CORRECTED = 2,
183 SRGB = 3,
184 LINEAR_RGB = 4,
185
186 LAST = LINEAR_RGB
187 };
188
189 static ImageBitmap* createImageBitmapWithColorSpaceConversion(
190 HTMLImageElement* image,
191 Optional<IntRect>& cropRect,
192 Document* document,
193 const ColorSpaceConversion& colorSpaceConversion) {
194 // Set the color space conversion in ImageBitmapOptions
195 ImageBitmapOptions options;
196 static const std::vector<std::string> conversions =
197 {"none", "default", "default", "srgb", "linear-rgb"};
198 options.setColorSpaceConversion(
199 WTF::String(conversions[(uint8_t)(colorSpaceConversion)].c_str()));
200
201 // Set the runtime flags
202 bool runtimeFlag =
203 (colorSpaceConversion !=
204 ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED);
205 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(runtimeFlag);
206 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(runtimeFlag);
207
208 // Create and return the ImageBitmap
209 return ImageBitmap::create(
210 image, cropRect, &(image->document()), options);
211 }
212
213 TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversion) {
214 HTMLImageElement* imageElement =
215 HTMLImageElement::create(*Document::create());
216
217 SkPaint p;
218 p.setColor(SK_ColorRED);
219 sk_sp<SkColorSpace> srcRGBColorSpace =
220 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
221
222 SkImageInfo rasterImageInfo =
223 SkImageInfo::MakeN32Premul(100, 100, srcRGBColorSpace);
224 sk_sp<SkSurface> surface(SkSurface::MakeRaster(rasterImageInfo));
225 surface->getCanvas()->drawCircle(50, 50, 50, p);
226 sk_sp<SkImage> image = surface->makeImageSnapshot();
227
228 uint8_t* srcPixel = new uint8_t[rasterImageInfo.bytesPerPixel()];
229 image->readPixels(rasterImageInfo.makeWH(1,1),
230 (void *)(srcPixel),
231 image->width() * rasterImageInfo.bytesPerPixel(),
232 50, 50);
233
234 // for(int i = 0; i < rasterImageInfo.bytesPerPixel(); i++)
235 // LOG(ERROR) << "====== " << (int)(srcPixel[i]);
236
237 ImageResource* originalImageResource =
238 ImageResource::create(StaticBitmapImage::create(image).get());
239 imageElement->setImageResource(originalImageResource);
240
241 Optional<IntRect> cropRect =
242 IntRect(0, 0, image->width(), image->height());
243
244 // Create and test the ImageBitmap objects.
245 // We don't check "none" color space conversion as it requires the encoded
246 // data in a format readable by ImageDecoder. Furthermore, the code path for
247 // "none" color space conversion is not affected by this CL.
248
249 sk_sp<SkColorSpace> colorSpace = nullptr;
250 SkColorType colorType = SkColorType::kN32_SkColorType;
251 SkColorSpaceXform::ColorFormat colorFormat32 =
252 (colorType == kBGRA_8888_SkColorType) ?
253 SkColorSpaceXform::ColorFormat::kBGRA_8888_ColorFormat :
254 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
255 SkColorSpaceXform::ColorFormat colorFormat = colorFormat32;
256 gfx::ColorSpace gfxColorSpace =
257 gfx::ICCProfile::FromBestMonitor().GetColorSpace();
258
259 for (uint8_t i = (uint8_t)(ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED);
260 i <= (uint8_t)(ColorSpaceConversion::LAST); i++) {
261
262 ColorSpaceConversion csConversion = (ColorSpaceConversion)(i);
263 ImageBitmap* imageBitmap = createImageBitmapWithColorSpaceConversion(
264 imageElement, cropRect, &(imageElement->document()), csConversion);
265 SkImage* convertedImage =
266 imageBitmap->bitmapImage()->imageForCurrentFrame().get();
267
268 switch(csConversion) {
269 case ColorSpaceConversion::NONE:
270 NOTREACHED();
271 break;
272 case ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED:
273 colorSpace =
274 (gfxColorSpace != gfx::ColorSpace()) ?
275 gfxColorSpace.ToSkColorSpace() :
276 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
277 colorFormat = colorFormat32;
278 break;
279 case ColorSpaceConversion::DEFAULT_COLOR_CORRECTED:
280 case ColorSpaceConversion::SRGB:
281 colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
282 colorFormat = colorFormat32;
283 break;
284 case ColorSpaceConversion::LINEAR_RGB:
285 colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named);
286 colorType = SkColorType::kRGBA_F16_SkColorType;
287 colorFormat = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
288 break;
289 default:
290 NOTREACHED();
291 }
292
293 SkImageInfo imageInfo = SkImageInfo::Make(1, 1, colorType,
294 SkAlphaType::kPremul_SkAlphaType,
295 colorSpace);
296 uint8_t* convertedPixel = new uint8_t[imageInfo.bytesPerPixel()];
297 convertedImage->readPixels(
298 imageInfo, (void *)(convertedPixel), convertedImage->width() *
299 imageInfo.bytesPerPixel(), 50, 50);
300
301 // for(int j = 0; j < imageInfo.bytesPerPixel(); j++)
302 // LOG(ERROR) << "====== " << (int)(convertedPixel[j]);
303
304 // Transform the source pixel and check if the image bitmap color conversion
305 // is done correctly.
306 std::unique_ptr<SkColorSpaceXform> colorSpaceXform =
307 SkColorSpaceXform::New(srcRGBColorSpace.get(), colorSpace.get());
308 uint8_t* transformedPixel = new uint8_t[imageInfo.bytesPerPixel()];
309 colorSpaceXform->apply(colorFormat, (void *)(transformedPixel),
310 colorFormat32, (void *)(srcPixel), 1,
311 SkAlphaType::kPremul_SkAlphaType);
312
313 // for(int j = 0; j < imageInfo.bytesPerPixel(); j++)
314 // LOG(ERROR) << "====== " << (int)(transformedPixel[j]);
315
316 int compare = std::memcmp(convertedPixel, transformedPixel, imageInfo.bytesP erPixel());
317 ASSERT_EQ(compare, 0);
318 }
319 }
320
161 } // namespace blink 321 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698