Index: third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp |
diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp |
index b332fd9d54f678d45843a7c906dc1d3ff6805cb7..d41cea4102bc26ebcacac2e82afd9ca11a56cef3 100644 |
--- a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp |
+++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp |
@@ -132,9 +132,7 @@ bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, |
// Prevents concurrent decode or scale operations on the same image data. |
MutexLocker lock(m_decodeMutex); |
- // This implementation does not support scaling so check the requested size. |
- SkISize scaledSize = SkISize::Make(info.width(), info.height()); |
- ASSERT(m_fullSize == scaledSize); |
+ SkISize outputSize = SkISize::Make(info.width(), info.height()); |
if (m_decodeFailedAndEmpty) |
return false; |
@@ -143,16 +141,17 @@ bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, |
m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, rowBytes)); |
- SkBitmap bitmap = tryToResumeDecode(scaledSize, index); |
- if (bitmap.isNull()) |
- return false; |
+ SkBitmap bitmap = tryToResumeDecode(outputSize, index, info.colorType(), rowBytes); |
// Don't keep the allocator because it contains a pointer to memory |
// that we do not own. |
m_externalAllocator.clear(); |
- ASSERT(bitmap.width() == scaledSize.width()); |
- ASSERT(bitmap.height() == scaledSize.height()); |
+ if (bitmap.isNull()) |
+ return false; |
+ |
+ ASSERT(bitmap.width() == outputSize.width()); |
+ ASSERT(bitmap.height() == outputSize.height()); |
bool result = true; |
SkAutoLockPixels bitmapLock(bitmap); |
@@ -205,7 +204,7 @@ bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes[3], void* planes[3] |
return yuvDecoded; |
} |
-SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_t index) |
+SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& outputSize, size_t index, SkColorType outputType, size_t rowBytes) |
{ |
TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index)); |
@@ -213,8 +212,8 @@ SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_ |
const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder); |
ASSERT(!resumeDecoding || decoder); |
- SkBitmap fullSizeImage; |
- bool complete = decode(index, &decoder, &fullSizeImage); |
+ SkBitmap image; |
+ bool complete = decode(index, &decoder, &image, outputType, outputSize, rowBytes); |
if (!decoder) |
return SkBitmap(); |
@@ -229,7 +228,7 @@ SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_ |
if (!resumeDecoding) |
decoderContainer = adoptPtr(decoder); |
- if (fullSizeImage.isNull()) { |
+ if (image.isNull()) { |
// If decode has failed and resulted an empty image we can save work |
// in the future by returning early. |
m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed(); |
@@ -265,7 +264,7 @@ SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_ |
} else if (!removeDecoder) { |
ImageDecodingStore::instance().insertDecoder(this, decoderContainer.release()); |
} |
- return fullSizeImage; |
+ return image; |
} |
void ImageFrameGenerator::setHasAlpha(size_t index, bool hasAlpha) |
@@ -280,19 +279,24 @@ void ImageFrameGenerator::setHasAlpha(size_t index, bool hasAlpha) |
m_hasAlpha[index] = hasAlpha; |
} |
-bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap) |
+bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap, SkColorType outputType, const SkISize& outputSize, size_t rowBytes) |
{ |
TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.width(), "height", m_fullSize.height()); |
ASSERT(decoder); |
SharedBuffer* data = 0; |
bool allDataReceived = false; |
- bool newDecoder = false; |
m_data.data(&data, &allDataReceived); |
+ if (outputSize.width() != m_fullSize.width() || outputSize.height() != m_fullSize.height()) { |
+ ASSERT(allDataReceived); |
+ ASSERT(!m_isMultiFrame); |
+ if (m_isMultiFrame || !allDataReceived) |
+ return false; |
+ } |
+ |
// Try to create an ImageDecoder if we are not given one. |
if (!*decoder) { |
- newDecoder = true; |
if (m_imageDecoderFactory) |
*decoder = m_imageDecoderFactory->create().leakPtr(); |
@@ -303,15 +307,25 @@ bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* |
return false; |
} |
- if (!m_isMultiFrame && newDecoder && allDataReceived) { |
+ if (!m_isMultiFrame && allDataReceived) { |
// If we're using an external memory allocator that means we're decoding |
// directly into the output memory and we can save one memcpy. |
ASSERT(m_externalAllocator.get()); |
(*decoder)->setMemoryAllocator(m_externalAllocator.get()); |
+ if (outputType != kN32_SkColorType || outputSize.width() != m_fullSize.width() || outputSize.height() != m_fullSize.height()) { |
+ size_t maxDecodeBytes = outputSize.height() * rowBytes; |
+ if (!(*decoder)->activateDecodeAndScale(static_cast<ImageFrame::ColorType>(outputType), maxDecodeBytes)) { |
+ ASSERT(false); |
+ (*decoder)->setMemoryAllocator(0); |
+ return false; |
+ } |
+ } |
} |
(*decoder)->setData(data, allDataReceived); |
- |
ImageFrame* frame = (*decoder)->frameBufferAtIndex(index); |
+ // restore back to default |
+ (*decoder)->disableDecodeAndScale(); |
+ |
// For multi-frame image decoders, we need to know how many frames are |
// in that image in order to release the decoder when all frames are |
// decoded. frameCount() is reliable only if all data is received and set in |
@@ -330,13 +344,13 @@ bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* |
// Or we have received all data. The image might not be fully decoded in |
// the latter case. |
const bool isDecodeComplete = frame->status() == ImageFrame::FrameComplete || allDataReceived; |
- SkBitmap fullSizeBitmap = frame->getSkBitmap(); |
- if (!fullSizeBitmap.isNull()) |
+ SkBitmap decodedBitmap = frame->getSkBitmap(); |
+ if (!decodedBitmap.isNull()) |
{ |
- ASSERT(fullSizeBitmap.width() == m_fullSize.width() && fullSizeBitmap.height() == m_fullSize.height()); |
- setHasAlpha(index, !fullSizeBitmap.isOpaque()); |
+ ASSERT(decodedBitmap.width() == outputSize.width() && decodedBitmap.height() == outputSize.height()); |
+ setHasAlpha(index, !decodedBitmap.isOpaque()); |
} |
- *bitmap = fullSizeBitmap; |
+ *bitmap = decodedBitmap; |
return isDecodeComplete; |
} |
@@ -379,4 +393,30 @@ bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes[3]) |
return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder::SizeForMemoryAllocation); |
} |
+void ImageFrameGenerator::getAvailableDecodeAndScale(SkColorType* outType, float* scale, float* lowerScale) |
+{ |
+ // as the same buffer could be used to store consecutive frames, avoid the complexity |
+ // since some of consecutive frames could have alpha |
+ if (m_isMultiFrame) { |
+ // pass the same content as in default ImageDecoder |
+ ImageDecoder::defaultDecodeAndScale(reinterpret_cast<ImageFrame::ColorType*>(outType), scale, lowerScale); |
+ } |
+ |
+ // FIXME check how much this cost (decoder creation) and, also for getYUVComponentSizes, |
+ // cache it in ImageDecodingStore for the real decode |
+ SharedBuffer* data = 0; |
+ bool allDataReceived = false; |
+ m_data.data(&data, &allDataReceived); |
+ |
+ // partially received data needs to have alpha and skip downsampling |
+ if (allDataReceived) { |
+ OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, ImageDecoder::AlphaPremultiplied, ImageDecoder::GammaAndColorProfileApplied); |
+ if (decoder) { |
+ decoder->getAvailableDecodeAndScale(reinterpret_cast<ImageFrame::ColorType*>(outType), scale, lowerScale); |
+ return; |
+ } |
+ } |
+ ImageDecoder::defaultDecodeAndScale(reinterpret_cast<ImageFrame::ColorType*>(outType), scale, lowerScale); |
+} |
+ |
} // namespace blink |