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 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 | 369 |
368 namespace { | 370 namespace { |
369 | 371 |
370 // The output device color space is global and shared across multiple threads. | 372 // The output device color space is global and shared across multiple threads. |
371 SpinLock gTargetColorSpaceLock; | 373 SpinLock gTargetColorSpaceLock; |
372 SkColorSpace* gTargetColorSpace = nullptr; | 374 SkColorSpace* gTargetColorSpace = nullptr; |
373 | 375 |
374 } // namespace | 376 } // namespace |
375 | 377 |
376 // static | 378 // static |
377 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) { | 379 void ImageDecoder::setGlobalTargetColorProfile(const WebVector<char>& profile) { |
378 if (profile.isEmpty()) | 380 if (profile.isEmpty()) |
379 return; | 381 return; |
380 | 382 |
381 // Take a lock around initializing and accessing the global device color | 383 // Take a lock around initializing and accessing the global device color |
382 // profile. | 384 // profile. |
383 SpinLock::Guard guard(gTargetColorSpaceLock); | 385 SpinLock::Guard guard(gTargetColorSpaceLock); |
384 | 386 |
385 // Layout tests expect that only the first call will take effect. | 387 // Layout tests expect that only the first call will take effect. |
386 if (gTargetColorSpace) | 388 if (gTargetColorSpace) |
387 return; | 389 return; |
388 | 390 |
389 gTargetColorSpace = | 391 gTargetColorSpace = |
390 SkColorSpace::MakeICC(profile.data(), profile.size()).release(); | 392 SkColorSpace::MakeICC(profile.data(), profile.size()).release(); |
391 | 393 |
392 // UMA statistics. | 394 // UMA statistics. |
393 BitmapImageMetrics::countOutputGamma(gTargetColorSpace); | 395 BitmapImageMetrics::countOutputGamma(gTargetColorSpace); |
394 } | 396 } |
395 | 397 |
| 398 // static |
| 399 sk_sp<SkColorSpace> ImageDecoder::globalTargetColorSpace() { |
| 400 // Take a lock around initializing and accessing the global device color |
| 401 // profile. |
| 402 SpinLock::Guard guard(gTargetColorSpaceLock); |
| 403 |
| 404 // Initialize the output device profile to sRGB if it has not yet been |
| 405 // initialized. |
| 406 if (!gTargetColorSpace) { |
| 407 gTargetColorSpace = |
| 408 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).release(); |
| 409 } |
| 410 |
| 411 gTargetColorSpace->ref(); |
| 412 return sk_sp<SkColorSpace>(gTargetColorSpace); |
| 413 } |
| 414 |
396 sk_sp<SkColorSpace> ImageDecoder::colorSpace() const { | 415 sk_sp<SkColorSpace> ImageDecoder::colorSpace() const { |
397 // TODO(ccameron): This should always return a non-null SkColorSpace. This is | 416 // TODO(ccameron): This should always return a non-null SkColorSpace. This is |
398 // disabled for now because specifying a non-renderable color space results in | 417 // disabled for now because specifying a non-renderable color space results in |
399 // errors. | 418 // errors. |
400 // https://bugs.chromium.org/p/skia/issues/detail?id=5907 | 419 // https://bugs.chromium.org/p/skia/issues/detail?id=5907 |
401 if (!RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 420 if (!RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
402 return nullptr; | 421 return nullptr; |
403 | 422 |
404 if (m_embeddedColorSpace) | 423 if (m_embeddedColorSpace) |
405 return m_embeddedColorSpace; | 424 return m_embeddedColorSpace; |
406 return SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | 425 return SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); |
407 } | 426 } |
408 | 427 |
409 void ImageDecoder::setColorProfileAndComputeTransform(const char* iccData, | 428 void ImageDecoder::setEmbeddedColorProfile(const char* iccData, |
410 unsigned iccLength) { | 429 unsigned iccLength) { |
411 sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(iccData, iccLength); | 430 sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(iccData, iccLength); |
412 if (!colorSpace) | 431 if (!colorSpace) |
413 DLOG(ERROR) << "Failed to parse image ICC profile"; | 432 DLOG(ERROR) << "Failed to parse image ICC profile"; |
414 setColorSpaceAndComputeTransform(std::move(colorSpace)); | 433 setEmbeddedColorSpace(std::move(colorSpace)); |
415 } | 434 } |
416 | 435 |
417 void ImageDecoder::setColorSpaceAndComputeTransform( | 436 void ImageDecoder::setEmbeddedColorSpace(sk_sp<SkColorSpace> colorSpace) { |
418 sk_sp<SkColorSpace> colorSpace) { | |
419 DCHECK(!m_ignoreColorSpace); | 437 DCHECK(!m_ignoreColorSpace); |
420 DCHECK(!m_hasHistogrammedColorSpace); | 438 DCHECK(!m_hasHistogrammedColorSpace); |
421 | 439 |
422 m_embeddedColorSpace = colorSpace; | 440 m_embeddedColorSpace = colorSpace; |
| 441 m_sourceToTargetColorTransformNeedsUpdate = true; |
| 442 } |
423 | 443 |
424 m_sourceToOutputDeviceColorTransform = nullptr; | 444 SkColorSpaceXform* ImageDecoder::colorTransform() { |
| 445 if (!m_sourceToTargetColorTransformNeedsUpdate) |
| 446 return m_sourceToTargetColorTransform.get(); |
| 447 m_sourceToTargetColorTransformNeedsUpdate = false; |
| 448 m_sourceToTargetColorTransform = nullptr; |
425 | 449 |
426 // With color correct rendering, we do not transform to the output color space | 450 // With color correct rendering, we do not transform to the output color space |
427 // at decode time. Instead, we tag the raw image pixels and pass the tagged | 451 // at decode time. Instead, we tag the raw image pixels and pass the tagged |
428 // SkImage to Skia. | 452 // SkImage to Skia. |
429 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 453 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
430 return; | 454 return nullptr; |
431 | 455 |
432 if (!m_embeddedColorSpace) | 456 if (!m_embeddedColorSpace) |
433 return; | 457 return nullptr; |
434 | 458 |
435 // Take a lock around initializing and accessing the global device color | 459 if (SkColorSpace::Equals(m_embeddedColorSpace.get(), |
436 // profile. | 460 m_targetColorSpace.get())) { |
437 SpinLock::Guard guard(gTargetColorSpaceLock); | 461 return nullptr; |
438 | |
439 // Initialize the output device profile to sRGB if it has not yet been | |
440 // initialized. | |
441 if (!gTargetColorSpace) { | |
442 gTargetColorSpace = | |
443 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).release(); | |
444 } | 462 } |
445 | 463 |
446 if (SkColorSpace::Equals(m_embeddedColorSpace.get(), gTargetColorSpace)) { | 464 m_sourceToTargetColorTransform = SkColorSpaceXform::New( |
447 return; | 465 m_embeddedColorSpace.get(), m_targetColorSpace.get()); |
448 } | 466 return m_sourceToTargetColorTransform.get(); |
449 | |
450 m_sourceToOutputDeviceColorTransform = | |
451 SkColorSpaceXform::New(m_embeddedColorSpace.get(), gTargetColorSpace); | |
452 } | 467 } |
453 | 468 |
454 } // namespace blink | 469 } // namespace blink |
OLD | NEW |