2 * Copyright 2006 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "SkImageDecoder.h"
11 #include "SkImagePriv.h"
12 #include "SkPixelRef.h"
14 #include "SkTemplates.h"
17 SkImageDecoder::SkImageDecoder()
19 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
24 , fDefaultPref(kUnknown_SkColorType)
25 , fPreserveSrcDepth(false)
27 , fSkipWritingZeroes(false)
28 , fPreferQualityOverSpeed(false)
29 , fRequireUnpremultipliedColors(false) {
32 SkImageDecoder::~SkImageDecoder() {
34 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
35 SkSafeUnref(fChooser);
37 SkSafeUnref(fAllocator);
40 void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) {
44 other->setPeeker(fPeeker);
45 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
46 other->setChooser(fChooser);
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);
57 SkImageDecoder::Format SkImageDecoder::getFormat() const {
58 return kUnknown_Format;
61 const char* SkImageDecoder::getFormatName() const {
62 return GetFormatName(this->getFormat());
65 const char* SkImageDecoder::GetFormatName(Format format) {
68 return "Unknown Format";
90 SkDEBUGFAIL("Invalid format type!");
92 return "Unknown Format";
95 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
96 SkRefCnt_SafeAssign(fPeeker, peeker);
100 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
101 SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
102 SkRefCnt_SafeAssign(fChooser, chooser);
107 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
108 SkRefCnt_SafeAssign(fAllocator, alloc);
112 void SkImageDecoder::setSampleSize(int size) {
119 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
120 // TODO: change Chooser virtual to take colorType, so we can stop calling SkColorTypeToBitmapConfig
122 bool SkImageDecoder::chooseFromOneChoice(SkColorType colorType, int width, int height) const {
123 Chooser* chooser = fChooser;
125 if (NULL == chooser) { // no chooser, we just say YES to decoding :)
129 chooser->inspect(0, SkColorTypeToBitmapConfig(colorType), width, height);
130 return chooser->choose() == 0;
134 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
135 SkColorTable* ctable) const {
136 return bitmap->tryAllocPixels(fAllocator, ctable);
139 ///////////////////////////////////////////////////////////////////////////////
141 SkColorType SkImageDecoder::getPrefColorType(SrcDepth srcDepth, bool srcHasAlpha) const {
142 SkColorType ct = fDefaultPref;
143 if (fPreserveSrcDepth) {
145 case kIndex_SrcDepth:
146 ct = kIndex_8_SkColorType;
148 case k8BitGray_SrcDepth:
149 ct = kN32_SkColorType;
151 case k32Bit_SrcDepth:
152 ct = kN32_SkColorType;
159 SkImageDecoder::Result SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref,
161 // we reset this to false before calling onDecode
162 fShouldCancelDecode = false;
163 // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
166 // pass a temporary bitmap, so that if we return false, we are assured of
167 // leaving the caller's bitmap untouched.
169 const Result result = this->onDecode(stream, &tmp, mode);
170 if (kFailure != result) {
176 bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, SkColorType pref) {
177 // we reset this to false before calling onDecodeSubset
178 fShouldCancelDecode = false;
179 // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
182 return this->onDecodeSubset(bm, rect);
185 bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
186 // we reset this to false before calling onBuildTileIndex
187 fShouldCancelDecode = false;
189 return this->onBuildTileIndex(stream, width, height);
192 bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
193 int dstX, int dstY, int width, int height,
194 int srcX, int srcY) {
195 int w = width / sampleSize;
196 int h = height / sampleSize;
197 if (src->colorType() == kIndex_8_SkColorType) {
198 // kIndex8 does not allow drawing via an SkCanvas, as is done below.
199 // Instead, use extractSubset. Note that this shares the SkPixelRef and
201 // FIXME: Since src is discarded in practice, this holds on to more
202 // pixels than is strictly necessary. Switch to a copy if memory
203 // savings are more important than speed here. This also means
204 // that the pixels in dst can not be reused (though there is no
205 // allocation, which was already done on src).
206 int x = (dstX - srcX) / sampleSize;
207 int y = (dstY - srcY) / sampleSize;
208 SkIRect subset = SkIRect::MakeXYWH(x, y, w, h);
209 return src->extractSubset(dst, subset);
211 // if the destination has no pixels then we must allocate them.
213 dst->setInfo(src->info().makeWH(w, h));
215 if (!this->allocPixelRef(dst, NULL)) {
216 SkDEBUGF(("failed to allocate pixels needed to crop the bitmap"));
220 // check to see if the destination is large enough to decode the desired
221 // region. If this assert fails we will just draw as much of the source
222 // into the destination that we can.
223 if (dst->width() < w || dst->height() < h) {
224 SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n"));
227 // Set the Src_Mode for the paint to prevent transparency issue in the
228 // dest in the event that the dest was being re-used.
230 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
232 SkCanvas canvas(*dst);
233 canvas.drawSprite(*src, (srcX - dstX) / sampleSize,
234 (srcY - dstY) / sampleSize,
239 ///////////////////////////////////////////////////////////////////////////////
241 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref, Mode mode,
246 SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(file));
248 if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) {
249 bm->pixelRef()->setURI(file);
256 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref,
257 Mode mode, Format* format) {
263 SkMemoryStream stream(buffer, size);
264 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
267 bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref,
268 Mode mode, Format* format) {
272 bool success = false;
273 SkImageDecoder* codec = SkImageDecoder::Factory(stream);
276 success = codec->decode(stream, bm, pref, mode) != kFailure;
277 if (success && format) {
278 *format = codec->getFormat();
279 if (kUnknown_Format == *format) {
280 if (stream->rewind()) {
281 *format = GetStreamFormat(stream);
290 bool SkImageDecoder::decodeYUV8Planes(SkStream* stream, SkISize componentSizes[3], void* planes[3],
291 size_t rowBytes[3], SkYUVColorSpace* colorSpace) {
292 // we reset this to false before calling onDecodeYUV8Planes
293 fShouldCancelDecode = false;
295 return this->onDecodeYUV8Planes(stream, componentSizes, planes, rowBytes, colorSpace);