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

Side by Side Diff: Source/core/platform/graphics/chromium/DeferredImageDecoder.cpp

Issue 19838002: Reland change to enable deferred image decoding for animated GIFs (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: merved Created 7 years, 5 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 | Annotate | Revision Log
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 28 matching lines...) Expand all
39 const char labelLazyDecoded[] = "lazy"; 39 const char labelLazyDecoded[] = "lazy";
40 40
41 } // namespace 41 } // namespace
42 42
43 bool DeferredImageDecoder::s_enabled = false; 43 bool DeferredImageDecoder::s_enabled = false;
44 44
45 DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecode r) 45 DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecode r)
46 : m_allDataReceived(false) 46 : m_allDataReceived(false)
47 , m_actualDecoder(actualDecoder) 47 , m_actualDecoder(actualDecoder)
48 , m_orientation(DefaultImageOrientation) 48 , m_orientation(DefaultImageOrientation)
49 , m_repetitionCount(cAnimationNone)
49 { 50 {
50 } 51 }
51 52
52 DeferredImageDecoder::~DeferredImageDecoder() 53 DeferredImageDecoder::~DeferredImageDecoder()
53 { 54 {
54 } 55 }
55 56
56 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer & data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileO ption gammaAndColorOption) 57 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer & data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileO ption gammaAndColorOption)
57 { 58 {
58 OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, gammaAndColorOption); 59 OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, gammaAndColorOption);
(...skipping 18 matching lines...) Expand all
77 78
78 int rowBytes = 0; 79 int rowBytes = 0;
79 rowBytes = SkBitmap::ComputeRowBytes(SkBitmap::kARGB_8888_Config, scaledSize .width()); 80 rowBytes = SkBitmap::ComputeRowBytes(SkBitmap::kARGB_8888_Config, scaledSize .width());
80 81
81 SkBitmap resizedBitmap; 82 SkBitmap resizedBitmap;
82 resizedBitmap.setConfig(SkBitmap::kARGB_8888_Config, scaledSubset.width(), s caledSubset.height(), rowBytes); 83 resizedBitmap.setConfig(SkBitmap::kARGB_8888_Config, scaledSubset.width(), s caledSubset.height(), rowBytes);
83 84
84 // FIXME: This code has the potential problem that multiple 85 // FIXME: This code has the potential problem that multiple
85 // LazyDecodingPixelRefs are created even though they share the same 86 // LazyDecodingPixelRefs are created even though they share the same
86 // scaled size and ImageFrameGenerator. 87 // scaled size and ImageFrameGenerator.
87 resizedBitmap.setPixelRef(new LazyDecodingPixelRef(pixelRef->frameGenerator( ), scaledSize, scaledSubset))->unref(); 88 resizedBitmap.setPixelRef(new LazyDecodingPixelRef(pixelRef->frameGenerator( ), scaledSize, pixelRef->frameIndex(), scaledSubset))->unref();
88 89
89 // See comments in createLazyDecodingBitmap(). 90 // See comments in createLazyDecodingBitmap().
90 resizedBitmap.setImmutable(); 91 resizedBitmap.setImmutable();
91 return resizedBitmap; 92 return resizedBitmap;
92 } 93 }
93 94
94 void DeferredImageDecoder::setEnabled(bool enabled) 95 void DeferredImageDecoder::setEnabled(bool enabled)
95 { 96 {
96 s_enabled = enabled; 97 s_enabled = enabled;
97 } 98 }
98 99
99 String DeferredImageDecoder::filenameExtension() const 100 String DeferredImageDecoder::filenameExtension() const
100 { 101 {
101 return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameEx tension; 102 return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameEx tension;
102 } 103 }
103 104
104 ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index) 105 ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index)
105 { 106 {
106 // Only defer image decoding if this is a single frame image. The reason is 107 prepareLazyDecodedFrames();
107 // because a multiframe is usually animated GIF. Animation is handled by 108 if (index < m_lazyDecodedFrames.size()) {
108 // BitmapImage which uses some metadata functions that do synchronous image 109 // ImageFrameGenerator has the latest known alpha state. There will
109 // decoding. 110 // be a performance boost if this frame is opaque.
110 if (s_enabled 111 m_lazyDecodedFrames[index]->setHasAlpha(m_frameGenerator->hasAlpha(index ));
111 && m_actualDecoder 112 return m_lazyDecodedFrames[index].get();
112 && m_actualDecoder->repetitionCount() == cAnimationNone
113 && m_actualDecoder->isSizeAvailable()
114 && m_actualDecoder->frameCount() == 1) {
115
116 m_size = m_actualDecoder->size();
117 m_filenameExtension = m_actualDecoder->filenameExtension();
118 m_orientation = m_actualDecoder->orientation();
119
120 SkBitmap lazyDecodedSkBitmap = createLazyDecodingBitmap();
121 m_lazyDecodedFrame.setSkBitmap(lazyDecodedSkBitmap);
122
123 // Don't mark the frame as completely decoded until the underlying
124 // decoder has really decoded it. Until then, our data and metadata may
125 // be incorrect, so callers can't rely on them.
126 m_lazyDecodedFrame.setStatus(ImageFrame::FramePartial);
127 } 113 }
128 114 if (m_actualDecoder)
129 return m_actualDecoder ? m_actualDecoder->frameBufferAtIndex(index) : &m_laz yDecodedFrame; 115 return m_actualDecoder->frameBufferAtIndex(index);
116 return 0;
130 } 117 }
131 118
132 void DeferredImageDecoder::setData(SharedBuffer* data, bool allDataReceived) 119 void DeferredImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
133 { 120 {
134 if (m_actualDecoder) { 121 if (m_actualDecoder) {
135 // Keep a reference to data until image decoding is deferred.
136 // When image decoding is deferred then ownership of m_data is
137 // transferred to ImageDecodingStore.
138 m_data = data; 122 m_data = data;
139 m_allDataReceived = allDataReceived; 123 m_allDataReceived = allDataReceived;
140 m_actualDecoder->setData(data, allDataReceived); 124 m_actualDecoder->setData(data, allDataReceived);
141 } else { 125 prepareLazyDecodedFrames();
142 ASSERT(!m_data); 126 }
127
128 if (m_frameGenerator)
143 m_frameGenerator->setData(data, allDataReceived); 129 m_frameGenerator->setData(data, allDataReceived);
144 }
145 } 130 }
146 131
147 bool DeferredImageDecoder::isSizeAvailable() 132 bool DeferredImageDecoder::isSizeAvailable()
148 { 133 {
149 // m_actualDecoder is 0 only if image decoding is deferred and that 134 // m_actualDecoder is 0 only if image decoding is deferred and that
150 // means image header decoded successfully and size is available. 135 // means image header decoded successfully and size is available.
151 return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true; 136 return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true;
152 } 137 }
153 138
154 IntSize DeferredImageDecoder::size() const 139 IntSize DeferredImageDecoder::size() const
155 { 140 {
156 return m_actualDecoder ? m_actualDecoder->size() : m_size; 141 return m_actualDecoder ? m_actualDecoder->size() : m_size;
157 } 142 }
158 143
159 IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const 144 IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const
160 { 145 {
146 // FIXME: Frame size is assumed to be uniform. This might not be true for
147 // future supported codecs.
161 return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size; 148 return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size;
162 } 149 }
163 150
164 size_t DeferredImageDecoder::frameCount() 151 size_t DeferredImageDecoder::frameCount()
165 { 152 {
166 return m_actualDecoder ? m_actualDecoder->frameCount() : 1; 153 return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames .size();
167 } 154 }
168 155
169 int DeferredImageDecoder::repetitionCount() const 156 int DeferredImageDecoder::repetitionCount() const
170 { 157 {
171 return m_actualDecoder ? m_actualDecoder->repetitionCount() : cAnimationNone ; 158 return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCo unt;
172 } 159 }
173 160
174 size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame) 161 size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
175 { 162 {
176 // If image decoding is deferred then frame buffer cache is managed by 163 // If image decoding is deferred then frame buffer cache is managed by
177 // the compositor and this call is ignored. 164 // the compositor and this call is ignored.
178 return m_actualDecoder ? m_actualDecoder->clearCacheExceptFrame(clearExceptF rame) : 0; 165 return m_actualDecoder ? m_actualDecoder->clearCacheExceptFrame(clearExceptF rame) : 0;
179 } 166 }
180 167
181 bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const 168 bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const
182 { 169 {
183 return m_actualDecoder ? m_actualDecoder->frameHasAlphaAtIndex(index) : m_fr ameGenerator->hasAlpha(); 170 if (m_actualDecoder)
171 return m_actualDecoder->frameHasAlphaAtIndex(index);
172 if (!m_frameGenerator->isMultiFrame())
173 return m_frameGenerator->hasAlpha(index);
174 return true;
184 } 175 }
185 176
186 bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const 177 bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const
187 { 178 {
188 // TODO: Implement this for deferred decoding. 179 if (m_actualDecoder)
189 return m_actualDecoder && m_actualDecoder->frameIsCompleteAtIndex(index); 180 return m_actualDecoder->frameIsCompleteAtIndex(index);
181 if (index < m_lazyDecodedFrames.size())
182 return m_lazyDecodedFrames[index]->status() == ImageFrame::FrameComplete ;
183 return false;
190 } 184 }
191 185
192 float DeferredImageDecoder::frameDurationAtIndex(size_t index) const 186 float DeferredImageDecoder::frameDurationAtIndex(size_t index) const
193 { 187 {
194 // TODO: Implement this for deferred decoding. 188 if (m_actualDecoder)
195 return m_actualDecoder ? m_actualDecoder->frameDurationAtIndex(index) : 0; 189 return m_actualDecoder->frameDurationAtIndex(index);
190 if (index < m_lazyDecodedFrames.size())
191 return m_lazyDecodedFrames[index]->duration();
192 return 0;
196 } 193 }
197 194
198 unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const 195 unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const
199 { 196 {
200 // If frame decoding is deferred then it is not managed by MemoryCache 197 // If frame decoding is deferred then it is not managed by MemoryCache
201 // so return 0 here. 198 // so return 0 here.
202 return m_actualDecoder ? m_actualDecoder->frameBytesAtIndex(index) : 0; 199 return m_frameGenerator ? 0 : m_actualDecoder->frameBytesAtIndex(index);
203 } 200 }
204 201
205 ImageOrientation DeferredImageDecoder::orientation() const 202 ImageOrientation DeferredImageDecoder::orientation() const
206 { 203 {
207 return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation; 204 return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation;
208 } 205 }
209 206
210 SkBitmap DeferredImageDecoder::createLazyDecodingBitmap() 207 void DeferredImageDecoder::activateLazyDecoding()
208 {
209 if (m_frameGenerator)
210 return;
211 m_size = m_actualDecoder->size();
212 m_orientation = m_actualDecoder->orientation();
213 m_filenameExtension = m_actualDecoder->filenameExtension();
214 const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationN one || (m_allDataReceived && m_actualDecoder->frameCount() == 1u);
215 m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_size.width(), m_size.height()), m_data, m_allDataReceived, !isSingleFrame);
216 }
217
218 void DeferredImageDecoder::prepareLazyDecodedFrames()
219 {
220 if (!s_enabled
221 || !m_actualDecoder
222 || !m_actualDecoder->isSizeAvailable()
223 || m_actualDecoder->filenameExtension() == "ico")
224 return;
225
226 activateLazyDecoding();
227
228 const size_t previousSize = m_lazyDecodedFrames.size();
229 m_lazyDecodedFrames.resize(m_actualDecoder->frameCount());
230 for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) {
231 OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame()));
232 frame->setSkBitmap(createLazyDecodingBitmap(i));
233 frame->setDuration(m_actualDecoder->frameDurationAtIndex(i));
234 frame->setStatus(m_actualDecoder->frameIsCompleteAtIndex(i) ? ImageFrame ::FrameComplete : ImageFrame::FramePartial);
235 m_lazyDecodedFrames[i] = frame.release();
236 }
237
238 // The last lazy decoded frame created from previous call might be
239 // incomplete so update its state.
240 if (previousSize)
241 m_lazyDecodedFrames[previousSize - 1]->setStatus(m_actualDecoder->frameI sCompleteAtIndex(previousSize - 1) ? ImageFrame::FrameComplete : ImageFrame::Fra mePartial);
242
243 if (m_allDataReceived) {
244 m_repetitionCount = m_actualDecoder->repetitionCount();
245 m_actualDecoder.clear();
246 m_data = nullptr;
247 }
248 }
249
250 SkBitmap DeferredImageDecoder::createLazyDecodingBitmap(size_t index)
211 { 251 {
212 SkISize fullSize = SkISize::Make(m_actualDecoder->size().width(), m_actualDe coder->size().height()); 252 SkISize fullSize = SkISize::Make(m_actualDecoder->size().width(), m_actualDe coder->size().height());
213 ASSERT(!fullSize.isEmpty()); 253 ASSERT(!fullSize.isEmpty());
214 254
215 SkIRect fullRect = SkIRect::MakeSize(fullSize); 255 SkIRect fullRect = SkIRect::MakeSize(fullSize);
216 256
217 // Creates a lazily decoded SkPixelRef that references the entire image with out scaling. 257 // Creates a lazily decoded SkPixelRef that references the entire image with out scaling.
218 SkBitmap bitmap; 258 SkBitmap bitmap;
219 bitmap.setConfig(SkBitmap::kARGB_8888_Config, fullSize.width(), fullSize.hei ght()); 259 bitmap.setConfig(SkBitmap::kARGB_8888_Config, fullSize.width(), fullSize.hei ght());
220 260 bitmap.setPixelRef(new LazyDecodingPixelRef(m_frameGenerator, fullSize, inde x, fullRect))->unref();
221 m_frameGenerator = ImageFrameGenerator::create(fullSize, m_data.release(), m _allDataReceived);
222 m_actualDecoder.clear();
223
224 bitmap.setPixelRef(new LazyDecodingPixelRef(m_frameGenerator, fullSize, full Rect))->unref();
225 261
226 // Use the URI to identify this as a lazily decoded SkPixelRef of type LazyD ecodingPixelRef. 262 // Use the URI to identify this as a lazily decoded SkPixelRef of type LazyD ecodingPixelRef.
227 // FIXME: It would be more useful to give the actual image URI. 263 // FIXME: It would be more useful to give the actual image URI.
228 bitmap.pixelRef()->setURI(labelLazyDecoded); 264 bitmap.pixelRef()->setURI(labelLazyDecoded);
229 265
230 // Inform the bitmap that we will never change the pixels. This is a perform ance hint 266 // Inform the bitmap that we will never change the pixels. This is a perform ance hint
231 // subsystems that may try to cache this bitmap (e.g. pictures, pipes, gpu, pdf, etc.) 267 // subsystems that may try to cache this bitmap (e.g. pictures, pipes, gpu, pdf, etc.)
232 bitmap.setImmutable(); 268 bitmap.setImmutable();
233 269
234 // FIXME: Setting bitmap.setIsOpaque() is big performance gain if possible. We can
235 // do so safely if the image is fully loaded and it is a JPEG image, or if t he image was
236 // decoded before.
237
238 return bitmap; 270 return bitmap;
239 } 271 }
240 272
241 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const 273 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
242 { 274 {
275 // TODO: Implement.
243 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false; 276 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
244 } 277 }
245 278
246 } // namespace WebCore 279 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698