Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |