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

Side by Side Diff: third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp

Issue 1460523002: GIF decoding to Index8, unit tests and misusing unit test as benchmark (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comment #25 processed. Created 4 years, 11 months 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) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 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 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 return true; 98 return true;
99 } 99 }
100 100
101 ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<Sha redBuffer> data, bool allDataReceived, bool isMultiFrame) 101 ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<Sha redBuffer> data, bool allDataReceived, bool isMultiFrame)
102 : m_fullSize(fullSize) 102 : m_fullSize(fullSize)
103 , m_data(adoptRef(new ThreadSafeDataTransport())) 103 , m_data(adoptRef(new ThreadSafeDataTransport()))
104 , m_isMultiFrame(isMultiFrame) 104 , m_isMultiFrame(isMultiFrame)
105 , m_decodeFailed(false) 105 , m_decodeFailed(false)
106 , m_frameCount(0) 106 , m_frameCount(0)
107 , m_encodedData(nullptr) 107 , m_encodedData(nullptr)
108 , m_decoderCanDecodeToIndex8(false)
108 { 109 {
109 setData(data.get(), allDataReceived); 110 setData(data.get(), allDataReceived);
110 } 111 }
111 112
112 ImageFrameGenerator::~ImageFrameGenerator() 113 ImageFrameGenerator::~ImageFrameGenerator()
113 { 114 {
114 if (m_encodedData) 115 if (m_encodedData)
115 m_encodedData->unref(); 116 m_encodedData->unref();
116 ImageDecodingStore::instance().removeCacheIndexedByGenerator(this); 117 ImageDecodingStore::instance().removeCacheIndexedByGenerator(this);
117 } 118 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 // While m_encodedData is referenced, prevent disposing m_data and its c ontent. 166 // While m_encodedData is referenced, prevent disposing m_data and its c ontent.
166 // it is dereferenced in sharedSkDataReleaseCallback, called when m_enco dedData gets dereferenced. 167 // it is dereferenced in sharedSkDataReleaseCallback, called when m_enco dedData gets dereferenced.
167 m_data->ref(); 168 m_data->ref();
168 } 169 }
169 // Increase the reference, caller must decrease it. One reference is always kept by ImageFrameGenerator and released 170 // Increase the reference, caller must decrease it. One reference is always kept by ImageFrameGenerator and released
170 // in destructor. 171 // in destructor.
171 m_encodedData->ref(); 172 m_encodedData->ref();
172 return m_encodedData; 173 return m_encodedData;
173 } 174 }
174 175
175 bool ImageFrameGenerator::decodeAndScale(size_t index, const SkImageInfo& info, void* pixels, size_t rowBytes) 176 static bool copyIndex8PixelsTo(const SkBitmap& bitmap, const SkImageInfo& info, void* pixels, size_t rowBytes)
scroggo_chromium 2016/04/29 19:48:14 Various thoughts: - I think it would be helpful t
177 {
178 // This method is called for GIF animations, only for frames that, in first animation loop, get
179 // decoded to N32, but then are decoded to Index8 in later animation loop. I t is needed to return
180 // N32 pixels but internally GIF decoder produces and caches Index8 bitmap.
181 if (bitmap.colorType() != kIndex_8_SkColorType)
scroggo_chromium 2016/04/29 19:48:14 I think this should be an assert statement, rather
182 return false;
183 // GIF decoder always produce colortable with 256 entries.
184 ASSERT(bitmap.getColorTable() && bitmap.getColorTable()->count() == 256);
185
186 const SkPMColor* colors = bitmap.getColorTable()->readColors();
187 uint8_t* destination8 = (uint8_t*)pixels;
188 for (int j = 0; j < bitmap.height(); ++j) {
189 uint32_t* destination32 = (uint32_t*)destination8;
190 const uint8_t* source = bitmap.getAddr8(0, j);
191 const uint8_t* sourceEnd = source + bitmap.width();
192 while (source != sourceEnd)
193 *destination32++ = colors[*source++];
194 destination8 += rowBytes;
195 }
196 return true;
197 }
198
199 bool ImageFrameGenerator::decodeAndScale(size_t index, const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], int* ctableCount)
176 { 200 {
177 // Prevent concurrent decode or scale operations on the same image data. 201 // Prevent concurrent decode or scale operations on the same image data.
178 MutexLocker lock(m_decodeMutex); 202 MutexLocker lock(m_decodeMutex);
179 203
180 if (m_decodeFailed) 204 if (m_decodeFailed)
181 return false; 205 return false;
182 206
183 TRACE_EVENT1("blink", "ImageFrameGenerator::decodeAndScale", "frame index", static_cast<int>(index)); 207 TRACE_EVENT1("blink", "ImageFrameGenerator::decodeAndScale", "frame index", static_cast<int>(index));
184 208
185 m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, row Bytes)); 209 m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, row Bytes));
186 210
187 // This implementation does not support scaling so check the requested size. 211 // This implementation does not support scaling so check the requested size.
188 SkISize scaledSize = SkISize::Make(info.width(), info.height()); 212 SkISize scaledSize = SkISize::Make(info.width(), info.height());
189 ASSERT(m_fullSize == scaledSize); 213 ASSERT(m_fullSize == scaledSize);
190 214
191 SkBitmap bitmap = tryToResumeDecode(index, scaledSize); 215 SkBitmap bitmap = tryToResumeDecode(index, scaledSize);
192 if (bitmap.isNull()) 216 if (bitmap.isNull())
193 return false; 217 return false;
194 218
195 // Don't keep the allocator because it contains a pointer to memory 219 // Don't keep the allocator because it contains a pointer to memory
196 // that we do not own. 220 // that we do not own.
197 m_externalAllocator.clear(); 221 m_externalAllocator.clear();
198 222
199 // Check to see if the decoder has written directly to the pixel memory 223 // Check to see if the decoder has written directly to the pixel memory
200 // provided. If not, make a copy. 224 // provided. If not, make a copy.
201 ASSERT(bitmap.width() == scaledSize.width()); 225 ASSERT(bitmap.width() == scaledSize.width());
202 ASSERT(bitmap.height() == scaledSize.height()); 226 ASSERT(bitmap.height() == scaledSize.height());
227
228 // If decoder cannot produce requested color type, return false.
229 if (bitmap.colorType() != info.colorType() && bitmap.colorType() != kIndex_8 _SkColorType)
230 return false;
231
232 bool result = true;
scroggo_chromium 2016/04/29 19:48:14 I don't think this variable is necessary. When you
203 SkAutoLockPixels bitmapLock(bitmap); 233 SkAutoLockPixels bitmapLock(bitmap);
204 if (bitmap.getPixels() != pixels) 234 if (bitmap.getPixels() != pixels) {
205 return bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes); 235 if (bitmap.colorType() == info.colorType()) {
206 return true; 236 result = bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBy tes);
237 } else {
238 ASSERT(bitmap.colorType() == kIndex_8_SkColorType && info.colorType( ) == kN32_SkColorType);
239 result = copyIndex8PixelsTo(bitmap, info, pixels, rowBytes);
240 }
241 }
242 if (info.colorType() == kIndex_8_SkColorType && ctable && bitmap.getColorTab le()) {
243 memcpy(ctable, bitmap.getColorTable()->readColors(), bitmap.getColorTabl e()->count() * sizeof(SkPMColor));
244 }
245 if (ctableCount) {
246 // Based on SkImageGenerator API spec, ctableCount needs to be set to 0 for other types.
247 *ctableCount = (info.colorType() == kIndex_8_SkColorType && bitmap.getCo lorTable())
248 ? bitmap.getColorTable()->count()
249 : 0;
250 }
251 return result;
207 } 252 }
208 253
209 bool ImageFrameGenerator::decodeToYUV(size_t index, SkISize componentSizes[3], v oid* planes[3], size_t rowBytes[3]) 254 bool ImageFrameGenerator::decodeToYUV(size_t index, SkISize componentSizes[3], v oid* planes[3], size_t rowBytes[3])
210 { 255 {
211 // Prevent concurrent decode or scale operations on the same image data. 256 // Prevent concurrent decode or scale operations on the same image data.
212 MutexLocker lock(m_decodeMutex); 257 MutexLocker lock(m_decodeMutex);
213 258
214 if (m_decodeFailed) 259 if (m_decodeFailed)
215 return false; 260 return false;
216 261
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 457
413 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding. 458 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding.
414 decoder->setData(data, allDataReceived); 459 decoder->setData(data, allDataReceived);
415 OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes); 460 OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes);
416 decoder->setImagePlanes(dummyImagePlanes.release()); 461 decoder->setImagePlanes(dummyImagePlanes.release());
417 462
418 ASSERT(componentSizes); 463 ASSERT(componentSizes);
419 return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder:: SizeForMemoryAllocation); 464 return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder:: SizeForMemoryAllocation);
420 } 465 }
421 466
467 bool ImageFrameGenerator::canDecodeTo(size_t index, SkColorType outputType)
468 {
469 if (!m_decoderCanDecodeToIndex8)
470 return (outputType == kN32_SkColorType);
471
472 // Prevents concurrent decode or scale operations on the same image data.
473 MutexLocker lock(m_decodeMutex);
474 ImageDecoder* decoder = 0;
475 const bool decoderExist = ImageDecodingStore::instance().lockDecoder(this, m _fullSize, &decoder);
476 ASSERT(!decoderExist || decoder);
477 SharedBuffer* data = 0;
478 bool allDataReceived = false;
479 m_data->data(&data, &allDataReceived);
480 if (!decoderExist) {
481 if (m_imageDecoderFactory)
482 decoder = m_imageDecoderFactory->create().leakPtr();
483 if (!decoder)
484 decoder = ImageDecoder::create(*data, ImageDecoder::AlphaPremultipli ed, ImageDecoder::GammaAndColorProfileApplied).leakPtr();
485 if (!decoder)
486 return (outputType == kIndex_8_SkColorType);
487 }
488 decoder->setData(data, allDataReceived);
489 bool canDecodeToIndex8 = decoder->canDecodeTo(index, static_cast<ImageFrame: :ColorType>(outputType));
490 decoder->setData(0, false); // Unref SharedBuffer from ImageDecoder.
491 if (decoderExist) {
492 ImageDecodingStore::instance().unlockDecoder(this, decoder);
493 } else {
494 ImageDecodingStore::instance().insertDecoder(this, PassOwnPtr<blink::Ima geDecoder>(adoptPtr(decoder)));
495 }
496 return (canDecodeToIndex8 && (outputType == kIndex_8_SkColorType));
497 }
498
499
422 } // namespace blink 500 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698