SkImageDecoder.cpp revision 62900b4c64401bc80ae85f6f5c87309a273cae10
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* libs/graphics/images/SkImageDecoder.cpp 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Copyright 2006, The Android Open Source Project 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 58a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Licensed under the Apache License, Version 2.0 (the "License"); 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** you may not use this file except in compliance with the License. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** You may obtain a copy of the License at 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** http://www.apache.org/licenses/LICENSE-2.0 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Unless required by applicable law or agreed to in writing, software 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** distributed under the License is distributed on an "AS IS" BASIS, 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** See the License for the specific language governing permissions and 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** limitations under the License. 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkImageDecoder.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmap.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPixelRef.h" 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h" 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config; 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap::Config SkImageDecoder::GetDeviceConfig() 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return gDeviceConfig; 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkImageDecoder::SetDeviceConfig(SkBitmap::Config config) 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gDeviceConfig = config; 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkImageDecoder::SkImageDecoder() 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fPeeker(NULL), fChooser(NULL), fAllocator(NULL), fSampleSize(1), 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDitherImage(true) { 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkImageDecoder::~SkImageDecoder() { 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPeeker->safeUnref(); 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fChooser->safeUnref(); 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAllocator->safeUnref(); 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkImageDecoder::Format SkImageDecoder::getFormat() const { 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return kUnknown_Format; 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) { 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fPeeker, peeker); 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return peeker; 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) { 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fChooser, chooser); 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return chooser; 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) { 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fAllocator, alloc); 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return alloc; 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkImageDecoder::setSampleSize(int size) { 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (size < 1) { 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size = 1; 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fSampleSize = size; 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width, 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height) const { 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Chooser* chooser = fChooser; 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == chooser) { // no chooser, we just say YES to decoding :) 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com chooser->begin(1); 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com chooser->inspect(0, config, width, height); 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return chooser->choose() == 0; 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkImageDecoder::allocPixelRef(SkBitmap* bitmap, 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkColorTable* ctable) const { 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bitmap->allocPixels(fAllocator, ctable); 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com/* Technically, this should be 342, since that is the cutoff point between 9562900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com an index and 32bit bitmap (they take equal ram), but since 32bit is almost 9662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com always faster, I bump up the value a bit. 9762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com*/ 9862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com#define MIN_SIZE_FOR_INDEX (512) 9962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com 10062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com/* Return the "optimal" config for this bitmap. In this case, we just look to 10162900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com promote index bitmaps to full-color, since those are a little faster to 10262900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com draw (fewer memory lookups). 10362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com 10462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com Seems like we could expose this to the caller through some exising or new 10562900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com proxy object, allowing them to decide (after sniffing some aspect of the 10662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com original bitmap) what config they really want. 10762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com */ 10862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.comstatic SkBitmap::Config optimal_config(const SkBitmap& bm, 10962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com SkBitmap::Config pref) { 11062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (bm.config() != pref) { 11162900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (bm.config() == SkBitmap::kIndex8_Config) { 11262900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com Sk64 size64 = bm.getSize64(); 11362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (size64.is32()) { 11462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com int32_t size = size64.get32(); 11562900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (size < MIN_SIZE_FOR_INDEX) { 11662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com return SkBitmap::kARGB_8888_Config; 11762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 11862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 11962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 12062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 12162900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com return bm.config(); 12262900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com} 12362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config pref, Mode mode) { 12662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com // pass a temporary bitmap, so that if we return false, we are assured of 12762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com // leaving the caller's bitmap untouched. 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap tmp; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we reset this to false before calling onDecode 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fShouldCancelDecode = false; 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (!this->onDecode(stream, &tmp, pref, mode)) { 13462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com return false; 13562900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 13662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com 13762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com SkBitmap::Config c = optimal_config(tmp, pref); 13862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (c != tmp.config()) { 13962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (mode == kDecodeBounds_Mode) { 14062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com tmp.setConfig(c, tmp.width(), tmp.height()); 14162900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } else { 14262900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com SkBitmap tmp2; 14362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (tmp.copyTo(&tmp2, c, this->getAllocator())) { 14462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com tmp.swap(tmp2); 14562900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 14662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com bm->swap(tmp); 14962900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com return true; 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config pref, Mode mode) { 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(file); 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bm); 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFILEStream stream(file); 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (stream.isValid()) { 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode)) { 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bm->pixelRef()->setURI(file); 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config pref, Mode mode) { 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == size) { 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(buffer); 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMemoryStream stream(buffer, size); 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkImageDecoder::DecodeStream(&stream, bm, pref, mode); 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm, 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::Config pref, Mode mode) { 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(stream); 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bm); 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = false; 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkImageDecoder* codec = SkImageDecoder::Factory(stream); 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != codec) { 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = codec->decode(stream, bm, pref, mode); 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com delete codec; 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return success; 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 195