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

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

Issue 17999003: Deferred image decoding to support animated GIFs (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: done 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 ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index) 100 ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index)
100 { 101 {
101 // Only defer image decoding if this is a single frame image. The reason is 102 prepareLazyDecodedFrames();
102 // because a multiframe is usually animated GIF. Animation is handled by 103 if (index < m_lazyDecodedFrames.size())
103 // BitmapImage which uses some metadata functions that do synchronous image 104 return m_lazyDecodedFrames[index].get();
104 // decoding. 105 if (m_actualDecoder)
105 if (s_enabled 106 return m_actualDecoder->frameBufferAtIndex(index);
106 && m_actualDecoder 107 return 0;
107 && m_actualDecoder->repetitionCount() == cAnimationNone
108 && m_actualDecoder->isSizeAvailable()
109 && m_actualDecoder->frameCount() == 1) {
110
111 m_size = m_actualDecoder->size();
112 m_orientation = m_actualDecoder->orientation();
113
114 SkBitmap lazyDecodedSkBitmap = createLazyDecodingBitmap();
115 m_lazyDecodedFrame.setSkBitmap(lazyDecodedSkBitmap);
116
117 // Don't mark the frame as completely decoded until the underlying
118 // decoder has really decoded it. Until then, our data and metadata may
119 // be incorrect, so callers can't rely on them.
120 m_lazyDecodedFrame.setStatus(ImageFrame::FramePartial);
121 }
122
123 return m_actualDecoder ? m_actualDecoder->frameBufferAtIndex(index) : &m_laz yDecodedFrame;
124 } 108 }
125 109
126 void DeferredImageDecoder::setData(SharedBuffer* data, bool allDataReceived) 110 void DeferredImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
127 { 111 {
128 if (m_actualDecoder) { 112 if (m_actualDecoder) {
129 // Keep a reference to data until image decoding is deferred.
130 // When image decoding is deferred then ownership of m_data is
131 // transferred to ImageDecodingStore.
132 m_data = data; 113 m_data = data;
133 m_allDataReceived = allDataReceived; 114 m_allDataReceived = allDataReceived;
134 m_actualDecoder->setData(data, allDataReceived); 115 m_actualDecoder->setData(data, allDataReceived);
135 } else { 116 prepareLazyDecodedFrames();
136 ASSERT(!m_data); 117 }
118
119 if (m_frameGenerator)
137 m_frameGenerator->setData(data, allDataReceived); 120 m_frameGenerator->setData(data, allDataReceived);
138 }
139 } 121 }
140 122
141 bool DeferredImageDecoder::isSizeAvailable() 123 bool DeferredImageDecoder::isSizeAvailable()
142 { 124 {
143 // m_actualDecoder is 0 only if image decoding is deferred and that 125 // m_actualDecoder is 0 only if image decoding is deferred and that
144 // means image header decoded successfully and size is available. 126 // means image header decoded successfully and size is available.
145 return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true; 127 return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true;
146 } 128 }
147 129
148 IntSize DeferredImageDecoder::size() const 130 IntSize DeferredImageDecoder::size() const
149 { 131 {
150 return m_actualDecoder ? m_actualDecoder->size() : m_size; 132 return m_actualDecoder ? m_actualDecoder->size() : m_size;
151 } 133 }
152 134
153 IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const 135 IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const
154 { 136 {
137 // FIXME: Frame size is assumed to be uniform. This might not be true for
138 // future supported codecs.
155 return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size; 139 return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size;
156 } 140 }
157 141
158 size_t DeferredImageDecoder::frameCount() 142 size_t DeferredImageDecoder::frameCount()
159 { 143 {
160 return m_actualDecoder ? m_actualDecoder->frameCount() : 1; 144 return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames .size();
161 } 145 }
162 146
163 int DeferredImageDecoder::repetitionCount() const 147 int DeferredImageDecoder::repetitionCount() const
164 { 148 {
165 return m_actualDecoder ? m_actualDecoder->repetitionCount() : cAnimationNone ; 149 return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCo unt;
166 } 150 }
167 151
168 size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame) 152 size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
169 { 153 {
170 // If image decoding is deferred then frame buffer cache is managed by 154 // If image decoding is deferred then frame buffer cache is managed by
171 // the compositor and this call is ignored. 155 // the compositor and this call is ignored.
172 return m_actualDecoder ? m_actualDecoder->clearCacheExceptFrame(clearExceptF rame) : 0; 156 return m_actualDecoder ? m_actualDecoder->clearCacheExceptFrame(clearExceptF rame) : 0;
173 } 157 }
174 158
175 bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const 159 bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const
176 { 160 {
177 return m_actualDecoder ? m_actualDecoder->frameHasAlphaAtIndex(index) : m_fr ameGenerator->hasAlpha(); 161 // FIXME: Report this for multi-frame image.
162 if (m_actualDecoder)
163 return m_actualDecoder->frameHasAlphaAtIndex(index);
164 if (!m_frameGenerator->isMultiFrame())
165 return m_frameGenerator->hasAlpha();
166 return true;
178 } 167 }
179 168
180 bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const 169 bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const
181 { 170 {
182 // TODO: Implement this for deferred decoding. 171 if (m_actualDecoder)
183 return m_actualDecoder && m_actualDecoder->frameIsCompleteAtIndex(index); 172 return m_actualDecoder->frameIsCompleteAtIndex(index);
173 if (index < m_lazyDecodedFrames.size())
174 return m_lazyDecodedFrames[index]->status() == ImageFrame::FrameComplete ;
175 return false;
184 } 176 }
185 177
186 float DeferredImageDecoder::frameDurationAtIndex(size_t index) const 178 float DeferredImageDecoder::frameDurationAtIndex(size_t index) const
187 { 179 {
188 // TODO: Implement this for deferred decoding. 180 if (m_actualDecoder)
189 return m_actualDecoder ? m_actualDecoder->frameDurationAtIndex(index) : 0; 181 return m_actualDecoder->frameDurationAtIndex(index);
182 if (index < m_lazyDecodedFrames.size())
183 return m_lazyDecodedFrames[index]->duration();
184 return 0;
190 } 185 }
191 186
192 unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const 187 unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const
193 { 188 {
194 // If frame decoding is deferred then it is not managed by MemoryCache 189 // If frame decoding is deferred then it is not managed by MemoryCache
195 // so return 0 here. 190 // so return 0 here.
196 return m_actualDecoder ? m_actualDecoder->frameBytesAtIndex(index) : 0; 191 return m_frameGenerator ? 0 : m_actualDecoder->frameBytesAtIndex(index);
197 } 192 }
198 193
199 ImageOrientation DeferredImageDecoder::orientation() const 194 ImageOrientation DeferredImageDecoder::orientation() const
200 { 195 {
201 return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation; 196 return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation;
202 } 197 }
203 198
204 SkBitmap DeferredImageDecoder::createLazyDecodingBitmap() 199 void DeferredImageDecoder::activateLazyDecoding()
200 {
201 if (m_frameGenerator)
202 return;
203 m_size = m_actualDecoder->size();
204 m_orientation = m_actualDecoder->orientation();
205 const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationN one || (m_allDataReceived && m_actualDecoder->frameCount() == 1u);
206 m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_size.width(), m_size.height()), m_data, m_allDataReceived, !isSingleFrame);
207 }
208
209 void DeferredImageDecoder::prepareLazyDecodedFrames()
210 {
211 if (!s_enabled
212 || !m_actualDecoder
213 || !m_actualDecoder->isSizeAvailable())
214 return;
215
216 activateLazyDecoding();
217
218 const size_t previousSize = m_lazyDecodedFrames.size();
219 m_lazyDecodedFrames.resize(m_actualDecoder->frameCount());
220 for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) {
221 OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame()));
222 frame->setSkBitmap(createLazyDecodingBitmap(i));
223 frame->setDuration(m_actualDecoder->frameDurationAtIndex(i));
224 frame->setStatus(m_actualDecoder->frameIsCompleteAtIndex(i) ? ImageFrame ::FrameComplete : ImageFrame::FramePartial);
225 m_lazyDecodedFrames[i] = frame.release();
226 }
227
228 // The last lazy decoded frame created from previous call might be
229 // incomplete so update its state.
230 if (previousSize)
231 m_lazyDecodedFrames[previousSize - 1]->setStatus(m_actualDecoder->frameI sCompleteAtIndex(previousSize - 1) ? ImageFrame::FrameComplete : ImageFrame::Fra mePartial);
232
233 if (m_allDataReceived) {
234 m_repetitionCount = m_actualDecoder->repetitionCount();
235 m_actualDecoder.clear();
236 m_data = nullptr;
237 }
238 }
239
240 SkBitmap DeferredImageDecoder::createLazyDecodingBitmap(size_t index)
205 { 241 {
206 SkISize fullSize = SkISize::Make(m_actualDecoder->size().width(), m_actualDe coder->size().height()); 242 SkISize fullSize = SkISize::Make(m_actualDecoder->size().width(), m_actualDe coder->size().height());
207 ASSERT(!fullSize.isEmpty()); 243 ASSERT(!fullSize.isEmpty());
208 244
209 SkIRect fullRect = SkIRect::MakeSize(fullSize); 245 SkIRect fullRect = SkIRect::MakeSize(fullSize);
210 246
211 // Creates a lazily decoded SkPixelRef that references the entire image with out scaling. 247 // Creates a lazily decoded SkPixelRef that references the entire image with out scaling.
212 SkBitmap bitmap; 248 SkBitmap bitmap;
213 bitmap.setConfig(SkBitmap::kARGB_8888_Config, fullSize.width(), fullSize.hei ght()); 249 bitmap.setConfig(SkBitmap::kARGB_8888_Config, fullSize.width(), fullSize.hei ght());
214 250 bitmap.setPixelRef(new LazyDecodingPixelRef(m_frameGenerator, fullSize, inde x, fullRect))->unref();
215 m_frameGenerator = ImageFrameGenerator::create(fullSize, m_data.release(), m _allDataReceived);
216 m_actualDecoder.clear();
217
218 bitmap.setPixelRef(new LazyDecodingPixelRef(m_frameGenerator, fullSize, full Rect))->unref();
219 251
220 // Use the URI to identify this as a lazily decoded SkPixelRef of type LazyD ecodingPixelRef. 252 // Use the URI to identify this as a lazily decoded SkPixelRef of type LazyD ecodingPixelRef.
221 // FIXME: It would be more useful to give the actual image URI. 253 // FIXME: It would be more useful to give the actual image URI.
222 bitmap.pixelRef()->setURI(labelLazyDecoded); 254 bitmap.pixelRef()->setURI(labelLazyDecoded);
223 255
224 // Inform the bitmap that we will never change the pixels. This is a perform ance hint 256 // Inform the bitmap that we will never change the pixels. This is a perform ance hint
225 // subsystems that may try to cache this bitmap (e.g. pictures, pipes, gpu, pdf, etc.) 257 // subsystems that may try to cache this bitmap (e.g. pictures, pipes, gpu, pdf, etc.)
226 bitmap.setImmutable(); 258 bitmap.setImmutable();
227 259
228 // FIXME: Setting bitmap.setIsOpaque() is big performance gain if possible. We can 260 // FIXME: Setting bitmap.setIsOpaque() is big performance gain if possible. We can
229 // do so safely if the image is fully loaded and it is a JPEG image, or if t he image was 261 // do so safely if the image is fully loaded and it is a JPEG image, or if t he image was
230 // decoded before. 262 // decoded before.
231 263
232 return bitmap; 264 return bitmap;
233 } 265 }
234 266
235 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const 267 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
236 { 268 {
269 // TODO: Implement.
237 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false; 270 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
238 } 271 }
239 272
240 } // namespace WebCore 273 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698