1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9#include "SkImageDecoder.h"
10#include "SkBitmap.h"
11#include "SkImagePriv.h"
12#include "SkPixelRef.h"
13#include "SkStream.h"
14#include "SkTemplates.h"
15#include "SkCanvas.h"
16
17SkImageDecoder::SkImageDecoder()
18    : fPeeker(NULL)
19#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
20    , fChooser(NULL)
21#endif
22    , fAllocator(NULL)
23    , fSampleSize(1)
24    , fDefaultPref(kUnknown_SkColorType)
25    , fPreserveSrcDepth(false)
26    , fDitherImage(true)
27    , fSkipWritingZeroes(false)
28    , fPreferQualityOverSpeed(false)
29    , fRequireUnpremultipliedColors(false) {
30}
31
32SkImageDecoder::~SkImageDecoder() {
33    SkSafeUnref(fPeeker);
34#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
35    SkSafeUnref(fChooser);
36#endif
37    SkSafeUnref(fAllocator);
38}
39
40void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) {
41    if (NULL == other) {
42        return;
43    }
44    other->setPeeker(fPeeker);
45#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
46    other->setChooser(fChooser);
47#endif
48    other->setAllocator(fAllocator);
49    other->setSampleSize(fSampleSize);
50    other->setPreserveSrcDepth(fPreserveSrcDepth);
51    other->setDitherImage(fDitherImage);
52    other->setSkipWritingZeroes(fSkipWritingZeroes);
53    other->setPreferQualityOverSpeed(fPreferQualityOverSpeed);
54    other->setRequireUnpremultipliedColors(fRequireUnpremultipliedColors);
55}
56
57SkImageDecoder::Format SkImageDecoder::getFormat() const {
58    return kUnknown_Format;
59}
60
61const char* SkImageDecoder::getFormatName() const {
62    return GetFormatName(this->getFormat());
63}
64
65const char* SkImageDecoder::GetFormatName(Format format) {
66    switch (format) {
67        case kUnknown_Format:
68            return "Unknown Format";
69        case kBMP_Format:
70            return "BMP";
71        case kGIF_Format:
72            return "GIF";
73        case kICO_Format:
74            return "ICO";
75        case kPKM_Format:
76            return "PKM";
77        case kKTX_Format:
78            return "KTX";
79        case kASTC_Format:
80            return "ASTC";
81        case kJPEG_Format:
82            return "JPEG";
83        case kPNG_Format:
84            return "PNG";
85        case kWBMP_Format:
86            return "WBMP";
87        case kWEBP_Format:
88            return "WEBP";
89        default:
90            SkDEBUGFAIL("Invalid format type!");
91    }
92    return "Unknown Format";
93}
94
95SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
96    SkRefCnt_SafeAssign(fPeeker, peeker);
97    return peeker;
98}
99
100#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
101SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
102    SkRefCnt_SafeAssign(fChooser, chooser);
103    return chooser;
104}
105#endif
106
107SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
108    SkRefCnt_SafeAssign(fAllocator, alloc);
109    return alloc;
110}
111
112void SkImageDecoder::setSampleSize(int size) {
113    if (size < 1) {
114        size = 1;
115    }
116    fSampleSize = size;
117}
118
119#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
120// TODO: change Chooser virtual to take colorType, so we can stop calling SkColorTypeToBitmapConfig
121//
122bool SkImageDecoder::chooseFromOneChoice(SkColorType colorType, int width, int height) const {
123    Chooser* chooser = fChooser;
124
125    if (NULL == chooser) {    // no chooser, we just say YES to decoding :)
126        return true;
127    }
128    chooser->begin(1);
129    chooser->inspect(0, SkColorTypeToBitmapConfig(colorType), width, height);
130    return chooser->choose() == 0;
131}
132#endif
133
134bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
135                                   SkColorTable* ctable) const {
136    return bitmap->tryAllocPixels(fAllocator, ctable);
137}
138
139///////////////////////////////////////////////////////////////////////////////
140
141SkColorType SkImageDecoder::getPrefColorType(SrcDepth srcDepth, bool srcHasAlpha) const {
142    SkColorType ct = fDefaultPref;
143    if (fPreserveSrcDepth) {
144        switch (srcDepth) {
145            case kIndex_SrcDepth:
146                ct = kIndex_8_SkColorType;
147                break;
148            case k8BitGray_SrcDepth:
149                ct = kN32_SkColorType;
150                break;
151            case k32Bit_SrcDepth:
152                ct = kN32_SkColorType;
153                break;
154        }
155    }
156    return ct;
157}
158
159bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref, Mode mode) {
160    // we reset this to false before calling onDecode
161    fShouldCancelDecode = false;
162    // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
163    fDefaultPref = pref;
164
165    // pass a temporary bitmap, so that if we return false, we are assured of
166    // leaving the caller's bitmap untouched.
167    SkBitmap    tmp;
168    if (!this->onDecode(stream, &tmp, mode)) {
169        return false;
170    }
171    bm->swap(tmp);
172    return true;
173}
174
175bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, SkColorType pref) {
176    // we reset this to false before calling onDecodeSubset
177    fShouldCancelDecode = false;
178    // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
179    fDefaultPref = pref;
180
181    return this->onDecodeSubset(bm, rect);
182}
183
184bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
185    // we reset this to false before calling onBuildTileIndex
186    fShouldCancelDecode = false;
187
188    return this->onBuildTileIndex(stream, width, height);
189}
190
191bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
192                                int dstX, int dstY, int width, int height,
193                                int srcX, int srcY) {
194    int w = width / sampleSize;
195    int h = height / sampleSize;
196    if (src->colorType() == kIndex_8_SkColorType) {
197        // kIndex8 does not allow drawing via an SkCanvas, as is done below.
198        // Instead, use extractSubset. Note that this shares the SkPixelRef and
199        // SkColorTable.
200        // FIXME: Since src is discarded in practice, this holds on to more
201        // pixels than is strictly necessary. Switch to a copy if memory
202        // savings are more important than speed here. This also means
203        // that the pixels in dst can not be reused (though there is no
204        // allocation, which was already done on src).
205        int x = (dstX - srcX) / sampleSize;
206        int y = (dstY - srcY) / sampleSize;
207        SkIRect subset = SkIRect::MakeXYWH(x, y, w, h);
208        return src->extractSubset(dst, subset);
209    }
210    // if the destination has no pixels then we must allocate them.
211    if (dst->isNull()) {
212        dst->setInfo(src->info().makeWH(w, h));
213
214        if (!this->allocPixelRef(dst, NULL)) {
215            SkDEBUGF(("failed to allocate pixels needed to crop the bitmap"));
216            return false;
217        }
218    }
219    // check to see if the destination is large enough to decode the desired
220    // region. If this assert fails we will just draw as much of the source
221    // into the destination that we can.
222    if (dst->width() < w || dst->height() < h) {
223        SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n"));
224    }
225
226    // Set the Src_Mode for the paint to prevent transparency issue in the
227    // dest in the event that the dest was being re-used.
228    SkPaint paint;
229    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
230
231    SkCanvas canvas(*dst);
232    canvas.drawSprite(*src, (srcX - dstX) / sampleSize,
233                            (srcY - dstY) / sampleSize,
234                            &paint);
235    return true;
236}
237
238///////////////////////////////////////////////////////////////////////////////
239
240bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref,  Mode mode,
241                                Format* format) {
242    SkASSERT(file);
243    SkASSERT(bm);
244
245    SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(file));
246    if (stream.get()) {
247        if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) {
248            bm->pixelRef()->setURI(file);
249            return true;
250        }
251    }
252    return false;
253}
254
255bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref,
256                                  Mode mode, Format* format) {
257    if (0 == size) {
258        return false;
259    }
260    SkASSERT(buffer);
261
262    SkMemoryStream  stream(buffer, size);
263    return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
264}
265
266bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref,
267                                  Mode mode, Format* format) {
268    SkASSERT(stream);
269    SkASSERT(bm);
270
271    bool success = false;
272    SkImageDecoder* codec = SkImageDecoder::Factory(stream);
273
274    if (codec) {
275        success = codec->decode(stream, bm, pref, mode);
276        if (success && format) {
277            *format = codec->getFormat();
278            if (kUnknown_Format == *format) {
279                if (stream->rewind()) {
280                    *format = GetStreamFormat(stream);
281                }
282            }
283        }
284        delete codec;
285    }
286    return success;
287}
288