OLD | NEW |
---|---|
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 15 matching lines...) Expand all Loading... | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #include "core/frame/ImageBitmap.h" | 31 #include "core/frame/ImageBitmap.h" |
32 | 32 |
33 #include "SkPixelRef.h" // FIXME: qualify this skia header file. | 33 #include "SkPixelRef.h" // FIXME: qualify this skia header file. |
34 #include "core/dom/Document.h" | 34 #include "core/dom/Document.h" |
35 #include "core/fetch/MemoryCache.h" | 35 #include "core/fetch/MemoryCache.h" |
36 #include "core/frame/FrameView.h" | |
36 #include "core/html/HTMLCanvasElement.h" | 37 #include "core/html/HTMLCanvasElement.h" |
37 #include "core/html/HTMLImageElement.h" | 38 #include "core/html/HTMLImageElement.h" |
38 #include "core/html/HTMLVideoElement.h" | 39 #include "core/html/HTMLVideoElement.h" |
39 #include "core/loader/resource/ImageResourceContent.h" | 40 #include "core/loader/resource/ImageResourceContent.h" |
40 #include "platform/graphics/StaticBitmapImage.h" | 41 #include "platform/graphics/StaticBitmapImage.h" |
41 #include "platform/graphics/skia/SkiaUtils.h" | 42 #include "platform/graphics/skia/SkiaUtils.h" |
42 #include "platform/heap/Handle.h" | 43 #include "platform/heap/Handle.h" |
43 #include "platform/image-decoders/ImageDecoder.h" | 44 #include "platform/image-decoders/ImageDecoder.h" |
44 #include "platform/network/ResourceRequest.h" | 45 #include "platform/network/ResourceRequest.h" |
45 #include "testing/gtest/include/gtest/gtest.h" | 46 #include "testing/gtest/include/gtest/gtest.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
58 m_image = surface->makeImageSnapshot(); | 59 m_image = surface->makeImageSnapshot(); |
59 | 60 |
60 sk_sp<SkSurface> surface2 = SkSurface::MakeRasterN32Premul(5, 5); | 61 sk_sp<SkSurface> surface2 = SkSurface::MakeRasterN32Premul(5, 5); |
61 surface2->getCanvas()->clear(0xAAAAAAAA); | 62 surface2->getCanvas()->clear(0xAAAAAAAA); |
62 m_image2 = surface2->makeImageSnapshot(); | 63 m_image2 = surface2->makeImageSnapshot(); |
63 | 64 |
64 // Save the global memory cache to restore it upon teardown. | 65 // Save the global memory cache to restore it upon teardown. |
65 m_globalMemoryCache = replaceMemoryCacheForTesting(MemoryCache::create()); | 66 m_globalMemoryCache = replaceMemoryCacheForTesting(MemoryCache::create()); |
66 | 67 |
67 // Save the state of experimental canvas features and color correct | 68 // Save the state of experimental canvas features and color correct |
68 // rendering flags to restore them on teardown. | 69 // rendering flags to restore them on teardown. Each test that changes the |
70 // flags must restore them to prevent affecting other ImageBitmap tests. | |
71 // This is an extra safety precaution to prevent such an error to leak from | |
72 // this test suite. | |
dcheng
2016/12/19 21:01:03
Nit: probably revert the latter half of the commen
| |
69 experimentalCanvasFeatures = | 73 experimentalCanvasFeatures = |
70 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); | 74 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); |
71 colorCorrectRendering = | 75 colorCorrectRendering = |
72 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); | 76 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); |
73 colorCorrectRenderingDefaultMode = | 77 colorCorrectRenderingDefaultMode = |
74 RuntimeEnabledFeatures::colorCorrectRenderingDefaultModeEnabled(); | 78 RuntimeEnabledFeatures::colorCorrectRenderingDefaultModeEnabled(); |
75 } | 79 } |
76 virtual void TearDown() { | 80 virtual void TearDown() { |
77 // Garbage collection is required prior to switching out the | 81 // Garbage collection is required prior to switching out the |
78 // test's memory cache; image resources are released, evicting | 82 // test's memory cache; image resources are released, evicting |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
207 enum class ColorSpaceConversion : uint8_t { | 211 enum class ColorSpaceConversion : uint8_t { |
208 NONE = 0, | 212 NONE = 0, |
209 DEFAULT_NOT_COLOR_CORRECTED = 1, | 213 DEFAULT_NOT_COLOR_CORRECTED = 1, |
210 DEFAULT_COLOR_CORRECTED = 2, | 214 DEFAULT_COLOR_CORRECTED = 2, |
211 SRGB = 3, | 215 SRGB = 3, |
212 LINEAR_RGB = 4, | 216 LINEAR_RGB = 4, |
213 | 217 |
214 LAST = LINEAR_RGB | 218 LAST = LINEAR_RGB |
215 }; | 219 }; |
216 | 220 |
217 static ImageBitmap* createImageBitmapWithColorSpaceConversion( | 221 static ImageBitmapOptions prepareBitmapOptionsAndSetRuntimeFlags( |
218 HTMLImageElement* image, | |
219 Optional<IntRect>& cropRect, | |
220 Document* document, | |
221 const ColorSpaceConversion& colorSpaceConversion) { | 222 const ColorSpaceConversion& colorSpaceConversion) { |
222 // Set the color space conversion in ImageBitmapOptions | 223 // Set the color space conversion in ImageBitmapOptions |
223 ImageBitmapOptions options; | 224 ImageBitmapOptions options; |
224 static const Vector<String> conversions = {"none", "default", "default", | 225 static const Vector<String> conversions = {"none", "default", "default", |
225 "srgb", "linear-rgb"}; | 226 "srgb", "linear-rgb"}; |
226 options.setColorSpaceConversion( | 227 options.setColorSpaceConversion( |
227 conversions[static_cast<uint8_t>(colorSpaceConversion)]); | 228 conversions[static_cast<uint8_t>(colorSpaceConversion)]); |
228 | 229 |
229 // Set the runtime flags | 230 // Set the runtime flags |
230 bool flag = (colorSpaceConversion != | 231 bool flag = (colorSpaceConversion != |
231 ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED); | 232 ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED); |
232 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(true); | 233 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(true); |
233 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(flag); | 234 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(flag); |
234 RuntimeEnabledFeatures::setColorCorrectRenderingDefaultModeEnabled(!flag); | 235 RuntimeEnabledFeatures::setColorCorrectRenderingDefaultModeEnabled(!flag); |
235 | 236 |
236 // Create and return the ImageBitmap | 237 return options; |
237 return ImageBitmap::create(image, cropRect, &(image->document()), options); | |
238 } | 238 } |
239 | 239 |
240 TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversion) { | 240 TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionHTMLImageElement) { |
241 HTMLImageElement* imageElement = | 241 HTMLImageElement* imageElement = |
242 HTMLImageElement::create(*Document::create()); | 242 HTMLImageElement::create(*Document::create()); |
243 | 243 |
244 SkPaint p; | 244 SkPaint p; |
245 p.setColor(SK_ColorRED); | 245 p.setColor(SK_ColorRED); |
246 sk_sp<SkColorSpace> srcRGBColorSpace = | 246 sk_sp<SkColorSpace> srcRGBColorSpace = |
247 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | 247 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); |
248 | 248 |
249 SkImageInfo rasterImageInfo = | 249 SkImageInfo rasterImageInfo = |
250 SkImageInfo::MakeN32Premul(100, 100, srcRGBColorSpace); | 250 SkImageInfo::MakeN32Premul(10, 10, srcRGBColorSpace); |
251 sk_sp<SkSurface> surface(SkSurface::MakeRaster(rasterImageInfo)); | 251 sk_sp<SkSurface> surface(SkSurface::MakeRaster(rasterImageInfo)); |
252 surface->getCanvas()->drawCircle(50, 50, 50, p); | 252 surface->getCanvas()->drawCircle(5, 5, 5, p); |
253 sk_sp<SkImage> image = surface->makeImageSnapshot(); | 253 sk_sp<SkImage> image = surface->makeImageSnapshot(); |
254 | 254 |
255 std::unique_ptr<uint8_t[]> srcPixel( | 255 std::unique_ptr<uint8_t[]> srcPixel( |
256 new uint8_t[rasterImageInfo.bytesPerPixel()]()); | 256 new uint8_t[rasterImageInfo.bytesPerPixel()]()); |
257 image->readPixels(rasterImageInfo.makeWH(1, 1), srcPixel.get(), | 257 image->readPixels(rasterImageInfo.makeWH(1, 1), srcPixel.get(), |
258 image->width() * rasterImageInfo.bytesPerPixel(), 50, 50); | 258 image->width() * rasterImageInfo.bytesPerPixel(), 5, 5); |
259 | 259 |
260 ImageResourceContent* originalImageResource = | 260 ImageResourceContent* originalImageResource = |
261 ImageResourceContent::create(StaticBitmapImage::create(image).get()); | 261 ImageResourceContent::create(StaticBitmapImage::create(image).get()); |
262 imageElement->setImageResource(originalImageResource); | 262 imageElement->setImageResource(originalImageResource); |
263 | 263 |
264 Optional<IntRect> cropRect = IntRect(0, 0, image->width(), image->height()); | 264 Optional<IntRect> cropRect = IntRect(0, 0, image->width(), image->height()); |
265 | 265 |
266 // Create and test the ImageBitmap objects. | 266 // Create and test the ImageBitmap objects. |
267 // We don't check "none" color space conversion as it requires the encoded | 267 // We don't check "none" color space conversion as it requires the encoded |
268 // data in a format readable by ImageDecoder. Furthermore, the code path for | 268 // data in a format readable by ImageDecoder. Furthermore, the code path for |
269 // "none" color space conversion is not affected by this CL. | 269 // "none" color space conversion is not affected by this CL. |
270 | 270 |
271 sk_sp<SkColorSpace> colorSpace = nullptr; | 271 sk_sp<SkColorSpace> colorSpace = nullptr; |
272 SkColorType colorType = SkColorType::kN32_SkColorType; | 272 SkColorType colorType = SkColorType::kN32_SkColorType; |
273 SkColorSpaceXform::ColorFormat colorFormat32 = | 273 SkColorSpaceXform::ColorFormat colorFormat32 = |
274 (colorType == kBGRA_8888_SkColorType) | 274 (colorType == kBGRA_8888_SkColorType) |
275 ? SkColorSpaceXform::ColorFormat::kBGRA_8888_ColorFormat | 275 ? SkColorSpaceXform::ColorFormat::kBGRA_8888_ColorFormat |
276 : SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; | 276 : SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; |
277 SkColorSpaceXform::ColorFormat colorFormat = colorFormat32; | 277 SkColorSpaceXform::ColorFormat colorFormat = colorFormat32; |
278 | 278 |
279 for (uint8_t i = static_cast<uint8_t>( | 279 for (uint8_t i = static_cast<uint8_t>( |
280 ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED); | 280 ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED); |
281 i <= static_cast<uint8_t>(ColorSpaceConversion::LAST); i++) { | 281 i <= static_cast<uint8_t>(ColorSpaceConversion::LAST); i++) { |
282 ColorSpaceConversion colorSpaceConversion = | 282 ColorSpaceConversion colorSpaceConversion = |
283 static_cast<ColorSpaceConversion>(i); | 283 static_cast<ColorSpaceConversion>(i); |
284 ImageBitmap* imageBitmap = createImageBitmapWithColorSpaceConversion( | 284 ImageBitmapOptions options = |
285 imageElement, cropRect, &(imageElement->document()), | 285 prepareBitmapOptionsAndSetRuntimeFlags(colorSpaceConversion); |
286 colorSpaceConversion); | 286 ImageBitmap* imageBitmap = ImageBitmap::create( |
287 imageElement, cropRect, &(imageElement->document()), options); | |
288 | |
289 // ColorBehavior::ignore() is used instead of | |
290 // ColorBehavior::transformToTargetForTesting() to avoid color conversion to | |
291 // display color profile, as we want to solely rely on the color correction | |
292 // that happens in ImageBitmap create method. | |
287 SkImage* convertedImage = | 293 SkImage* convertedImage = |
288 imageBitmap->bitmapImage() | 294 imageBitmap->bitmapImage() |
289 ->imageForCurrentFrame(ColorBehavior::ignore()) | 295 ->imageForCurrentFrame(ColorBehavior::ignore()) |
290 .get(); | 296 .get(); |
291 | 297 |
292 switch (colorSpaceConversion) { | 298 switch (colorSpaceConversion) { |
293 case ColorSpaceConversion::NONE: | 299 case ColorSpaceConversion::NONE: |
294 NOTREACHED(); | 300 NOTREACHED(); |
295 break; | 301 break; |
296 case ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED: | 302 case ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED: |
(...skipping 16 matching lines...) Expand all Loading... | |
313 default: | 319 default: |
314 NOTREACHED(); | 320 NOTREACHED(); |
315 } | 321 } |
316 | 322 |
317 SkImageInfo imageInfo = SkImageInfo::Make( | 323 SkImageInfo imageInfo = SkImageInfo::Make( |
318 1, 1, colorType, SkAlphaType::kPremul_SkAlphaType, colorSpace); | 324 1, 1, colorType, SkAlphaType::kPremul_SkAlphaType, colorSpace); |
319 std::unique_ptr<uint8_t[]> convertedPixel( | 325 std::unique_ptr<uint8_t[]> convertedPixel( |
320 new uint8_t[imageInfo.bytesPerPixel()]()); | 326 new uint8_t[imageInfo.bytesPerPixel()]()); |
321 convertedImage->readPixels( | 327 convertedImage->readPixels( |
322 imageInfo, convertedPixel.get(), | 328 imageInfo, convertedPixel.get(), |
323 convertedImage->width() * imageInfo.bytesPerPixel(), 50, 50); | 329 convertedImage->width() * imageInfo.bytesPerPixel(), 5, 5); |
324 | 330 |
325 // Transform the source pixel and check if the image bitmap color conversion | 331 // Transform the source pixel and check if the image bitmap color conversion |
326 // is done correctly. | 332 // is done correctly. |
333 std::unique_ptr<SkColorSpaceXform> colorSpaceXform = | |
334 SkColorSpaceXform::New(srcRGBColorSpace.get(), colorSpace.get()); | |
335 std::unique_ptr<uint8_t[]> transformedPixel( | |
336 new uint8_t[imageInfo.bytesPerPixel()]()); | |
337 colorSpaceXform->apply(colorFormat, transformedPixel.get(), colorFormat32, | |
338 srcPixel.get(), 1, SkAlphaType::kPremul_SkAlphaType); | |
339 | |
340 int compare = std::memcmp(convertedPixel.get(), transformedPixel.get(), | |
341 imageInfo.bytesPerPixel()); | |
342 ASSERT_EQ(compare, 0); | |
343 } | |
344 } | |
345 | |
346 TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionImageBitmap) { | |
347 HTMLImageElement* imageElement = | |
348 HTMLImageElement::create(*Document::create()); | |
349 | |
350 SkPaint p; | |
351 p.setColor(SK_ColorRED); | |
352 sk_sp<SkColorSpace> srcRGBColorSpace = | |
353 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | |
354 | |
355 SkImageInfo rasterImageInfo = | |
356 SkImageInfo::MakeN32Premul(10, 10, srcRGBColorSpace); | |
357 sk_sp<SkSurface> surface(SkSurface::MakeRaster(rasterImageInfo)); | |
358 surface->getCanvas()->drawCircle(5, 5, 5, p); | |
359 sk_sp<SkImage> image = surface->makeImageSnapshot(); | |
360 | |
361 std::unique_ptr<uint8_t[]> srcPixel( | |
362 new uint8_t[rasterImageInfo.bytesPerPixel()]()); | |
363 image->readPixels(rasterImageInfo.makeWH(1, 1), srcPixel.get(), | |
364 image->width() * rasterImageInfo.bytesPerPixel(), 5, 5); | |
365 | |
366 ImageResourceContent* sourceImageResource = | |
367 ImageResourceContent::create(StaticBitmapImage::create(image).get()); | |
368 imageElement->setImageResource(sourceImageResource); | |
369 | |
370 Optional<IntRect> cropRect = IntRect(0, 0, image->width(), image->height()); | |
371 ImageBitmapOptions options = | |
372 prepareBitmapOptionsAndSetRuntimeFlags(ColorSpaceConversion::SRGB); | |
373 ImageBitmap* sourceImageBitmap = ImageBitmap::create( | |
374 imageElement, cropRect, &(imageElement->document()), options); | |
375 | |
376 sk_sp<SkColorSpace> colorSpace = nullptr; | |
377 SkColorType colorType = SkColorType::kN32_SkColorType; | |
378 SkColorSpaceXform::ColorFormat colorFormat32 = | |
379 (colorType == kBGRA_8888_SkColorType) | |
380 ? SkColorSpaceXform::ColorFormat::kBGRA_8888_ColorFormat | |
381 : SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; | |
382 SkColorSpaceXform::ColorFormat colorFormat = colorFormat32; | |
383 | |
384 for (uint8_t i = static_cast<uint8_t>( | |
385 ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED); | |
386 i <= static_cast<uint8_t>(ColorSpaceConversion::LAST); i++) { | |
387 ColorSpaceConversion colorSpaceConversion = | |
388 static_cast<ColorSpaceConversion>(i); | |
389 options = prepareBitmapOptionsAndSetRuntimeFlags(colorSpaceConversion); | |
390 ImageBitmap* imageBitmap = | |
391 ImageBitmap::create(sourceImageBitmap, cropRect, options); | |
392 // ColorBehavior::ignore() is used instead of | |
393 // ColorBehavior::transformToTargetForTesting() to avoid color conversion to | |
394 // display color profile, as we want to solely rely on the color correction | |
395 // that happens in ImageBitmap create method. | |
396 SkImage* convertedImage = | |
397 imageBitmap->bitmapImage() | |
398 ->imageForCurrentFrame(ColorBehavior::ignore()) | |
399 .get(); | |
400 | |
401 switch (colorSpaceConversion) { | |
402 case ColorSpaceConversion::NONE: | |
403 NOTREACHED(); | |
404 break; | |
405 case ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED: | |
406 // TODO(zakerinasab): Replace sRGB with a call to | |
407 // ImageDecoder::globalTargetColorSpace() when the crash problem on Mac | |
408 // is fixed. crbug.com/668546. | |
409 colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | |
410 colorFormat = colorFormat32; | |
411 break; | |
412 case ColorSpaceConversion::DEFAULT_COLOR_CORRECTED: | |
413 case ColorSpaceConversion::SRGB: | |
414 colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | |
415 colorFormat = colorFormat32; | |
416 break; | |
417 case ColorSpaceConversion::LINEAR_RGB: | |
418 colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named); | |
419 colorType = SkColorType::kRGBA_F16_SkColorType; | |
420 colorFormat = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat; | |
421 break; | |
422 default: | |
423 NOTREACHED(); | |
424 } | |
425 | |
426 SkImageInfo imageInfo = SkImageInfo::Make( | |
427 1, 1, colorType, SkAlphaType::kPremul_SkAlphaType, colorSpace); | |
428 std::unique_ptr<uint8_t[]> convertedPixel( | |
429 new uint8_t[imageInfo.bytesPerPixel()]()); | |
430 convertedImage->readPixels( | |
431 imageInfo, convertedPixel.get(), | |
432 convertedImage->width() * imageInfo.bytesPerPixel(), 5, 5); | |
433 | |
434 // Transform the source pixel and check if the image bitmap color conversion | |
435 // is done correctly. | |
327 std::unique_ptr<SkColorSpaceXform> colorSpaceXform = | 436 std::unique_ptr<SkColorSpaceXform> colorSpaceXform = |
328 SkColorSpaceXform::New(srcRGBColorSpace.get(), colorSpace.get()); | 437 SkColorSpaceXform::New(srcRGBColorSpace.get(), colorSpace.get()); |
329 std::unique_ptr<uint8_t[]> transformedPixel( | 438 std::unique_ptr<uint8_t[]> transformedPixel( |
330 new uint8_t[imageInfo.bytesPerPixel()]()); | 439 new uint8_t[imageInfo.bytesPerPixel()]()); |
331 colorSpaceXform->apply(colorFormat, transformedPixel.get(), colorFormat32, | 440 colorSpaceXform->apply(colorFormat, transformedPixel.get(), colorFormat32, |
332 srcPixel.get(), 1, SkAlphaType::kPremul_SkAlphaType); | 441 srcPixel.get(), 1, SkAlphaType::kPremul_SkAlphaType); |
333 | 442 |
334 int compare = std::memcmp(convertedPixel.get(), transformedPixel.get(), | 443 int compare = std::memcmp(convertedPixel.get(), transformedPixel.get(), |
335 imageInfo.bytesPerPixel()); | 444 imageInfo.bytesPerPixel()); |
336 ASSERT_EQ(compare, 0); | 445 ASSERT_EQ(compare, 0); |
337 } | 446 } |
338 } | 447 } |
339 | 448 |
340 } // namespace blink | 449 } // namespace blink |
OLD | NEW |