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

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

Issue 2436223002: Revert of Use SkColorSpaceXform to handle color conversions in decoders (Closed)
Patch Set: 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) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 10 matching lines...) Expand all
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "platform/image-decoders/webp/WEBPImageDecoder.h" 29 #include "platform/image-decoders/webp/WEBPImageDecoder.h"
30 30
31 #if USE(QCMSLIB)
32 #include "qcms.h"
33 #endif
34
31 #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) 35 #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN)
32 #error Blink assumes a little-endian target. 36 #error Blink assumes a little-endian target.
33 #endif 37 #endif
34 38
35 #if SK_B32_SHIFT // Output little-endian RGBA pixels (Android). 39 #if SK_B32_SHIFT // Output little-endian RGBA pixels (Android).
36 inline WEBP_CSP_MODE outputMode(bool hasAlpha) { 40 inline WEBP_CSP_MODE outputMode(bool hasAlpha) {
37 return hasAlpha ? MODE_rgbA : MODE_RGBA; 41 return hasAlpha ? MODE_rgbA : MODE_RGBA;
38 } 42 }
39 #else // Output little-endian BGRA pixels. 43 #else // Output little-endian BGRA pixels.
40 inline WEBP_CSP_MODE outputMode(bool hasAlpha) { 44 inline WEBP_CSP_MODE outputMode(bool hasAlpha) {
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 WebPChunkIterator chunkIterator; 339 WebPChunkIterator chunkIterator;
336 if (!WebPDemuxGetChunk(m_demux, "ICCP", 1, &chunkIterator)) { 340 if (!WebPDemuxGetChunk(m_demux, "ICCP", 1, &chunkIterator)) {
337 WebPDemuxReleaseChunkIterator(&chunkIterator); 341 WebPDemuxReleaseChunkIterator(&chunkIterator);
338 return; 342 return;
339 } 343 }
340 344
341 const char* profileData = 345 const char* profileData =
342 reinterpret_cast<const char*>(chunkIterator.chunk.bytes); 346 reinterpret_cast<const char*>(chunkIterator.chunk.bytes);
343 size_t profileSize = chunkIterator.chunk.size; 347 size_t profileSize = chunkIterator.chunk.size;
344 348
345 setColorSpaceAndComputeTransform(profileData, profileSize, 349 setColorProfileAndComputeTransform(profileData, profileSize,
346 false /* useSRGB */); 350 true /* hasAlpha */, false /* useSRGB */);
347 351
348 WebPDemuxReleaseChunkIterator(&chunkIterator); 352 WebPDemuxReleaseChunkIterator(&chunkIterator);
349 } 353 }
350 354
351 void WEBPImageDecoder::applyPostProcessing(size_t frameIndex) { 355 void WEBPImageDecoder::applyPostProcessing(size_t frameIndex) {
352 ImageFrame& buffer = m_frameBufferCache[frameIndex]; 356 ImageFrame& buffer = m_frameBufferCache[frameIndex];
353 int width; 357 int width;
354 int decodedHeight; 358 int decodedHeight;
355 if (!WebPIDecGetRGB(m_decoder, &decodedHeight, &width, 0, 0)) 359 if (!WebPIDecGetRGB(m_decoder, &decodedHeight, &width, 0, 0))
356 return; // See also https://bugs.webkit.org/show_bug.cgi?id=74062 360 return; // See also https://bugs.webkit.org/show_bug.cgi?id=74062
357 if (decodedHeight <= 0) 361 if (decodedHeight <= 0)
358 return; 362 return;
359 363
360 const IntRect& frameRect = buffer.originalFrameRect(); 364 const IntRect& frameRect = buffer.originalFrameRect();
361 ASSERT_WITH_SECURITY_IMPLICATION(width == frameRect.width()); 365 ASSERT_WITH_SECURITY_IMPLICATION(width == frameRect.width());
362 ASSERT_WITH_SECURITY_IMPLICATION(decodedHeight <= frameRect.height()); 366 ASSERT_WITH_SECURITY_IMPLICATION(decodedHeight <= frameRect.height());
363 const int left = frameRect.x(); 367 const int left = frameRect.x();
364 const int top = frameRect.y(); 368 const int top = frameRect.y();
365 369
366 #if USE(SKCOLORXFORM) 370 #if USE(QCMSLIB)
367 // TODO (msarett): 371 if (qcms_transform* transform = colorTransform()) {
368 // Here we apply the color space transformation to the dst space.
369 // It does not really make sense to transform to a gamma-encoded
370 // space and then immediately after, perform a linear premultiply
371 // and linear blending. Can we find a way to perform the
372 // premultiplication and blending in a linear space?
373 SkColorSpaceXform* xform = colorTransform();
374 if (xform) {
375 const SkColorSpaceXform::ColorFormat srcFormat =
376 SkColorSpaceXform::kBGRA_8888_ColorFormat;
377 const SkColorSpaceXform::ColorFormat dstFormat =
378 SkColorSpaceXform::kRGBA_8888_ColorFormat;
379 for (int y = m_decodedHeight; y < decodedHeight; ++y) { 372 for (int y = m_decodedHeight; y < decodedHeight; ++y) {
380 const int canvasY = top + y; 373 const int canvasY = top + y;
381 uint8_t* row = reinterpret_cast<uint8_t*>(buffer.getAddr(left, canvasY)); 374 uint8_t* row = reinterpret_cast<uint8_t*>(buffer.getAddr(left, canvasY));
382 xform->apply(dstFormat, row, srcFormat, row, width, 375 qcms_transform_data_type(transform, row, row, width, QCMS_OUTPUT_RGBX);
383 kUnpremul_SkAlphaType);
384
385 uint8_t* pixel = row; 376 uint8_t* pixel = row;
386 for (int x = 0; x < width; ++x, pixel += 4) { 377 for (int x = 0; x < width; ++x, pixel += 4) {
387 const int canvasX = left + x; 378 const int canvasX = left + x;
388 buffer.setRGBA(canvasX, canvasY, pixel[0], pixel[1], pixel[2], 379 buffer.setRGBA(canvasX, canvasY, pixel[0], pixel[1], pixel[2],
389 pixel[3]); 380 pixel[3]);
390 } 381 }
391 } 382 }
392 } 383 }
393 #endif // USE(SKCOLORXFORM) 384 #endif // USE(QCMSLIB)
394 385
395 // During the decoding of the current frame, we may have set some pixels to be 386 // During the decoding of the current frame, we may have set some pixels to be
396 // transparent (i.e. alpha < 255). If the alpha blend source was 387 // transparent (i.e. alpha < 255). If the alpha blend source was
397 // 'BlendAtopPreviousFrame', the values of these pixels should be determined 388 // 'BlendAtopPreviousFrame', the values of these pixels should be determined
398 // by blending them against the pixels of the corresponding previous frame. 389 // by blending them against the pixels of the corresponding previous frame.
399 // Compute the correct opaque values now. 390 // Compute the correct opaque values now.
400 // FIXME: This could be avoided if libwebp decoder had an API that used the 391 // FIXME: This could be avoided if libwebp decoder had an API that used the
401 // previous required frame to do the alpha-blending by itself. 392 // previous required frame to do the alpha-blending by itself.
402 if ((m_formatFlags & ANIMATION_FLAG) && frameIndex && 393 if ((m_formatFlags & ANIMATION_FLAG) && frameIndex &&
403 buffer.getAlphaBlendSource() == ImageFrame::BlendAtopPreviousFrame && 394 buffer.getAlphaBlendSource() == ImageFrame::BlendAtopPreviousFrame &&
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 // fully decoded. 524 // fully decoded.
534 buffer.setHasAlpha(true); 525 buffer.setHasAlpha(true);
535 buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); 526 buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
536 } 527 }
537 528
538 const IntRect& frameRect = buffer.originalFrameRect(); 529 const IntRect& frameRect = buffer.originalFrameRect();
539 if (!m_decoder) { 530 if (!m_decoder) {
540 WEBP_CSP_MODE mode = outputMode(m_formatFlags & ALPHA_FLAG); 531 WEBP_CSP_MODE mode = outputMode(m_formatFlags & ALPHA_FLAG);
541 if (!m_premultiplyAlpha) 532 if (!m_premultiplyAlpha)
542 mode = outputMode(false); 533 mode = outputMode(false);
543 #if USE(SKCOLORXFORM) 534 #if USE(QCMSLIB)
544 if (colorTransform()) { 535 if (colorTransform())
545 // Swizzling between RGBA and BGRA is zero cost in a color transform. 536 mode = MODE_RGBA; // Decode to RGBA for input to libqcms.
546 // So when we have a color transform, we should decode to whatever is
547 // easiest for libwebp, and then let the color transform swizzle if
548 // necessary.
549 // Lossy webp is encoded as YUV (so RGBA and BGRA are the same cost).
550 // Lossless webp is encoded as BGRA. This means decoding to BGRA is
551 // either faster or the same cost as RGBA.
552 mode = MODE_BGRA;
553 }
554 #endif 537 #endif
555 WebPInitDecBuffer(&m_decoderBuffer); 538 WebPInitDecBuffer(&m_decoderBuffer);
556 m_decoderBuffer.colorspace = mode; 539 m_decoderBuffer.colorspace = mode;
557 m_decoderBuffer.u.RGBA.stride = 540 m_decoderBuffer.u.RGBA.stride =
558 size().width() * sizeof(ImageFrame::PixelData); 541 size().width() * sizeof(ImageFrame::PixelData);
559 m_decoderBuffer.u.RGBA.size = 542 m_decoderBuffer.u.RGBA.size =
560 m_decoderBuffer.u.RGBA.stride * frameRect.height(); 543 m_decoderBuffer.u.RGBA.stride * frameRect.height();
561 m_decoderBuffer.is_external_memory = 1; 544 m_decoderBuffer.is_external_memory = 1;
562 m_decoder = WebPINewDecoder(&m_decoderBuffer); 545 m_decoder = WebPINewDecoder(&m_decoderBuffer);
563 if (!m_decoder) 546 if (!m_decoder)
(...skipping 17 matching lines...) Expand all
581 return false; 564 return false;
582 } 565 }
583 // FALLTHROUGH 566 // FALLTHROUGH
584 default: 567 default:
585 clear(); 568 clear();
586 return setFailed(); 569 return setFailed();
587 } 570 }
588 } 571 }
589 572
590 } // namespace blink 573 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698