1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/*
2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com *
4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */
7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkImageDecoder.h"
10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBitmap.h"
11de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com#include "SkImagePriv.h"
12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPixelRef.h"
13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkStream.h"
14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkTemplates.h"
152c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org#include "SkCanvas.h"
16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1786dbfc4180c99e8934ac930f87c569d5babbf838robertphillips@google.comSK_DEFINE_INST_COUNT(SkImageDecoder::Peeker)
1886dbfc4180c99e8934ac930f87c569d5babbf838robertphillips@google.comSK_DEFINE_INST_COUNT(SkImageDecoder::Chooser)
1986dbfc4180c99e8934ac930f87c569d5babbf838robertphillips@google.comSK_DEFINE_INST_COUNT(SkImageDecoderFactory)
2086dbfc4180c99e8934ac930f87c569d5babbf838robertphillips@google.com
21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkBitmap::Config SkImageDecoder::GetDeviceConfig()
24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return gDeviceConfig;
26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{
30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    gDeviceConfig = config;
31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkImageDecoder::SkImageDecoder()
369da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    : fPeeker(NULL)
379da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    , fChooser(NULL)
389da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    , fAllocator(NULL)
399da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    , fSampleSize(1)
409da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    , fDefaultPref(SkBitmap::kNo_Config)
419da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    , fDitherImage(true)
429da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    , fUsePrefTable(false)
43746b6b83a7e954f59a6c6dd44e3e8216dc11a8bbscroggo@google.com    , fPreferQualityOverSpeed(false)
44746b6b83a7e954f59a6c6dd44e3e8216dc11a8bbscroggo@google.com    , fRequireUnpremultipliedColors(false) {
45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkImageDecoder::~SkImageDecoder() {
48919114813d58933c9d9433b141e0222c34b700b1reed@google.com    SkSafeUnref(fPeeker);
49919114813d58933c9d9433b141e0222c34b700b1reed@google.com    SkSafeUnref(fChooser);
50919114813d58933c9d9433b141e0222c34b700b1reed@google.com    SkSafeUnref(fAllocator);
51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
5317179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.comvoid SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) {
5417179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    if (NULL == other) {
5517179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com        return;
5617179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    }
5717179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    other->setPeeker(fPeeker);
5817179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    other->setChooser(fChooser);
5917179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    other->setAllocator(fAllocator);
6017179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    other->setSampleSize(fSampleSize);
6117179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    if (fUsePrefTable) {
6217179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com        other->setPrefConfigTable(fPrefTable);
6317179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    } else {
6417179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com        other->fDefaultPref = fDefaultPref;
6517179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    }
6617179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    other->setPreferQualityOverSpeed(fPreferQualityOverSpeed);
6717179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com    other->setRequireUnpremultipliedColors(fRequireUnpremultipliedColors);
6817179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com}
6917179bf8349cf4f1448c0bd57539f1df66b485d9scroggo@google.com
70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkImageDecoder::Format SkImageDecoder::getFormat() const {
71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return kUnknown_Format;
72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
742c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.orgconst char* SkImageDecoder::getFormatName() const {
7561fb262531142b22406b2e6cfb62ec0ff8221733scroggo@google.com    return GetFormatName(this->getFormat());
7661fb262531142b22406b2e6cfb62ec0ff8221733scroggo@google.com}
7761fb262531142b22406b2e6cfb62ec0ff8221733scroggo@google.com
7861fb262531142b22406b2e6cfb62ec0ff8221733scroggo@google.comconst char* SkImageDecoder::GetFormatName(Format format) {
7961fb262531142b22406b2e6cfb62ec0ff8221733scroggo@google.com    switch (format) {
8006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        case kUnknown_Format:
8106a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            return "Unknown Format";
8206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        case kBMP_Format:
8306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            return "BMP";
8406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        case kGIF_Format:
8506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            return "GIF";
8606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        case kICO_Format:
8706a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            return "ICO";
8806a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        case kJPEG_Format:
8906a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            return "JPEG";
9006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        case kPNG_Format:
9106a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            return "PNG";
9206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        case kWBMP_Format:
9306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            return "WBMP";
9406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        case kWEBP_Format:
9506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            return "WEBP";
9606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        default:
9706a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            SkASSERT(!"Invalid format type!");
9806a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    }
9906a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    return "Unknown Format";
1002c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org}
1012c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org
102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRefCnt_SafeAssign(fPeeker, peeker);
104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return peeker;
105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRefCnt_SafeAssign(fChooser, chooser);
109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return chooser;
110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRefCnt_SafeAssign(fAllocator, alloc);
114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return alloc;
115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkImageDecoder::setSampleSize(int size) {
118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (size < 1) {
119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        size = 1;
120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fSampleSize = size;
122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                                         int height) const {
126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Chooser* chooser = fChooser;
127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (NULL == chooser) {    // no chooser, we just say YES to decoding :)
129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return true;
130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    chooser->begin(1);
132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    chooser->inspect(0, config, width, height);
133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return chooser->choose() == 0;
134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                                   SkColorTable* ctable) const {
138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return bitmap->allocPixels(fAllocator, ctable);
139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
142226ab004e724ca97fc0c567479b327379695092dreed@android.com
143dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.comvoid SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) {
144dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    if (NULL == pref) {
145dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com        fUsePrefTable = false;
146dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    } else {
147dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com        fUsePrefTable = true;
1488a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com        fPrefTable.fPrefFor_8Index_NoAlpha_src = pref[0];
1498a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com        fPrefTable.fPrefFor_8Index_YesAlpha_src = pref[1];
1508a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com        fPrefTable.fPrefFor_8Gray_src = SkBitmap::kNo_Config;
1518a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com        fPrefTable.fPrefFor_8bpc_NoAlpha_src = pref[4];
1528a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com        fPrefTable.fPrefFor_8bpc_YesAlpha_src = pref[5];
153dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    }
154dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com}
155dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com
1568a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.comvoid SkImageDecoder::setPrefConfigTable(const PrefConfigTable& prefTable) {
1578a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com    fUsePrefTable = true;
1588a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com    fPrefTable = prefTable;
1598a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com}
1608a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com
161dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.comSkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
162dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com                                               bool srcHasAlpha) const {
1638463824b653f020a0f735c56dcfb39101c6c6ca9scroggo@google.com    SkBitmap::Config config = SkBitmap::kNo_Config;
164dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com
165dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    if (fUsePrefTable) {
166dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com        switch (srcDepth) {
167dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com            case kIndex_SrcDepth:
1688a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com                config = srcHasAlpha ? fPrefTable.fPrefFor_8Index_YesAlpha_src
1698a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com                                     : fPrefTable.fPrefFor_8Index_NoAlpha_src;
170dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com                break;
1718a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com            case k8BitGray_SrcDepth:
1728a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com                config = fPrefTable.fPrefFor_8Gray_src;
173dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com                break;
174dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com            case k32Bit_SrcDepth:
1758a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com                config = srcHasAlpha ? fPrefTable.fPrefFor_8bpc_YesAlpha_src
1768a37728d5c4445408c2f343f90807cc7f50d4d6escroggo@google.com                                     : fPrefTable.fPrefFor_8bpc_NoAlpha_src;
177dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com                break;
178dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com        }
179dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    } else {
180dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com        config = fDefaultPref;
181dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    }
182dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com
183dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    if (SkBitmap::kNo_Config == config) {
184dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com        config = SkImageDecoder::GetDeviceConfig();
185dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    }
186dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    return config;
187dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com}
188dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com
189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
190a80d3ddc590d6b5bd1893836f8aca89412267c39scroggo@google.com                            SkBitmap::Config pref, Mode mode) {
191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // we reset this to false before calling onDecode
192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fShouldCancelDecode = false;
193dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
194dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    fDefaultPref = pref;
195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1962c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    // pass a temporary bitmap, so that if we return false, we are assured of
1972c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    // leaving the caller's bitmap untouched.
1982c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    SkBitmap    tmp;
199dcfc89cccfe82f8099ef32170d352edba9778b0freed@android.com    if (!this->onDecode(stream, &tmp, mode)) {
200efc74b8af0ee522065266db255e9bc48c8ceaceereed@android.com        return false;
201efc74b8af0ee522065266db255e9bc48c8ceaceereed@android.com    }
202efc74b8af0ee522065266db255e9bc48c8ceaceereed@android.com    bm->swap(tmp);
203efc74b8af0ee522065266db255e9bc48c8ceaceereed@android.com    return true;
204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
2069da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.combool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect,
2072c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org                                  SkBitmap::Config pref) {
2089da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    // we reset this to false before calling onDecodeSubset
2092c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    fShouldCancelDecode = false;
2102c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
2112c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    fDefaultPref = pref;
2122c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org
2139da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    return this->onDecodeSubset(bm, rect);
2142c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org}
2152c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org
2162c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.orgbool SkImageDecoder::buildTileIndex(SkStream* stream,
2172c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org                                int *width, int *height) {
2182c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    // we reset this to false before calling onBuildTileIndex
2192c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    fShouldCancelDecode = false;
2202c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org
2212c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    return this->onBuildTileIndex(stream, width, height);
2222c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org}
2232c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org
2249da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.combool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
2259da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com                                int dstX, int dstY, int width, int height,
2269da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com                                int srcX, int srcY) {
2272c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    int w = width / sampleSize;
2282c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    int h = height / sampleSize;
2299da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    if (src->getConfig() == SkBitmap::kIndex8_Config) {
2309da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        // kIndex8 does not allow drawing via an SkCanvas, as is done below.
2319da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        // Instead, use extractSubset. Note that this shares the SkPixelRef and
2329da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        // SkColorTable.
2339da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        // FIXME: Since src is discarded in practice, this holds on to more
2349da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        // pixels than is strictly necessary. Switch to a copy if memory
2359da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        // savings are more important than speed here. This also means
2369da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        // that the pixels in dst can not be reused (though there is no
2379da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        // allocation, which was already done on src).
2389da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        int x = (dstX - srcX) / sampleSize;
2399da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        int y = (dstY - srcY) / sampleSize;
2409da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        SkIRect subset = SkIRect::MakeXYWH(x, y, w, h);
2419da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        return src->extractSubset(dst, subset);
2429da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    }
2432c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    // if the destination has no pixels then we must allocate them.
2442c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    if (dst->isNull()) {
2452c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org        dst->setConfig(src->getConfig(), w, h);
2462c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org        dst->setIsOpaque(src->isOpaque());
2472c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org
2482c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org        if (!this->allocPixelRef(dst, NULL)) {
2492c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org            SkDEBUGF(("failed to allocate pixels needed to crop the bitmap"));
2509da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com            return false;
2512c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org        }
2522c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    }
2532c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    // check to see if the destination is large enough to decode the desired
2542c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    // region. If this assert fails we will just draw as much of the source
2552c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    // into the destination that we can.
2569da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    if (dst->width() < w || dst->height() < h) {
2579da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com        SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n"));
2589da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    }
2592c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org
2602c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    // Set the Src_Mode for the paint to prevent transparency issue in the
2612c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    // dest in the event that the dest was being re-used.
2622c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    SkPaint paint;
2632c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
2642c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org
2652c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    SkCanvas canvas(*dst);
2662c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org    canvas.drawSprite(*src, (srcX - dstX) / sampleSize,
2672c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org                            (srcY - dstY) / sampleSize,
2682c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org                            &paint);
2699da03b7e9819927e7d247aec2bab591e4a3addb7scroggo@google.com    return true;
2702c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org}
2712c5e316d42796d958b5656410fcb2cd0218b785ecommit-bot@chromium.org
272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
275664ff1bdb098df3b56e398f74af63519fa756fdcreed@android.com                            SkBitmap::Config pref,  Mode mode, Format* format) {
276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(file);
277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(bm);
278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
279772e57c160af54b9143c131f6fb9e50f7034a54dmike@reedtribe.org    SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(file));
280772e57c160af54b9143c131f6fb9e50f7034a54dmike@reedtribe.org    if (stream.get()) {
281772e57c160af54b9143c131f6fb9e50f7034a54dmike@reedtribe.org        if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) {
282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            bm->pixelRef()->setURI(file);
2830ade2b116178656f2f0ca3cfafa05b76ad19703ctomhudson@google.com            return true;
284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return false;
287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
290664ff1bdb098df3b56e398f74af63519fa756fdcreed@android.com                          SkBitmap::Config pref, Mode mode, Format* format) {
291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (0 == size) {
292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return false;
293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(buffer);
295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkMemoryStream  stream(buffer, size);
297664ff1bdb098df3b56e398f74af63519fa756fdcreed@android.com    return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
30082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com/**
30182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  Special allocator used by DecodeMemoryToTarget. Uses preallocated memory
30282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  provided if the bm is 8888. Otherwise, uses a heap allocator. The same
30382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  allocator will be used again for a copy to 8888, when the preallocated
30482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  memory will be used.
30582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com */
30682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.comclass TargetAllocator : public SkBitmap::HeapAllocator {
307de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com
308de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.compublic:
309de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    TargetAllocator(void* target)
310de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com        : fTarget(target) {}
311de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com
312de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
31382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        // If the config is not 8888, allocate a pixelref using the heap.
31482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        // fTarget will be used to store the final pixels when copied to
31582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        // 8888.
31682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        if (bm->config() != SkBitmap::kARGB_8888_Config) {
31782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com            return INHERITED::allocPixelRef(bm, ct);
31882b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        }
31982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        // In kARGB_8888_Config, there is no colortable.
320de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com        SkASSERT(NULL == ct);
321de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com        bm->setPixels(fTarget);
322de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com        return true;
323de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    }
324de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com
325de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.comprivate:
326de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    void* fTarget;
32782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    typedef SkBitmap::HeapAllocator INHERITED;
328de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com};
329de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com
33082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com/**
33182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  Helper function for DecodeMemoryToTarget. DecodeMemoryToTarget wants
33282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  8888, so set the config to it. All parameters must not be null.
33382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  @param decoder Decoder appropriate for this stream.
33482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  @param stream Rewound stream to the encoded data.
33582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  @param bitmap On success, will have its bounds set to the bounds of the
33682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *      encoded data, and its config set to 8888.
33782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  @return True if the bounds were decoded and the bitmap is 8888 or can be
33882b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *      copied to 8888.
33982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com */
34082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.comstatic bool decode_bounds_to_8888(SkImageDecoder* decoder, SkStream* stream,
34182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com                                  SkBitmap* bitmap) {
34282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkASSERT(decoder != NULL);
34382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkASSERT(stream != NULL);
34482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkASSERT(bitmap != NULL);
34582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
34682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    if (!decoder->decode(stream, bitmap, SkImageDecoder::kDecodeBounds_Mode)) {
34782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        return false;
34882b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    }
34982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
35082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    if (bitmap->config() == SkBitmap::kARGB_8888_Config) {
35182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        return true;
35282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    }
35382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
35482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    if (!bitmap->canCopyTo(SkBitmap::kARGB_8888_Config)) {
35582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        return false;
35682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    }
35782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
35882b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    bitmap->setConfig(SkBitmap::kARGB_8888_Config, bitmap->width(), bitmap->height());
35982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    return true;
36082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com}
36182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
36282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com/**
36382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  Helper function for DecodeMemoryToTarget. Decodes the stream into bitmap, and if
36482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  the bitmap is not 8888, then it is copied to 8888. Either way, the end result has
36582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  its pixels stored in target. All parameters must not be null.
36682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  @param decoder Decoder appropriate for this stream.
36782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  @param stream Rewound stream to the encoded data.
36882b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  @param bitmap On success, will contain the decoded image, with its pixels stored
36982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *      at target.
37082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  @param target Preallocated memory for storing pixels.
37182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com *  @return bool Whether the decode (and copy, if necessary) succeeded.
37282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com */
37382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.comstatic bool decode_pixels_to_8888(SkImageDecoder* decoder, SkStream* stream,
37482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com                                  SkBitmap* bitmap, void* target) {
37582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkASSERT(decoder != NULL);
37682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkASSERT(stream != NULL);
37782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkASSERT(bitmap != NULL);
37882b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkASSERT(target != NULL);
37982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
38082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    TargetAllocator allocator(target);
38182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    decoder->setAllocator(&allocator);
38282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
38382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    bool success = decoder->decode(stream, bitmap, SkImageDecoder::kDecodePixels_Mode);
38482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    decoder->setAllocator(NULL);
38582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
38682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    if (!success) {
38782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        return false;
38882b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    }
38982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
39082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    if (bitmap->config() == SkBitmap::kARGB_8888_Config) {
39182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        return true;
39282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    }
39382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
39482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkBitmap bm8888;
39582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    if (!bitmap->copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator)) {
39682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        return false;
39782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    }
39882b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
39982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    bitmap->swap(bm8888);
40082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    return true;
40182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com}
40282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
403de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.combool SkImageDecoder::DecodeMemoryToTarget(const void* buffer, size_t size,
404de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com                                          SkImage::Info* info,
405de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com                                          const SkBitmapFactory::Target* target) {
406de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    if (NULL == info) {
407de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com        return false;
408de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    }
40982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
410de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    // FIXME: Just to get this working, implement in terms of existing
411de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    // ImageDecoder calls.
412de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    SkBitmap bm;
413de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    SkMemoryStream stream(buffer, size);
414de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
41582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    if (NULL == decoder.get()) {
41682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        return false;
41782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    }
418de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com
41982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    if (!decode_bounds_to_8888(decoder.get(), &stream, &bm)) {
42082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        return false;
42182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    }
422de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com
42382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkASSERT(bm.config() == SkBitmap::kARGB_8888_Config);
424de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com
42582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    // Now set info properly.
42682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    // Since Config is SkBitmap::kARGB_8888_Config, SkBitmapToImageInfo
42782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    // will always succeed.
42882b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkAssertResult(SkBitmapToImageInfo(bm, info));
42982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
43082b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    if (NULL == target) {
43182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        return true;
43282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    }
433de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com
43482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    if (target->fRowBytes != SkToU32(bm.rowBytes())) {
43582b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        if (target->fRowBytes < SkImageMinRowBytes(*info)) {
43682b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com            SkASSERT(!"Desired row bytes is too small");
43782b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com            return false;
43882b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        }
43982b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com        bm.setConfig(bm.config(), bm.width(), bm.height(), target->fRowBytes);
440de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com    }
44182b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com
44282b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    // SkMemoryStream.rewind() will always return true.
44382b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    SkAssertResult(stream.rewind());
44482b9077620425e33e17e96bf5a15f36929eb8436scroggo@google.com    return decode_pixels_to_8888(decoder.get(), &stream, &bm, target->fAddr);
445de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com}
446de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com
447de5698ff718963fd47fbb9d100ab51af35247bb6scroggo@google.com
448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm,
449664ff1bdb098df3b56e398f74af63519fa756fdcreed@android.com                          SkBitmap::Config pref, Mode mode, Format* format) {
450bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(stream);
451bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(bm);
452bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
453bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bool success = false;
454bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkImageDecoder* codec = SkImageDecoder::Factory(stream);
455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
456bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (NULL != codec) {
457bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        success = codec->decode(stream, bm, pref, mode);
458664ff1bdb098df3b56e398f74af63519fa756fdcreed@android.com        if (success && format) {
459664ff1bdb098df3b56e398f74af63519fa756fdcreed@android.com            *format = codec->getFormat();
46006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            if (kUnknown_Format == *format) {
46106a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com                if (stream->rewind()) {
46206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com                    *format = GetStreamFormat(stream);
46306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com                }
46406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            }
465664ff1bdb098df3b56e398f74af63519fa756fdcreed@android.com        }
466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        delete codec;
467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
468bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return success;
469bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
470