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