1 /*
2 * Copyright 2007, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "BitmapAllocatorAndroid.h"
28 #include "ImageSource.h"
29 #include "IntSize.h"
30 #include "NotImplemented.h"
31 #include "SharedBuffer.h"
32 #include "PlatformString.h"
33
34 #include "SkBitmapRef.h"
35 #include "SkImageDecoder.h"
36 #include "SkImageRef.h"
37 #include "SkStream.h"
38 #include "SkTemplates.h"
39
40 #ifdef ANDROID_ANIMATED_GIF
41 #include "EmojiFont.h"
42 #include "gif/GIFImageDecoder.h"
43
44 using namespace android;
45 #endif
46
47 SkPixelRef* SkCreateRLEPixelRef(const SkBitmap& src);
48
49 //#define TRACE_SUBSAMPLE_BITMAPS
50 //#define TRACE_RLE_BITMAPS
51
52
53 // don't use RLE for images smaller than this, since they incur a drawing cost
54 // (and don't work as patterns yet) we only want to use RLE when we must
55 #define MIN_RLE_ALLOC_SIZE (2*1024*1024)
56
57 /* Images larger than this should be subsampled. Using ashmem, the decoded
58 pixels will be purged as needed, so this value can be pretty large. Making
59 it too small hurts image quality (e.g. abc.com background). 2Meg works for
60 the sites I've tested, but if we hit important sites that need more, we
61 should try increasing it and see if it has negative impact on performance
62 (i.e. we end up thrashing because we need to keep decoding images that have
63 been purged.
64
65 Perhaps this value should be some fraction of the available RAM...
66 */
computeMaxBitmapSizeForCache()67 static size_t computeMaxBitmapSizeForCache() {
68 return 2*1024*1024;
69 }
70
71 /* 8bit images larger than this should be recompressed in RLE, to reduce
72 on the imageref cache.
73
74 Downside: performance, since we have to decode/encode
75 and then rle-decode when we draw.
76 */
shouldReencodeAsRLE(const SkBitmap & bm)77 static bool shouldReencodeAsRLE(const SkBitmap& bm) {
78 const SkBitmap::Config c = bm.config();
79 return (SkBitmap::kIndex8_Config == c || SkBitmap::kA8_Config == c)
80 &&
81 bm.width() >= 64 // narrower than this won't compress well in RLE
82 &&
83 bm.getSize() > MIN_RLE_ALLOC_SIZE;
84 }
85
86 ///////////////////////////////////////////////////////////////////////////////
87
88 class PrivateAndroidImageSourceRec : public SkBitmapRef {
89 public:
PrivateAndroidImageSourceRec(const SkBitmap & bm,int origWidth,int origHeight,int sampleSize)90 PrivateAndroidImageSourceRec(const SkBitmap& bm, int origWidth,
91 int origHeight, int sampleSize)
92 : SkBitmapRef(bm), fSampleSize(sampleSize), fAllDataReceived(false) {
93 this->setOrigSize(origWidth, origHeight);
94 }
95
96 int fSampleSize;
97 bool fAllDataReceived;
98 };
99
100 namespace WebCore {
101
ImageSource()102 ImageSource::ImageSource() {
103 m_decoder.m_image = NULL;
104 #ifdef ANDROID_ANIMATED_GIF
105 m_decoder.m_gifDecoder = 0;
106 #endif
107 }
108
~ImageSource()109 ImageSource::~ImageSource() {
110 delete m_decoder.m_image;
111 #ifdef ANDROID_ANIMATED_GIF
112 delete m_decoder.m_gifDecoder;
113 #endif
114 }
115
initialized() const116 bool ImageSource::initialized() const {
117 return
118 #ifdef ANDROID_ANIMATED_GIF
119 m_decoder.m_gifDecoder ||
120 #endif
121 m_decoder.m_image != NULL;
122 }
123
computeSampleSize(const SkBitmap & bitmap)124 static int computeSampleSize(const SkBitmap& bitmap) {
125 const size_t maxSize = computeMaxBitmapSizeForCache();
126 size_t size = bitmap.getSize();
127 int sampleSize = 1;
128
129 while (size > maxSize) {
130 sampleSize <<= 1;
131 size >>= 2;
132 }
133
134 #ifdef TRACE_SUBSAMPLE_BITMAPS
135 if (sampleSize > 1) {
136 SkDebugf("------- bitmap [%d %d] config=%d origSize=%d predictSize=%d sampleSize=%d\n",
137 bitmap.width(), bitmap.height(), bitmap.config(),
138 bitmap.getSize(), size, sampleSize);
139 }
140 #endif
141 return sampleSize;
142 }
143
convertToRLE(SkBitmap * bm,const void * data,size_t len)144 static SkPixelRef* convertToRLE(SkBitmap* bm, const void* data, size_t len) {
145 if (!shouldReencodeAsRLE(*bm)) {
146 return NULL;
147 }
148
149 SkBitmap tmp;
150
151 if (!SkImageDecoder::DecodeMemory(data, len, &tmp) || !tmp.getPixels()) {
152 return NULL;
153 }
154
155 SkPixelRef* ref = SkCreateRLEPixelRef(tmp);
156 if (NULL == ref) {
157 return NULL;
158 }
159
160 #ifdef TRACE_RLE_BITMAPS
161 SkDebugf("---- reencode bitmap as RLE: [%d %d] encodeSize=%d\n",
162 tmp.width(), tmp.height(), len);
163 #endif
164
165 bm->setConfig(SkBitmap::kRLE_Index8_Config, tmp.width(), tmp.height());
166 return ref;
167 }
168
clearURL()169 void ImageSource::clearURL()
170 {
171 m_decoder.m_url.reset();
172 }
173
setURL(const String & url)174 void ImageSource::setURL(const String& url)
175 {
176 if (url.startsWith("data:")) {
177 clearURL();
178 } else {
179 m_decoder.m_url.setUTF16(url.characters(), url.length());
180 }
181 }
182
183 #ifdef ANDROID_ANIMATED_GIF
184 // we only animate small GIFs for now, to save memory
185 // also, we only support this in Japan, hence the Emoji check
should_use_animated_gif(int width,int height)186 static bool should_use_animated_gif(int width, int height) {
187 return EmojiFont::IsAvailable() &&
188 width <= 32 && height <= 32;
189 }
190 #endif
191
setData(SharedBuffer * data,bool allDataReceived)192 void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
193 {
194 #ifdef ANDROID_ANIMATED_GIF
195 // This is only necessary if we allow ourselves to partially decode GIF
196 if (m_decoder.m_gifDecoder
197 && !m_decoder.m_gifDecoder->failed()) {
198 m_decoder.m_gifDecoder->setData(data, allDataReceived);
199 return;
200 }
201 #endif
202 if (NULL == m_decoder.m_image
203 #ifdef ANDROID_ANIMATED_GIF
204 && !m_decoder.m_gifDecoder
205 #endif
206 ) {
207 SkBitmap tmp;
208
209 SkMemoryStream stream(data->data(), data->size(), false);
210 SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
211 SkAutoTDelete<SkImageDecoder> ad(codec);
212
213 if (!codec || !codec->decode(&stream, &tmp, SkBitmap::kNo_Config,
214 SkImageDecoder::kDecodeBounds_Mode)) {
215 return;
216 }
217
218 int origW = tmp.width();
219 int origH = tmp.height();
220
221 #ifdef ANDROID_ANIMATED_GIF
222 // First, check to see if this is an animated GIF
223 const Vector<char>& buffer = data->buffer();
224 const char* contents = buffer.data();
225 if (buffer.size() > 3 && strncmp(contents, "GIF8", 4) == 0 &&
226 should_use_animated_gif(origW, origH)) {
227 // This means we are looking at a GIF, so create special
228 // GIF Decoder
229 // Need to wait for all data received if we are assigning an
230 // allocator (which we are not at the moment).
231 if (!m_decoder.m_gifDecoder /*&& allDataReceived*/)
232 m_decoder.m_gifDecoder = new GIFImageDecoder();
233 if (!m_decoder.m_gifDecoder->failed())
234 m_decoder.m_gifDecoder->setData(data, allDataReceived);
235 return;
236 }
237 #endif
238
239 int sampleSize = computeSampleSize(tmp);
240 if (sampleSize > 1) {
241 codec->setSampleSize(sampleSize);
242 stream.rewind();
243 if (!codec->decode(&stream, &tmp, SkBitmap::kNo_Config,
244 SkImageDecoder::kDecodeBounds_Mode)) {
245 return;
246 }
247 }
248
249 m_decoder.m_image = new PrivateAndroidImageSourceRec(tmp, origW, origH,
250 sampleSize);
251
252 // SkDebugf("----- started: [%d %d] %s\n", origW, origH, m_decoder.m_url.c_str());
253 }
254
255 PrivateAndroidImageSourceRec* decoder = m_decoder.m_image;
256 if (allDataReceived && !decoder->fAllDataReceived) {
257 decoder->fAllDataReceived = true;
258
259 SkBitmap* bm = &decoder->bitmap();
260 SkPixelRef* ref = convertToRLE(bm, data->data(), data->size());
261
262 if (ref) {
263 bm->setPixelRef(ref)->unref();
264 } else {
265 BitmapAllocatorAndroid alloc(data, decoder->fSampleSize);
266 if (!alloc.allocPixelRef(bm, NULL)) {
267 return;
268 }
269 ref = bm->pixelRef();
270 }
271
272 // we promise to never change the pixels (makes picture recording fast)
273 ref->setImmutable();
274 // give it the URL if we have one
275 ref->setURI(m_decoder.m_url);
276 }
277 }
278
isSizeAvailable()279 bool ImageSource::isSizeAvailable()
280 {
281 return
282 #ifdef ANDROID_ANIMATED_GIF
283 (m_decoder.m_gifDecoder
284 && m_decoder.m_gifDecoder->isSizeAvailable()) ||
285 #endif
286 m_decoder.m_image != NULL;
287 }
288
size() const289 IntSize ImageSource::size() const
290 {
291 #ifdef ANDROID_ANIMATED_GIF
292 if (m_decoder.m_gifDecoder)
293 return m_decoder.m_gifDecoder->size();
294 #endif
295 if (m_decoder.m_image) {
296 return IntSize(m_decoder.m_image->origWidth(), m_decoder.m_image->origHeight());
297 }
298 return IntSize(0, 0);
299 }
300
repetitionCount()301 int ImageSource::repetitionCount()
302 {
303 #ifdef ANDROID_ANIMATED_GIF
304 if (m_decoder.m_gifDecoder)
305 return m_decoder.m_gifDecoder->repetitionCount();
306 if (!m_decoder.m_image) return 0;
307 #endif
308 return 1;
309 // A property with value 0 means loop forever.
310 }
311
frameCount() const312 size_t ImageSource::frameCount() const
313 {
314 #ifdef ANDROID_ANIMATED_GIF
315 if (m_decoder.m_gifDecoder) {
316 return m_decoder.m_gifDecoder->failed() ? 0
317 : m_decoder.m_gifDecoder->frameCount();
318 }
319 #endif
320 // i.e. 0 frames if we're not decoded, or 1 frame if we are
321 return m_decoder.m_image != NULL;
322 }
323
createFrameAtIndex(size_t index)324 SkBitmapRef* ImageSource::createFrameAtIndex(size_t index)
325 {
326 #ifdef ANDROID_ANIMATED_GIF
327 if (m_decoder.m_gifDecoder) {
328 RGBA32Buffer* buffer =
329 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
330 if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
331 return 0;
332 SkBitmap& bitmap = buffer->bitmap();
333 SkPixelRef* pixelRef = bitmap.pixelRef();
334 if (pixelRef)
335 pixelRef->setURI(m_decoder.m_url);
336 return new SkBitmapRef(bitmap);
337 }
338 #else
339 SkASSERT(index == 0);
340 #endif
341 SkASSERT(m_decoder.m_image != NULL);
342 m_decoder.m_image->ref();
343 return m_decoder.m_image;
344 }
345
frameDurationAtIndex(size_t index)346 float ImageSource::frameDurationAtIndex(size_t index)
347 {
348 float duration = 0;
349 #ifdef ANDROID_ANIMATED_GIF
350 if (m_decoder.m_gifDecoder) {
351 RGBA32Buffer* buffer
352 = m_decoder.m_gifDecoder->frameBufferAtIndex(index);
353 if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
354 return 0;
355 duration = buffer->duration() / 1000.0f;
356 }
357 #else
358 SkASSERT(index == 0);
359 #endif
360
361 // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
362 // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
363 // a duration of <= 10 ms. See gfxImageFrame::GetTimeout in Gecko or Radar 4051389 for more.
364 if (duration <= 0.010f)
365 duration = 0.100f;
366 return duration;
367 }
368
frameHasAlphaAtIndex(size_t index)369 bool ImageSource::frameHasAlphaAtIndex(size_t index)
370 {
371 #ifdef ANDROID_ANIMATED_GIF
372 if (m_decoder.m_gifDecoder) {
373 if (!m_decoder.m_gifDecoder->supportsAlpha())
374 return false;
375
376 RGBA32Buffer* buffer =
377 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
378 if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
379 return false;
380
381 return buffer->hasAlpha();
382 }
383 #else
384 SkASSERT(0 == index);
385 #endif
386
387 if (NULL == m_decoder.m_image)
388 return true; // if we're not sure, assume the worse-case
389 const PrivateAndroidImageSourceRec& decoder = *m_decoder.m_image;
390 // if we're 16bit, we know even without all the data available
391 if (decoder.bitmap().getConfig() == SkBitmap::kRGB_565_Config)
392 return false;
393
394 if (!decoder.fAllDataReceived)
395 return true; // if we're not sure, assume the worse-case
396
397 return !decoder.bitmap().isOpaque();
398 }
399
frameIsCompleteAtIndex(size_t index)400 bool ImageSource::frameIsCompleteAtIndex(size_t index)
401 {
402 #ifdef ANDROID_ANIMATED_GIF
403 if (m_decoder.m_gifDecoder) {
404 RGBA32Buffer* buffer =
405 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
406 return buffer && buffer->status() == RGBA32Buffer::FrameComplete;
407 }
408 #else
409 SkASSERT(0 == index);
410 #endif
411 return m_decoder.m_image && m_decoder.m_image->fAllDataReceived;
412 }
413
clear(bool destroyAll,size_t clearBeforeFrame,SharedBuffer * data,bool allDataReceived)414 void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
415 {
416 #ifdef ANDROID_ANIMATED_GIF
417 if (!destroyAll) {
418 if (m_decoder.m_gifDecoder)
419 m_decoder.m_gifDecoder->clearFrameBufferCache(clearBeforeFrame);
420 return;
421 }
422
423 delete m_decoder.m_gifDecoder;
424 m_decoder.m_gifDecoder = 0;
425 if (data)
426 setData(data, allDataReceived);
427 #endif
428 // do nothing, since the cache is managed elsewhere
429 }
430
frameSizeAtIndex(size_t index) const431 IntSize ImageSource::frameSizeAtIndex(size_t index) const
432 {
433 // for now, all (1) of our frames are the same size
434 return this->size();
435 }
436
filenameExtension() const437 String ImageSource::filenameExtension() const
438 {
439 // FIXME: need to add virtual to our decoders to return "jpg/png/gif/..."
440 #ifdef ANDROID_ANIMATED_GIF
441 if (m_decoder.m_gifDecoder)
442 return m_decoder.m_gifDecoder->filenameExtension();
443 #endif
444 return String();
445 }
446
447 }
448