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 THE COPYRIGHT OWNER 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 #define LOG_TAG "ImageSourceAndroid"
27
28 #include "config.h"
29
30 #include "AndroidLog.h"
31 #include "BitmapAllocatorAndroid.h"
32 #include "ImageSource.h"
33 #include "IntSize.h"
34 #include "NotImplemented.h"
35 #include "SharedBuffer.h"
36 #include "PlatformString.h"
37
38 #include "SkBitmapRef.h"
39 #include "SkImageDecoder.h"
40 #include "SkImageRef.h"
41 #include "SkStream.h"
42 #include "SkTemplates.h"
43
44 #ifdef ANDROID_ANIMATED_GIF
45 #include "EmojiFont.h"
46 #include "GIFImageDecoder.h"
47
48 using namespace android;
49 #endif
50
51 // TODO: We should make use of some of the common code in platform/graphics/ImageSource.cpp.
52
53 //#define TRACE_SUBSAMPLE_BITMAPS
54
55
56 // flag to tell us when we're on a large-ram device (e.g. >= 256M)
57 #ifdef ANDROID_LARGE_MEMORY_DEVICE
58 // see dox for computeMaxBitmapSizeForCache()
59 #define MAX_SIZE_BEFORE_SUBSAMPLE (32*1024*1024)
60
61 // preserve quality for 24/32bit src
62 static const SkBitmap::Config gPrefConfigTable[6] = {
63 SkBitmap::kIndex8_Config, // src: index, opaque
64 SkBitmap::kIndex8_Config, // src: index, alpha
65 SkBitmap::kRGB_565_Config, // src: 16bit, opaque
66 SkBitmap::kARGB_8888_Config, // src: 16bit, alpha (promote to 32bit)
67 SkBitmap::kARGB_8888_Config, // src: 32bit, opaque
68 SkBitmap::kARGB_8888_Config, // src: 32bit, alpha
69 };
70 #else
71 #define MAX_SIZE_BEFORE_SUBSAMPLE (2*1024*1024)
72
73 // tries to minimize memory usage (i.e. demote opaque 32bit -> 16bit)
74 static const SkBitmap::Config gPrefConfigTable[6] = {
75 SkBitmap::kIndex8_Config, // src: index, opaque
76 SkBitmap::kIndex8_Config, // src: index, alpha
77 SkBitmap::kRGB_565_Config, // src: 16bit, opaque
78 SkBitmap::kARGB_8888_Config, // src: 16bit, alpha (promote to 32bit)
79 SkBitmap::kRGB_565_Config, // src: 32bit, opaque (demote to 16bit)
80 SkBitmap::kARGB_8888_Config, // src: 32bit, alpha
81 };
82 #endif
83
84 /* Images larger than this should be subsampled. Using ashmem, the decoded
85 pixels will be purged as needed, so this value can be pretty large. Making
86 it too small hurts image quality (e.g. abc.com background). 2Meg works for
87 the sites I've tested, but if we hit important sites that need more, we
88 should try increasing it and see if it has negative impact on performance
89 (i.e. we end up thrashing because we need to keep decoding images that have
90 been purged.
91
92 Perhaps this value should be some fraction of the available RAM...
93 */
computeMaxBitmapSizeForCache()94 size_t computeMaxBitmapSizeForCache() {
95 return MAX_SIZE_BEFORE_SUBSAMPLE;
96 }
97 ///////////////////////////////////////////////////////////////////////////////
98
99 class PrivateAndroidImageSourceRec : public SkBitmapRef {
100 public:
PrivateAndroidImageSourceRec(const SkBitmap & bm,int origWidth,int origHeight,int sampleSize)101 PrivateAndroidImageSourceRec(const SkBitmap& bm, int origWidth,
102 int origHeight, int sampleSize)
103 : SkBitmapRef(bm), fSampleSize(sampleSize), fAllDataReceived(false) {
104 this->setOrigSize(origWidth, origHeight);
105 }
106
107 int fSampleSize;
108 bool fAllDataReceived;
109 };
110
111 namespace WebCore {
112
ImageSource(AlphaOption alphaOption,GammaAndColorProfileOption gammaAndColorProfileOption)113 ImageSource::ImageSource(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
114 : m_alphaOption(alphaOption)
115 , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
116 {
117 m_decoder.m_image = NULL;
118 #ifdef ANDROID_ANIMATED_GIF
119 m_decoder.m_gifDecoder = 0;
120 #endif
121 }
122
~ImageSource()123 ImageSource::~ImageSource() {
124 delete m_decoder.m_image;
125 #ifdef ANDROID_ANIMATED_GIF
126 delete m_decoder.m_gifDecoder;
127 #endif
128 }
129
initialized() const130 bool ImageSource::initialized() const {
131 return
132 #ifdef ANDROID_ANIMATED_GIF
133 m_decoder.m_gifDecoder ||
134 #endif
135 m_decoder.m_image != NULL;
136 }
137
computeSampleSize(const SkBitmap & bitmap)138 static int computeSampleSize(const SkBitmap& bitmap) {
139 const size_t maxSize = computeMaxBitmapSizeForCache();
140 size_t size = bitmap.getSize();
141 int sampleSize = 1;
142
143 while (size > maxSize) {
144 sampleSize <<= 1;
145 size >>= 2;
146 }
147
148 #ifdef TRACE_SUBSAMPLE_BITMAPS
149 if (sampleSize > 1) {
150 ALOGD("------- bitmap [%d %d] config=%d origSize=%d predictSize=%d sampleSize=%d\n",
151 bitmap.width(), bitmap.height(), bitmap.config(),
152 bitmap.getSize(), size, sampleSize);
153 }
154 #endif
155 return sampleSize;
156 }
157
clearURL()158 void ImageSource::clearURL()
159 {
160 m_decoder.m_url.reset();
161 }
162
setURL(const String & url)163 void ImageSource::setURL(const String& url)
164 {
165 m_decoder.m_url.setUTF16(url.characters(), url.length());
166 }
167
168 #ifdef ANDROID_ANIMATED_GIF
169 // we only animate small GIFs for now, to save memory
170 // also, we only support this in Japan, hence the Emoji check
should_use_animated_gif(int width,int height)171 static bool should_use_animated_gif(int width, int height) {
172 #ifdef ANDROID_LARGE_MEMORY_DEVICE
173 return true;
174 #else
175 return EmojiFont::IsAvailable() &&
176 width <= 32 && height <= 32;
177 #endif
178 }
179 #endif
180
setData(SharedBuffer * data,bool allDataReceived)181 void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
182 {
183 #ifdef ANDROID_ANIMATED_GIF
184 // This is only necessary if we allow ourselves to partially decode GIF
185 bool disabledAnimatedGif = false;
186 if (m_decoder.m_gifDecoder
187 && !m_decoder.m_gifDecoder->failed()) {
188 m_decoder.m_gifDecoder->setData(data, allDataReceived);
189 if (!allDataReceived || m_decoder.m_gifDecoder->frameCount() != 1)
190 return;
191 disabledAnimatedGif = true;
192 delete m_decoder.m_gifDecoder;
193 m_decoder.m_gifDecoder = 0;
194 }
195 #endif
196 if (NULL == m_decoder.m_image
197 #ifdef ANDROID_ANIMATED_GIF
198 && !m_decoder.m_gifDecoder
199 #endif
200 ) {
201 SkBitmap tmp;
202
203 SkMemoryStream stream(data->data(), data->size(), false);
204 SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
205 if (!codec)
206 return;
207
208 SkAutoTDelete<SkImageDecoder> ad(codec);
209 codec->setPrefConfigTable(gPrefConfigTable);
210 if (!codec->decode(&stream, &tmp, SkImageDecoder::kDecodeBounds_Mode))
211 return;
212
213 int origW = tmp.width();
214 int origH = tmp.height();
215
216 #ifdef ANDROID_ANIMATED_GIF
217 // First, check to see if this is an animated GIF
218 const char* contents = data->data();
219 if (data->size() > 3 && strncmp(contents, "GIF8", 4) == 0
220 && should_use_animated_gif(origW, origH)
221 && !disabledAnimatedGif) {
222 // This means we are looking at a GIF, so create special
223 // GIF Decoder
224 // Need to wait for all data received if we are assigning an
225 // allocator (which we are not at the moment).
226 if (!m_decoder.m_gifDecoder /*&& allDataReceived*/)
227 m_decoder.m_gifDecoder = new GIFImageDecoder(m_alphaOption, m_gammaAndColorProfileOption);
228 int frameCount = 0;
229 if (!m_decoder.m_gifDecoder->failed()) {
230 m_decoder.m_gifDecoder->setData(data, allDataReceived);
231 if (!allDataReceived)
232 return;
233 frameCount = m_decoder.m_gifDecoder->frameCount();
234 }
235 if (frameCount != 1)
236 return;
237 delete m_decoder.m_gifDecoder;
238 m_decoder.m_gifDecoder = 0;
239 }
240 #endif
241
242 int sampleSize = computeSampleSize(tmp);
243 if (sampleSize > 1) {
244 codec->setSampleSize(sampleSize);
245 stream.rewind();
246 if (!codec->decode(&stream, &tmp,
247 SkImageDecoder::kDecodeBounds_Mode)) {
248 return;
249 }
250 }
251
252 m_decoder.m_image = new PrivateAndroidImageSourceRec(tmp, origW, origH,
253 sampleSize);
254
255 // ALOGD("----- started: [%d %d] %s\n", origW, origH, m_decoder.m_url.c_str());
256 }
257
258 PrivateAndroidImageSourceRec* decoder = m_decoder.m_image;
259 if (allDataReceived && decoder && !decoder->fAllDataReceived) {
260 decoder->fAllDataReceived = true;
261
262 SkBitmap* bm = &decoder->bitmap();
263
264 BitmapAllocatorAndroid alloc(data, decoder->fSampleSize);
265 if (!alloc.allocPixelRef(bm, NULL)) {
266 return;
267 }
268 SkPixelRef* ref = bm->pixelRef();
269
270 // we promise to never change the pixels (makes picture recording fast)
271 ref->setImmutable();
272 // give it the URL if we have one
273 ref->setURI(m_decoder.m_url);
274 }
275 }
276
isSizeAvailable()277 bool ImageSource::isSizeAvailable()
278 {
279 return
280 #ifdef ANDROID_ANIMATED_GIF
281 (m_decoder.m_gifDecoder
282 && m_decoder.m_gifDecoder->isSizeAvailable()) ||
283 #endif
284 m_decoder.m_image != NULL;
285 }
286
size() const287 IntSize ImageSource::size() const
288 {
289 #ifdef ANDROID_ANIMATED_GIF
290 if (m_decoder.m_gifDecoder)
291 return m_decoder.m_gifDecoder->size();
292 #endif
293 if (m_decoder.m_image) {
294 return IntSize(m_decoder.m_image->origWidth(), m_decoder.m_image->origHeight());
295 }
296 return IntSize(0, 0);
297 }
298
repetitionCount()299 int ImageSource::repetitionCount()
300 {
301 #ifdef ANDROID_ANIMATED_GIF
302 if (m_decoder.m_gifDecoder)
303 return m_decoder.m_gifDecoder->repetitionCount();
304 if (!m_decoder.m_image) return 0;
305 #endif
306 return 1;
307 // A property with value 0 means loop forever.
308 }
309
frameCount() const310 size_t ImageSource::frameCount() const
311 {
312 #ifdef ANDROID_ANIMATED_GIF
313 if (m_decoder.m_gifDecoder) {
314 return m_decoder.m_gifDecoder->failed() ? 0
315 : m_decoder.m_gifDecoder->frameCount();
316 }
317 #endif
318 // i.e. 0 frames if we're not decoded, or 1 frame if we are
319 return m_decoder.m_image != NULL;
320 }
321
createFrameAtIndex(size_t index)322 SkBitmapRef* ImageSource::createFrameAtIndex(size_t index)
323 {
324 #ifdef ANDROID_ANIMATED_GIF
325 if (m_decoder.m_gifDecoder) {
326 ImageFrame* buffer =
327 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
328 if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
329 return 0;
330 SkBitmap& bitmap = buffer->bitmap();
331 SkPixelRef* pixelRef = bitmap.pixelRef();
332 if (pixelRef)
333 pixelRef->setURI(m_decoder.m_url);
334 return new SkBitmapRef(bitmap);
335 }
336 #else
337 SkASSERT(index == 0);
338 #endif
339 SkASSERT(m_decoder.m_image != NULL);
340 m_decoder.m_image->ref();
341 return m_decoder.m_image;
342 }
343
frameDurationAtIndex(size_t index)344 float ImageSource::frameDurationAtIndex(size_t index)
345 {
346 float duration = 0;
347 #ifdef ANDROID_ANIMATED_GIF
348 if (m_decoder.m_gifDecoder) {
349 ImageFrame* buffer
350 = m_decoder.m_gifDecoder->frameBufferAtIndex(index);
351 if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
352 return 0;
353 duration = buffer->duration() / 1000.0f;
354 }
355 #else
356 SkASSERT(index == 0);
357 #endif
358
359 // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
360 // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
361 // a duration of <= 10 ms. See gfxImageFrame::GetTimeout in Gecko or Radar 4051389 for more.
362 if (duration <= 0.010f)
363 duration = 0.100f;
364 return duration;
365 }
366
frameHasAlphaAtIndex(size_t index)367 bool ImageSource::frameHasAlphaAtIndex(size_t index)
368 {
369 #ifdef ANDROID_ANIMATED_GIF
370 if (m_decoder.m_gifDecoder) {
371 ImageFrame* buffer =
372 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
373 if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
374 return false;
375
376 return buffer->hasAlpha();
377 }
378 #else
379 SkASSERT(0 == index);
380 #endif
381
382 if (NULL == m_decoder.m_image)
383 return true; // if we're not sure, assume the worse-case
384 const PrivateAndroidImageSourceRec& decoder = *m_decoder.m_image;
385 // if we're 16bit, we know even without all the data available
386 if (decoder.bitmap().getConfig() == SkBitmap::kRGB_565_Config)
387 return false;
388
389 if (!decoder.fAllDataReceived)
390 return true; // if we're not sure, assume the worse-case
391
392 return !decoder.bitmap().isOpaque();
393 }
394
frameIsCompleteAtIndex(size_t index)395 bool ImageSource::frameIsCompleteAtIndex(size_t index)
396 {
397 #ifdef ANDROID_ANIMATED_GIF
398 if (m_decoder.m_gifDecoder) {
399 ImageFrame* buffer =
400 m_decoder.m_gifDecoder->frameBufferAtIndex(index);
401 return buffer && buffer->status() == ImageFrame::FrameComplete;
402 }
403 #else
404 SkASSERT(0 == index);
405 #endif
406 return m_decoder.m_image && m_decoder.m_image->fAllDataReceived;
407 }
408
clear(bool destroyAll,size_t clearBeforeFrame,SharedBuffer * data,bool allDataReceived)409 void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
410 {
411 #ifdef ANDROID_ANIMATED_GIF
412 if (!destroyAll) {
413 if (m_decoder.m_gifDecoder)
414 m_decoder.m_gifDecoder->clearFrameBufferCache(clearBeforeFrame);
415 return;
416 }
417
418 delete m_decoder.m_gifDecoder;
419 m_decoder.m_gifDecoder = 0;
420 if (data)
421 setData(data, allDataReceived);
422 #endif
423 // do nothing, since the cache is managed elsewhere
424 }
425
frameSizeAtIndex(size_t index) const426 IntSize ImageSource::frameSizeAtIndex(size_t index) const
427 {
428 // for now, all (1) of our frames are the same size
429 return this->size();
430 }
431
filenameExtension() const432 String ImageSource::filenameExtension() const
433 {
434 // FIXME: need to add virtual to our decoders to return "jpg/png/gif/..."
435 #ifdef ANDROID_ANIMATED_GIF
436 if (m_decoder.m_gifDecoder)
437 return m_decoder.m_gifDecoder->filenameExtension();
438 #endif
439 return String();
440 }
441
getHotSpot(IntPoint &) const442 bool ImageSource::getHotSpot(IntPoint&) const
443 {
444 return false;
445 }
446
bytesDecodedToDetermineProperties() const447 size_t ImageSource::bytesDecodedToDetermineProperties() const
448 {
449 return 0;
450 }
451
452 }
453