1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkImageDecoder.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmap.h" 11f8d7d2731318cdf510ab68e6b3f5ec68ab22c8e2scroggo@google.com#include "SkImagePriv.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPixelRef.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h" 15a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org#include "SkCanvas.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkImageDecoder::SkImageDecoder() 187e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com : fPeeker(NULL) 195926b86b90c68bffefbdc8639e41b5bc9102cec6reed#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 207e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com , fChooser(NULL) 215926b86b90c68bffefbdc8639e41b5bc9102cec6reed#endif 227e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com , fAllocator(NULL) 237e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com , fSampleSize(1) 24bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed , fDefaultPref(kUnknown_SkColorType) 257e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com , fDitherImage(true) 26c3b3266b7db2f1a41d41ecac010c766b7ad8eebcreed#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG 277e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com , fUsePrefTable(false) 28c3b3266b7db2f1a41d41ecac010c766b7ad8eebcreed#endif 298d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com , fSkipWritingZeroes(false) 302bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com , fPreferQualityOverSpeed(false) 312bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com , fRequireUnpremultipliedColors(false) { 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkImageDecoder::~SkImageDecoder() { 3582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeUnref(fPeeker); 365926b86b90c68bffefbdc8639e41b5bc9102cec6reed#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 3782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeUnref(fChooser); 385926b86b90c68bffefbdc8639e41b5bc9102cec6reed#endif 3982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeUnref(fAllocator); 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 42468142b2f50de055f00d5684515d962777da5131scroggo@google.comvoid SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) { 43468142b2f50de055f00d5684515d962777da5131scroggo@google.com if (NULL == other) { 44468142b2f50de055f00d5684515d962777da5131scroggo@google.com return; 45468142b2f50de055f00d5684515d962777da5131scroggo@google.com } 46468142b2f50de055f00d5684515d962777da5131scroggo@google.com other->setPeeker(fPeeker); 475926b86b90c68bffefbdc8639e41b5bc9102cec6reed#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 48468142b2f50de055f00d5684515d962777da5131scroggo@google.com other->setChooser(fChooser); 495926b86b90c68bffefbdc8639e41b5bc9102cec6reed#endif 50468142b2f50de055f00d5684515d962777da5131scroggo@google.com other->setAllocator(fAllocator); 51468142b2f50de055f00d5684515d962777da5131scroggo@google.com other->setSampleSize(fSampleSize); 52c3b3266b7db2f1a41d41ecac010c766b7ad8eebcreed#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG 53468142b2f50de055f00d5684515d962777da5131scroggo@google.com if (fUsePrefTable) { 54468142b2f50de055f00d5684515d962777da5131scroggo@google.com other->setPrefConfigTable(fPrefTable); 55468142b2f50de055f00d5684515d962777da5131scroggo@google.com } else { 56468142b2f50de055f00d5684515d962777da5131scroggo@google.com other->fDefaultPref = fDefaultPref; 57468142b2f50de055f00d5684515d962777da5131scroggo@google.com } 58c3b3266b7db2f1a41d41ecac010c766b7ad8eebcreed#endif 598d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com other->setDitherImage(fDitherImage); 608d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com other->setSkipWritingZeroes(fSkipWritingZeroes); 61468142b2f50de055f00d5684515d962777da5131scroggo@google.com other->setPreferQualityOverSpeed(fPreferQualityOverSpeed); 62468142b2f50de055f00d5684515d962777da5131scroggo@google.com other->setRequireUnpremultipliedColors(fRequireUnpremultipliedColors); 63468142b2f50de055f00d5684515d962777da5131scroggo@google.com} 64468142b2f50de055f00d5684515d962777da5131scroggo@google.com 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkImageDecoder::Format SkImageDecoder::getFormat() const { 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return kUnknown_Format; 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 69a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.orgconst char* SkImageDecoder::getFormatName() const { 70f98118e65cbcee064bb8034f94a4faf4ea8d5536scroggo@google.com return GetFormatName(this->getFormat()); 71f98118e65cbcee064bb8034f94a4faf4ea8d5536scroggo@google.com} 72f98118e65cbcee064bb8034f94a4faf4ea8d5536scroggo@google.com 73f98118e65cbcee064bb8034f94a4faf4ea8d5536scroggo@google.comconst char* SkImageDecoder::GetFormatName(Format format) { 74f98118e65cbcee064bb8034f94a4faf4ea8d5536scroggo@google.com switch (format) { 7539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case kUnknown_Format: 7639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return "Unknown Format"; 7739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case kBMP_Format: 7839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return "BMP"; 7939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case kGIF_Format: 8039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return "GIF"; 8139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case kICO_Format: 8239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return "ICO"; 838cf81e0f4fa2a8054ac4cea1e7490028809cb893robertphillips@google.com case kPKM_Format: 848cf81e0f4fa2a8054ac4cea1e7490028809cb893robertphillips@google.com return "PKM"; 8599ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski case kKTX_Format: 8699ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski return "KTX"; 8739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case kJPEG_Format: 8839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return "JPEG"; 8939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case kPNG_Format: 9039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return "PNG"; 9139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case kWBMP_Format: 9239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return "WBMP"; 9339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case kWEBP_Format: 9439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return "WEBP"; 9539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com default: 96330313a8a8343876ee596da39da06a5d69badd9cmtklein@google.com SkDEBUGFAIL("Invalid format type!"); 9739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com } 9839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return "Unknown Format"; 99a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org} 100a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) { 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fPeeker, peeker); 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return peeker; 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1065926b86b90c68bffefbdc8639e41b5bc9102cec6reed#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) { 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fChooser, chooser); 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return chooser; 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1115926b86b90c68bffefbdc8639e41b5bc9102cec6reed#endif 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) { 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt_SafeAssign(fAllocator, alloc); 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return alloc; 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkImageDecoder::setSampleSize(int size) { 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (size < 1) { 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size = 1; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fSampleSize = size; 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1255926b86b90c68bffefbdc8639e41b5bc9102cec6reed#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 1266c22573edb234ad14df947278cfed010669a39a7reed// TODO: change Chooser virtual to take colorType, so we can stop calling SkColorTypeToBitmapConfig 1276c22573edb234ad14df947278cfed010669a39a7reed// 1286c22573edb234ad14df947278cfed010669a39a7reedbool SkImageDecoder::chooseFromOneChoice(SkColorType colorType, int width, int height) const { 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Chooser* chooser = fChooser; 1306c22573edb234ad14df947278cfed010669a39a7reed 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == chooser) { // no chooser, we just say YES to decoding :) 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com chooser->begin(1); 1356c22573edb234ad14df947278cfed010669a39a7reed chooser->inspect(0, SkColorTypeToBitmapConfig(colorType), width, height); 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return chooser->choose() == 0; 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1385926b86b90c68bffefbdc8639e41b5bc9102cec6reed#endif 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkImageDecoder::allocPixelRef(SkBitmap* bitmap, 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkColorTable* ctable) const { 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bitmap->allocPixels(fAllocator, ctable); 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 146b6137c3139b1b1da99ad9f6c28ac0d9e8f910ff6reed@android.com 147c3b3266b7db2f1a41d41ecac010c766b7ad8eebcreed#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG 148f698c8262df397a7015662e91b1a727e1134c418scroggo@google.comvoid SkImageDecoder::setPrefConfigTable(const PrefConfigTable& prefTable) { 149f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com fUsePrefTable = true; 150f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com fPrefTable = prefTable; 151f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com} 152c3b3266b7db2f1a41d41ecac010c766b7ad8eebcreed#endif 153f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com 1542f785a24eba5b59da30f5ffa0c53cc731e4c3078reed// TODO: use colortype in fPrefTable, fDefaultPref so we can stop using SkBitmapConfigToColorType() 1556c22573edb234ad14df947278cfed010669a39a7reed// 1566c22573edb234ad14df947278cfed010669a39a7reedSkColorType SkImageDecoder::getPrefColorType(SrcDepth srcDepth, bool srcHasAlpha) const { 157bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed SkColorType ct = fDefaultPref; 158c3b3266b7db2f1a41d41ecac010c766b7ad8eebcreed#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG 1593f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com 1603f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com if (fUsePrefTable) { 161bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed // Until we kill or change the PrefTable, we have to go into Config land for a moment. 162bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed SkBitmap::Config config = SkBitmap::kNo_Config; 1633f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com switch (srcDepth) { 1643f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com case kIndex_SrcDepth: 165f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com config = srcHasAlpha ? fPrefTable.fPrefFor_8Index_YesAlpha_src 166f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com : fPrefTable.fPrefFor_8Index_NoAlpha_src; 1673f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com break; 168f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com case k8BitGray_SrcDepth: 169f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com config = fPrefTable.fPrefFor_8Gray_src; 1703f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com break; 1713f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com case k32Bit_SrcDepth: 172f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com config = srcHasAlpha ? fPrefTable.fPrefFor_8bpc_YesAlpha_src 173f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com : fPrefTable.fPrefFor_8bpc_NoAlpha_src; 1743f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com break; 1753f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com } 176bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed // now return to SkColorType land 177bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed ct = SkBitmapConfigToColorType(config); 1783f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com } 179c3b3266b7db2f1a41d41ecac010c766b7ad8eebcreed#endif 180bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed return ct; 1813f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com} 1823f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com 183af1d4f84b8730781cc6dca61748cae66c237ca57Leon Scroggins IIISkImageDecoder::Result SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref, 184af1d4f84b8730781cc6dca61748cae66c237ca57Leon Scroggins III Mode mode) { 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we reset this to false before calling onDecode 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fShouldCancelDecode = false; 187bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed // assign this, for use by getPrefColorType(), in case fUsePrefTable is false 1883f1f06a26bdb2022a5c72f93ae623a57b6659464reed@android.com fDefaultPref = pref; 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 190a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org // pass a temporary bitmap, so that if we return false, we are assured of 191a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org // leaving the caller's bitmap untouched. 192af1d4f84b8730781cc6dca61748cae66c237ca57Leon Scroggins III SkBitmap tmp; 193af1d4f84b8730781cc6dca61748cae66c237ca57Leon Scroggins III const Result result = this->onDecode(stream, &tmp, mode); 194af1d4f84b8730781cc6dca61748cae66c237ca57Leon Scroggins III if (kFailure != result) { 195af1d4f84b8730781cc6dca61748cae66c237ca57Leon Scroggins III bm->swap(tmp); 19662900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 197af1d4f84b8730781cc6dca61748cae66c237ca57Leon Scroggins III return result; 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 200bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereedbool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, SkColorType pref) { 2017e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com // we reset this to false before calling onDecodeSubset 202a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org fShouldCancelDecode = false; 203bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed // assign this, for use by getPrefColorType(), in case fUsePrefTable is false 204a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org fDefaultPref = pref; 205a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org 2067e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com return this->onDecodeSubset(bm, rect); 207a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org} 208a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org 209bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereedbool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream, int *width, int *height) { 210a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org // we reset this to false before calling onBuildTileIndex 211a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org fShouldCancelDecode = false; 212a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org 213a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org return this->onBuildTileIndex(stream, width, height); 214a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org} 215a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org 2167e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.combool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, 2177e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com int dstX, int dstY, int width, int height, 2187e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com int srcX, int srcY) { 219a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org int w = width / sampleSize; 220a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org int h = height / sampleSize; 2210689d7b12e7c427a077b003d3d8ae759d86f798freed if (src->colorType() == kIndex_8_SkColorType) { 2227e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com // kIndex8 does not allow drawing via an SkCanvas, as is done below. 2237e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com // Instead, use extractSubset. Note that this shares the SkPixelRef and 2247e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com // SkColorTable. 2257e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com // FIXME: Since src is discarded in practice, this holds on to more 2267e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com // pixels than is strictly necessary. Switch to a copy if memory 2277e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com // savings are more important than speed here. This also means 2287e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com // that the pixels in dst can not be reused (though there is no 2297e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com // allocation, which was already done on src). 2307e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com int x = (dstX - srcX) / sampleSize; 2317e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com int y = (dstY - srcY) / sampleSize; 2327e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com SkIRect subset = SkIRect::MakeXYWH(x, y, w, h); 2337e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com return src->extractSubset(dst, subset); 2347e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com } 235a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org // if the destination has no pixels then we must allocate them. 236a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org if (dst->isNull()) { 2376c22573edb234ad14df947278cfed010669a39a7reed dst->setInfo(src->info().makeWH(w, h)); 238a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org 239a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org if (!this->allocPixelRef(dst, NULL)) { 240a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org SkDEBUGF(("failed to allocate pixels needed to crop the bitmap")); 2417e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com return false; 242a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org } 243a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org } 244a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org // check to see if the destination is large enough to decode the desired 245a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org // region. If this assert fails we will just draw as much of the source 246a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org // into the destination that we can. 2477e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com if (dst->width() < w || dst->height() < h) { 2487e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n")); 2497e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com } 250a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org 251a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org // Set the Src_Mode for the paint to prevent transparency issue in the 252a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org // dest in the event that the dest was being re-used. 253a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org SkPaint paint; 254a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org paint.setXfermodeMode(SkXfermode::kSrc_Mode); 255a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org 256a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org SkCanvas canvas(*dst); 257a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org canvas.drawSprite(*src, (srcX - dstX) / sampleSize, 258a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org (srcY - dstY) / sampleSize, 259a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org &paint); 2607e6fceeffd250d99eff9f1dbb459a916ae4a754escroggo@google.com return true; 261a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org} 262a936e37cc76614868f5b489395bceeb340cc04cdcommit-bot@chromium.org 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 265bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereedbool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref, Mode mode, 266bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed Format* format) { 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(file); 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bm); 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 270b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(file)); 271f381162e5616daacdbcc06d693aca5111aeeebe8mike@reedtribe.org if (stream.get()) { 272f381162e5616daacdbcc06d693aca5111aeeebe8mike@reedtribe.org if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) { 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bm->pixelRef()->setURI(file); 2741a366217cd7a9833756fe1b53c59053d6621f4bctomhudson@google.com return true; 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 280bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereedbool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref, 281bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed Mode mode, Format* format) { 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == size) { 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(buffer); 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMemoryStream stream(buffer, size); 288b3ade9d1b0a63f8f0dc3bee5785e930c8e84311dreed@android.com return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 291bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereedbool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref, 292bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed Mode mode, Format* format) { 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(stream); 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bm); 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = false; 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkImageDecoder* codec = SkImageDecoder::Factory(stream); 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != codec) { 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = codec->decode(stream, bm, pref, mode); 301b3ade9d1b0a63f8f0dc3bee5785e930c8e84311dreed@android.com if (success && format) { 302b3ade9d1b0a63f8f0dc3bee5785e930c8e84311dreed@android.com *format = codec->getFormat(); 30339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com if (kUnknown_Format == *format) { 30439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com if (stream->rewind()) { 30539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com *format = GetStreamFormat(stream); 30639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com } 30739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com } 308b3ade9d1b0a63f8f0dc3bee5785e930c8e84311dreed@android.com } 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com delete codec; 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return success; 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 313