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

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: Rebase 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) 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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 namespace {
345 334
346 #if USE(QCMSLIB) 335 #if USE(SKCOLORXFORM)
347 336
348 const unsigned kIccColorProfileHeaderLength = 128; 337 // The output device color space is global and shared across multiple threads.
338 SpinLock gTargetColorSpaceLock;
339 SkColorSpace* gTargetColorSpace = nullptr;
349 340
350 bool rgbColorProfile(const char* profileData, unsigned profileLength) { 341 #endif // USE(SKCOLORXFORM)
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 342
369 } // namespace 343 } // namespace
370 344
371 // static 345 // static
372 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) { 346 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) {
373 #if USE(QCMSLIB) 347 #if USE(SKCOLORXFORM)
374 if (profile.isEmpty()) 348 if (profile.isEmpty())
375 return; 349 return;
376 350
377 // Take a lock around initializing and accessing the global device color 351 // Take a lock around initializing and accessing the global device color
378 // profile. 352 // profile.
379 SpinLock::Guard guard(gTargetColorProfileLock); 353 SpinLock::Guard guard(gTargetColorSpaceLock);
380 354
381 // Layout tests expect that only the first call will take effect. 355 // Layout tests expect that only the first call will take effect.
382 if (gTargetColorProfile) 356 if (gTargetColorSpace)
383 return; 357 return;
384 358
385 { 359 gTargetColorSpace =
386 sk_sp<SkColorSpace> colorSpace = 360 SkColorSpace::NewICC(profile.data(), profile.size()).release();
387 SkColorSpace::NewICC(profile.data(), profile.size());
388 BitmapImageMetrics::countGamma(colorSpace.get());
389 }
390 361
391 // FIXME: Add optional ICCv4 support and support for multiple monitors. 362 // UMA statistics.
392 gTargetColorProfile = 363 BitmapImageMetrics::countGamma(gTargetColorSpace);
393 qcms_profile_from_memory(profile.data(), profile.size()); 364 #endif // USE(SKCOLORXFORM)
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 } 365 }
406 366
407 void ImageDecoder::setColorProfileAndComputeTransform(const char* iccData, 367 void ImageDecoder::setColorSpaceAndComputeTransform(const char* iccData,
408 unsigned iccLength, 368 unsigned iccLength,
409 bool hasAlpha, 369 bool useSRGB) {
410 bool useSRGB) {
411 // Sub-classes should not call this if they were instructed to ignore embedded 370 // Sub-classes should not call this if they were instructed to ignore embedded
412 // color profiles. 371 // color profiles.
413 DCHECK(!m_ignoreGammaAndColorProfile); 372 DCHECK(!m_ignoreGammaAndColorProfile);
414 373
415 m_colorProfile.assign(iccData, iccLength); 374 m_colorProfile.assign(iccData, iccLength);
416 m_hasColorProfile = true; 375 m_hasColorProfile = true;
417 376
418 // With color correct rendering, we use Skia instead of QCMS to color correct 377 // With color correct rendering, we do not transform to the output color space
419 // images. 378 // at decode time. Instead, we tag the raw image pixels and pass the tagged
379 // SkImage to Skia.
420 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) 380 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled())
421 return; 381 return;
422 382
423 #if USE(QCMSLIB) 383 #if USE(SKCOLORXFORM)
424 m_sourceToOutputDeviceColorTransform.reset(); 384 m_sourceToOutputDeviceColorTransform = nullptr;
425 385
426 // Create the input profile 386 // Create the input profile.
427 QCMSProfileUniquePtr inputProfile; 387 sk_sp<SkColorSpace> srcSpace = nullptr;
428 if (useSRGB) { 388 if (useSRGB) {
429 inputProfile.reset(qcms_profile_sRGB()); 389 srcSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
430 } else { 390 } else {
431 // Only accept RGB color profiles from input class devices. 391 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 } 392 }
440 if (!inputProfile) 393
394 if (!srcSpace)
441 return; 395 return;
442 396
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 397 // Take a lock around initializing and accessing the global device color
447 // profile. 398 // profile.
448 SpinLock::Guard guard(gTargetColorProfileLock); 399 SpinLock::Guard guard(gTargetColorSpaceLock);
449 400
450 // Initialize the output device profile to sRGB if it has not yet been 401 // Initialize the output device profile to sRGB if it has not yet been
451 // initialized. 402 // initialized.
452 if (!gTargetColorProfile) { 403 if (!gTargetColorSpace) {
453 gTargetColorProfile = qcms_profile_sRGB(); 404 gTargetColorSpace =
454 qcms_profile_precache_output_transform(gTargetColorProfile); 405 SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named).release();
455 } 406 }
456 407
457 if (qcms_profile_match(inputProfile.get(), gTargetColorProfile)) 408 if (SkColorSpace::Equals(srcSpace.get(), gTargetColorSpace)) {
458 return; 409 return;
410 }
459 411
460 qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; 412 m_sourceToOutputDeviceColorTransform =
461 413 SkColorSpaceXform::New(srcSpace.get(), gTargetColorSpace);
462 // FIXME: Don't force perceptual intent if the image profile contains an 414 #endif // USE(SKCOLORXFORM)
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 } 415 }
469 416
470 } // namespace blink 417 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698