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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 new ICOImageDecoder(alphaOption, colorOptions, maxDecodedBytes)); | 114 new ICOImageDecoder(alphaOption, colorOptions, maxDecodedBytes)); |
115 break; | 115 break; |
116 case SniffResult::BMP: | 116 case SniffResult::BMP: |
117 decoder.reset( | 117 decoder.reset( |
118 new BMPImageDecoder(alphaOption, colorOptions, maxDecodedBytes)); | 118 new BMPImageDecoder(alphaOption, colorOptions, maxDecodedBytes)); |
119 break; | 119 break; |
120 case SniffResult::Invalid: | 120 case SniffResult::Invalid: |
121 break; | 121 break; |
122 } | 122 } |
123 | 123 |
124 if (decoder) | 124 if (decoder) { |
125 decoder->setData(data.release(), dataComplete); | 125 decoder->setData(data.release(), dataComplete); |
| 126 decoder->m_targetColorSpace = globalTargetColorSpace(); |
| 127 } |
126 | 128 |
127 return decoder; | 129 return decoder; |
128 } | 130 } |
129 | 131 |
130 bool ImageDecoder::hasSufficientDataToSniffImageType(const SharedBuffer& data) { | 132 bool ImageDecoder::hasSufficientDataToSniffImageType(const SharedBuffer& data) { |
131 return data.size() >= kLongestSignatureLength; | 133 return data.size() >= kLongestSignatureLength; |
132 } | 134 } |
133 | 135 |
134 ImageDecoder::SniffResult ImageDecoder::determineImageType(const char* contents, | 136 ImageDecoder::SniffResult ImageDecoder::determineImageType(const char* contents, |
135 size_t length) { | 137 size_t length) { |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 | 416 |
415 namespace { | 417 namespace { |
416 | 418 |
417 // The output device color space is global and shared across multiple threads. | 419 // The output device color space is global and shared across multiple threads. |
418 SpinLock gTargetColorSpaceLock; | 420 SpinLock gTargetColorSpaceLock; |
419 SkColorSpace* gTargetColorSpace = nullptr; | 421 SkColorSpace* gTargetColorSpace = nullptr; |
420 | 422 |
421 } // namespace | 423 } // namespace |
422 | 424 |
423 // static | 425 // static |
424 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) { | 426 void ImageDecoder::setGlobalTargetColorProfile(const WebVector<char>& profile) { |
425 if (profile.isEmpty()) | 427 if (profile.isEmpty()) |
426 return; | 428 return; |
427 | 429 |
428 // Take a lock around initializing and accessing the global device color | 430 // Take a lock around initializing and accessing the global device color |
429 // profile. | 431 // profile. |
430 SpinLock::Guard guard(gTargetColorSpaceLock); | 432 SpinLock::Guard guard(gTargetColorSpaceLock); |
431 | 433 |
432 // Layout tests expect that only the first call will take effect. | 434 // Layout tests expect that only the first call will take effect. |
433 if (gTargetColorSpace) | 435 if (gTargetColorSpace) |
434 return; | 436 return; |
435 | 437 |
436 gTargetColorSpace = | 438 gTargetColorSpace = |
437 SkColorSpace::MakeICC(profile.data(), profile.size()).release(); | 439 SkColorSpace::MakeICC(profile.data(), profile.size()).release(); |
438 | 440 |
439 // UMA statistics. | 441 // UMA statistics. |
440 BitmapImageMetrics::countOutputGamma(gTargetColorSpace); | 442 BitmapImageMetrics::countOutputGamma(gTargetColorSpace); |
441 } | 443 } |
442 | 444 |
| 445 // static |
| 446 sk_sp<SkColorSpace> ImageDecoder::globalTargetColorSpace() { |
| 447 // Take a lock around initializing and accessing the global device color |
| 448 // profile. |
| 449 SpinLock::Guard guard(gTargetColorSpaceLock); |
| 450 |
| 451 // Initialize the output device profile to sRGB if it has not yet been |
| 452 // initialized. |
| 453 if (!gTargetColorSpace) { |
| 454 gTargetColorSpace = |
| 455 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).release(); |
| 456 } |
| 457 |
| 458 gTargetColorSpace->ref(); |
| 459 return sk_sp<SkColorSpace>(gTargetColorSpace); |
| 460 } |
| 461 |
443 sk_sp<SkColorSpace> ImageDecoder::colorSpace() const { | 462 sk_sp<SkColorSpace> ImageDecoder::colorSpace() const { |
444 // TODO(ccameron): This should always return a non-null SkColorSpace. This is | 463 // TODO(ccameron): This should always return a non-null SkColorSpace. This is |
445 // disabled for now because specifying a non-renderable color space results in | 464 // disabled for now because specifying a non-renderable color space results in |
446 // errors. | 465 // errors. |
447 // https://bugs.chromium.org/p/skia/issues/detail?id=5907 | 466 // https://bugs.chromium.org/p/skia/issues/detail?id=5907 |
448 if (!RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 467 if (!RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
449 return nullptr; | 468 return nullptr; |
450 | 469 |
451 if (m_embeddedColorSpace) | 470 if (m_embeddedColorSpace) |
452 return m_embeddedColorSpace; | 471 return m_embeddedColorSpace; |
453 return SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | 472 return SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); |
454 } | 473 } |
455 | 474 |
456 void ImageDecoder::setColorProfileAndComputeTransform(const char* iccData, | 475 void ImageDecoder::setEmbeddedColorProfile(const char* iccData, |
457 unsigned iccLength) { | 476 unsigned iccLength) { |
458 sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(iccData, iccLength); | 477 sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(iccData, iccLength); |
459 if (!colorSpace) | 478 if (!colorSpace) |
460 DLOG(ERROR) << "Failed to parse image ICC profile"; | 479 DLOG(ERROR) << "Failed to parse image ICC profile"; |
461 setColorSpaceAndComputeTransform(std::move(colorSpace)); | 480 setEmbeddedColorSpace(std::move(colorSpace)); |
462 } | 481 } |
463 | 482 |
464 void ImageDecoder::setColorSpaceAndComputeTransform( | 483 void ImageDecoder::setEmbeddedColorSpace(sk_sp<SkColorSpace> colorSpace) { |
465 sk_sp<SkColorSpace> colorSpace) { | |
466 DCHECK(!m_ignoreColorSpace); | 484 DCHECK(!m_ignoreColorSpace); |
467 DCHECK(!m_hasHistogrammedColorSpace); | 485 DCHECK(!m_hasHistogrammedColorSpace); |
468 | 486 |
469 m_embeddedColorSpace = colorSpace; | 487 m_embeddedColorSpace = colorSpace; |
| 488 m_sourceToTargetColorTransformNeedsUpdate = true; |
| 489 } |
470 | 490 |
471 m_sourceToOutputDeviceColorTransform = nullptr; | 491 SkColorSpaceXform* ImageDecoder::colorTransform() { |
| 492 if (!m_sourceToTargetColorTransformNeedsUpdate) |
| 493 return m_sourceToTargetColorTransform.get(); |
| 494 m_sourceToTargetColorTransformNeedsUpdate = false; |
| 495 m_sourceToTargetColorTransform = nullptr; |
472 | 496 |
473 // With color correct rendering, we do not transform to the output color space | 497 // With color correct rendering, we do not transform to the output color space |
474 // at decode time. Instead, we tag the raw image pixels and pass the tagged | 498 // at decode time. Instead, we tag the raw image pixels and pass the tagged |
475 // SkImage to Skia. | 499 // SkImage to Skia. |
476 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 500 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
477 return; | 501 return nullptr; |
478 | 502 |
479 if (!m_embeddedColorSpace) | 503 if (!m_embeddedColorSpace) |
480 return; | 504 return nullptr; |
481 | 505 |
482 // Take a lock around initializing and accessing the global device color | 506 if (SkColorSpace::Equals(m_embeddedColorSpace.get(), |
483 // profile. | 507 m_targetColorSpace.get())) { |
484 SpinLock::Guard guard(gTargetColorSpaceLock); | 508 return nullptr; |
485 | |
486 // Initialize the output device profile to sRGB if it has not yet been | |
487 // initialized. | |
488 if (!gTargetColorSpace) { | |
489 gTargetColorSpace = | |
490 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).release(); | |
491 } | 509 } |
492 | 510 |
493 if (SkColorSpace::Equals(m_embeddedColorSpace.get(), gTargetColorSpace)) { | 511 m_sourceToTargetColorTransform = SkColorSpaceXform::New( |
494 return; | 512 m_embeddedColorSpace.get(), m_targetColorSpace.get()); |
495 } | 513 return m_sourceToTargetColorTransform.get(); |
496 | |
497 m_sourceToOutputDeviceColorTransform = | |
498 SkColorSpaceXform::New(m_embeddedColorSpace.get(), gTargetColorSpace); | |
499 } | 514 } |
500 | 515 |
501 } // namespace blink | 516 } // namespace blink |
OLD | NEW |