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

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

Issue 2426723005: Use SkColorSpaceXform to handle color conversions in decoders (Closed)
Patch Set: Remove ifdefs - fixes blink_platform_unittests Created 4 years, 2 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
1 /* 1 /*
2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
3 * 3 *
4 * This library is free software; you can redistribute it and/or 4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public 5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either 6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version. 7 * version 2 of the License, or (at your option) any later version.
8 * 8 *
9 * This library is distributed in the hope that it will be useful, 9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 17 matching lines...) Expand all
28 #include "platform/image-decoders/gif/GIFImageDecoder.h" 28 #include "platform/image-decoders/gif/GIFImageDecoder.h"
29 #include "platform/image-decoders/ico/ICOImageDecoder.h" 29 #include "platform/image-decoders/ico/ICOImageDecoder.h"
30 #include "platform/image-decoders/jpeg/JPEGImageDecoder.h" 30 #include "platform/image-decoders/jpeg/JPEGImageDecoder.h"
31 #include "platform/image-decoders/png/PNGImageDecoder.h" 31 #include "platform/image-decoders/png/PNGImageDecoder.h"
32 #include "platform/image-decoders/webp/WEBPImageDecoder.h" 32 #include "platform/image-decoders/webp/WEBPImageDecoder.h"
33 #include "wtf/PtrUtil.h" 33 #include "wtf/PtrUtil.h"
34 #include <memory> 34 #include <memory>
35 35
36 namespace blink { 36 namespace blink {
37 37
38 #if USE(QCMSLIB)
39 struct QCMSProfileDeleter {
40 void operator()(qcms_profile* profile) {
41 if (profile)
42 qcms_profile_release(profile);
43 }
44 };
45
46 using QCMSProfileUniquePtr = std::unique_ptr<qcms_profile, QCMSProfileDeleter>;
47 #endif // USE(QCMSLIB)
48
49 inline bool matchesJPEGSignature(const char* contents) { 38 inline bool matchesJPEGSignature(const char* contents) {
50 return !memcmp(contents, "\xFF\xD8\xFF", 3); 39 return !memcmp(contents, "\xFF\xD8\xFF", 3);
51 } 40 }
52 41
53 inline bool matchesPNGSignature(const char* contents) { 42 inline bool matchesPNGSignature(const char* contents) {
54 return !memcmp(contents, "\x89PNG\r\n\x1A\n", 8); 43 return !memcmp(contents, "\x89PNG\r\n\x1A\n", 8);
55 } 44 }
56 45
57 inline bool matchesGIFSignature(const char* contents) { 46 inline bool matchesGIFSignature(const char* contents) {
58 return !memcmp(contents, "GIF87a", 6) || !memcmp(contents, "GIF89a", 6); 47 return !memcmp(contents, "GIF87a", 6) || !memcmp(contents, "GIF89a", 6);
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 void* ImagePlanes::plane(int i) { 323 void* ImagePlanes::plane(int i) {
335 ASSERT((i >= 0) && i < 3); 324 ASSERT((i >= 0) && i < 3);
336 return m_planes[i]; 325 return m_planes[i];
337 } 326 }
338 327
339 size_t ImagePlanes::rowBytes(int i) const { 328 size_t ImagePlanes::rowBytes(int i) const {
340 ASSERT((i >= 0) && i < 3); 329 ASSERT((i >= 0) && i < 3);
341 return m_rowBytes[i]; 330 return m_rowBytes[i];
342 } 331 }
343 332
344 namespace { 333 // The output device color space is global and shared across multiple threads.
345 334 SpinLock gTargetColorSpaceLock;
scroggo_chromium 2016/10/19 18:26:25 Why not leave these in an anonymous namespace?
msarett 2016/10/19 19:55:43 Didn't mean to remove this, adding it back.
346 #if USE(QCMSLIB) 335 SkColorSpace* gTargetColorSpace = nullptr;
347
348 const unsigned kIccColorProfileHeaderLength = 128;
349
350 bool rgbColorProfile(const char* profileData, unsigned profileLength) {
351 DCHECK_GE(profileLength, kIccColorProfileHeaderLength);
352
353 return !memcmp(&profileData[16], "RGB ", 4);
354 }
355
356 bool inputDeviceColorProfile(const char* profileData, unsigned profileLength) {
357 DCHECK_GE(profileLength, kIccColorProfileHeaderLength);
358
359 return !memcmp(&profileData[12], "mntr", 4) ||
360 !memcmp(&profileData[12], "scnr", 4);
361 }
362
363 // The output device color profile is global and shared across multiple threads.
364 SpinLock gTargetColorProfileLock;
365 qcms_profile* gTargetColorProfile = nullptr;
366
367 #endif // USE(QCMSLIB)
368
369 } // namespace
370 336
371 // static 337 // static
372 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) { 338 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) {
373 #if USE(QCMSLIB)
374 if (profile.isEmpty()) 339 if (profile.isEmpty())
375 return; 340 return;
376 341
377 // Take a lock around initializing and accessing the global device color 342 // Take a lock around initializing and accessing the global device color
378 // profile. 343 // profile.
379 SpinLock::Guard guard(gTargetColorProfileLock); 344 SpinLock::Guard guard(gTargetColorSpaceLock);
380 345
381 // Layout tests expect that only the first call will take effect. 346 // Layout tests expect that only the first call will take effect.
382 if (gTargetColorProfile) 347 if (gTargetColorSpace)
383 return; 348 return;
384 349
385 { 350 gTargetColorSpace =
386 sk_sp<SkColorSpace> colorSpace = 351 SkColorSpace::NewICC(profile.data(), profile.size()).release();
scroggo_chromium 2016/10/19 18:26:25 nit: Can this fit on one line?
msarett 2016/10/19 19:55:43 Autoformatter actually keeps forcing me to less th
387 SkColorSpace::NewICC(profile.data(), profile.size());
388 BitmapImageMetrics::countGamma(colorSpace.get());
389 }
390 352
391 // FIXME: Add optional ICCv4 support and support for multiple monitors. 353 // UMA statistics.
392 gTargetColorProfile = 354 BitmapImageMetrics::countGamma(gTargetColorSpace);
393 qcms_profile_from_memory(profile.data(), profile.size());
394 if (!gTargetColorProfile)
395 return;
396
397 if (qcms_profile_is_bogus(gTargetColorProfile)) {
398 qcms_profile_release(gTargetColorProfile);
399 gTargetColorProfile = nullptr;
400 return;
401 }
402
403 qcms_profile_precache_output_transform(gTargetColorProfile);
404 #endif // USE(QCMSLIB)
405 } 355 }
406 356
407 void ImageDecoder::setColorProfileAndComputeTransform(const char* iccData, 357 void ImageDecoder::setColorSpaceAndComputeTransform(const char* iccData,
408 unsigned iccLength, 358 unsigned iccLength,
409 bool hasAlpha, 359 bool useSRGB) {
410 bool useSRGB) {
411 // Sub-classes should not call this if they were instructed to ignore embedded 360 // Sub-classes should not call this if they were instructed to ignore embedded
412 // color profiles. 361 // color profiles.
413 DCHECK(!m_ignoreGammaAndColorProfile); 362 DCHECK(!m_ignoreGammaAndColorProfile);
414 363
415 m_colorProfile.assign(iccData, iccLength); 364 m_colorProfile.assign(iccData, iccLength);
416 m_hasColorProfile = true; 365 m_hasColorProfile = true;
417 366
418 // With color correct rendering, we use Skia instead of QCMS to color correct 367 // With color correct rendering, we do not transform to the output color space
419 // images. 368 // at decode time. Instead, we tag the raw image pixels and pass the tagged
369 // SkImage to Skia.
420 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) 370 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled())
421 return; 371 return;
422 372
423 #if USE(QCMSLIB) 373 m_sourceToOutputDeviceColorTransform = nullptr;
424 m_sourceToOutputDeviceColorTransform.reset();
425 374
426 // Create the input profile 375 // Create the input profile.
427 QCMSProfileUniquePtr inputProfile; 376 sk_sp<SkColorSpace> srcSpace = nullptr;
428 if (useSRGB) { 377 if (useSRGB) {
429 inputProfile.reset(qcms_profile_sRGB()); 378 srcSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
430 } else { 379 } else {
431 // Only accept RGB color profiles from input class devices. 380 srcSpace = SkColorSpace::NewICC(iccData, iccLength);
432 if (iccLength < kIccColorProfileHeaderLength)
433 return;
434 if (!rgbColorProfile(iccData, iccLength))
435 return;
436 if (!inputDeviceColorProfile(iccData, iccLength))
437 return;
438 inputProfile.reset(qcms_profile_from_memory(iccData, iccLength));
439 } 381 }
440 if (!inputProfile) 382
383 if (!srcSpace)
441 return; 384 return;
442 385
443 // We currently only support color profiles for RGB profiled images.
444 ASSERT(rgbData == qcms_profile_get_color_space(inputProfile.get()));
445
446 // Take a lock around initializing and accessing the global device color 386 // Take a lock around initializing and accessing the global device color
447 // profile. 387 // profile.
448 SpinLock::Guard guard(gTargetColorProfileLock); 388 SpinLock::Guard guard(gTargetColorSpaceLock);
449 389
450 // Initialize the output device profile to sRGB if it has not yet been 390 // Initialize the output device profile to sRGB if it has not yet been
451 // initialized. 391 // initialized.
452 if (!gTargetColorProfile) { 392 if (!gTargetColorSpace) {
453 gTargetColorProfile = qcms_profile_sRGB(); 393 gTargetColorSpace =
scroggo_chromium 2016/10/19 18:26:25 nit: Can this fit on one line?
msarett 2016/10/19 19:55:43 Autoformatter puts it on two lines.
454 qcms_profile_precache_output_transform(gTargetColorProfile); 394 SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named).release();
455 } 395 }
456 396
457 if (qcms_profile_match(inputProfile.get(), gTargetColorProfile)) 397 if (SkColorSpace::Equals(srcSpace.get(), gTargetColorSpace)) {
458 return; 398 return;
399 }
459 400
460 qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; 401 m_sourceToOutputDeviceColorTransform =
461 402 SkColorSpaceXform::New(srcSpace.get(), gTargetColorSpace);
462 // FIXME: Don't force perceptual intent if the image profile contains an
463 // intent.
464 m_sourceToOutputDeviceColorTransform.reset(
465 qcms_transform_create(inputProfile.get(), dataFormat, gTargetColorProfile,
466 QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL));
467 #endif // USE(QCMSLIB)
468 } 403 }
469 404
470 } // namespace blink 405 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698