blob: 221faf74d5e33cf0160e765c3887c69a7e7b3a45 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00008
9#include "SkImageDecoder.h"
10#include "SkBitmap.h"
scroggo@google.comf8d7d272013-02-22 21:38:35 +000011#include "SkImagePriv.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000012#include "SkPixelRef.h"
13#include "SkStream.h"
14#include "SkTemplates.h"
commit-bot@chromium.orga936e372013-03-14 14:42:18 +000015#include "SkCanvas.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000016
reed@android.com8a1c16f2008-12-17 15:59:43 +000017SkImageDecoder::SkImageDecoder()
halcanary96fcdcc2015-08-27 07:41:13 -070018 : fPeeker(nullptr)
19 , fAllocator(nullptr)
scroggo@google.com7e6fcee2013-05-03 20:14:28 +000020 , fSampleSize(1)
reedbfefc7c2014-06-12 17:40:00 -070021 , fDefaultPref(kUnknown_SkColorType)
reedbe08ace2014-07-08 11:15:59 -070022 , fPreserveSrcDepth(false)
scroggo@google.com7e6fcee2013-05-03 20:14:28 +000023 , fDitherImage(true)
scroggo@google.com8d239242013-10-01 17:27:15 +000024 , fSkipWritingZeroes(false)
scroggo@google.com2bbc2c92013-06-14 15:33:20 +000025 , fPreferQualityOverSpeed(false)
26 , fRequireUnpremultipliedColors(false) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000027}
28
29SkImageDecoder::~SkImageDecoder() {
reed@google.com82065d62011-02-07 15:30:46 +000030 SkSafeUnref(fPeeker);
reed@google.com82065d62011-02-07 15:30:46 +000031 SkSafeUnref(fAllocator);
reed@android.com8a1c16f2008-12-17 15:59:43 +000032}
33
scroggo@google.com468142b2013-07-09 15:48:24 +000034void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) {
halcanary96fcdcc2015-08-27 07:41:13 -070035 if (nullptr == other) {
scroggo@google.com468142b2013-07-09 15:48:24 +000036 return;
37 }
38 other->setPeeker(fPeeker);
scroggo@google.com468142b2013-07-09 15:48:24 +000039 other->setAllocator(fAllocator);
40 other->setSampleSize(fSampleSize);
reedbe08ace2014-07-08 11:15:59 -070041 other->setPreserveSrcDepth(fPreserveSrcDepth);
scroggo@google.com8d239242013-10-01 17:27:15 +000042 other->setDitherImage(fDitherImage);
43 other->setSkipWritingZeroes(fSkipWritingZeroes);
scroggo@google.com468142b2013-07-09 15:48:24 +000044 other->setPreferQualityOverSpeed(fPreferQualityOverSpeed);
45 other->setRequireUnpremultipliedColors(fRequireUnpremultipliedColors);
46}
47
reed@android.com8a1c16f2008-12-17 15:59:43 +000048SkImageDecoder::Format SkImageDecoder::getFormat() const {
49 return kUnknown_Format;
50}
51
commit-bot@chromium.orga936e372013-03-14 14:42:18 +000052const char* SkImageDecoder::getFormatName() const {
scroggo@google.comf98118e2013-05-15 14:53:49 +000053 return GetFormatName(this->getFormat());
54}
55
56const char* SkImageDecoder::GetFormatName(Format format) {
57 switch (format) {
scroggo@google.com39edf4c2013-04-25 17:33:51 +000058 case kUnknown_Format:
59 return "Unknown Format";
60 case kBMP_Format:
61 return "BMP";
62 case kGIF_Format:
63 return "GIF";
64 case kICO_Format:
65 return "ICO";
robertphillips@google.com8cf81e02014-05-22 18:40:29 +000066 case kPKM_Format:
67 return "PKM";
krajcevski99ffe242014-06-03 13:04:35 -070068 case kKTX_Format:
69 return "KTX";
krajcevski95b1b3d2014-08-07 12:58:38 -070070 case kASTC_Format:
71 return "ASTC";
scroggo@google.com39edf4c2013-04-25 17:33:51 +000072 case kJPEG_Format:
73 return "JPEG";
74 case kPNG_Format:
75 return "PNG";
76 case kWBMP_Format:
77 return "WBMP";
78 case kWEBP_Format:
79 return "WEBP";
80 default:
mtklein@google.com330313a2013-08-22 15:37:26 +000081 SkDEBUGFAIL("Invalid format type!");
scroggo@google.com39edf4c2013-04-25 17:33:51 +000082 }
83 return "Unknown Format";
commit-bot@chromium.orga936e372013-03-14 14:42:18 +000084}
85
scroggocf98fa92015-11-23 08:14:40 -080086SkPngChunkReader* SkImageDecoder::setPeeker(SkPngChunkReader* peeker) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000087 SkRefCnt_SafeAssign(fPeeker, peeker);
88 return peeker;
89}
90
reed@android.com8a1c16f2008-12-17 15:59:43 +000091SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
92 SkRefCnt_SafeAssign(fAllocator, alloc);
93 return alloc;
94}
95
96void SkImageDecoder::setSampleSize(int size) {
97 if (size < 1) {
98 size = 1;
99 }
100 fSampleSize = size;
101}
102
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
104 SkColorTable* ctable) const {
reed84825042014-09-02 12:50:45 -0700105 return bitmap->tryAllocPixels(fAllocator, ctable);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000106}
107
108///////////////////////////////////////////////////////////////////////////////
reed@android.comb6137c32009-07-29 20:56:52 +0000109
reed6c225732014-06-09 19:52:07 -0700110SkColorType SkImageDecoder::getPrefColorType(SrcDepth srcDepth, bool srcHasAlpha) const {
reedbfefc7c2014-06-12 17:40:00 -0700111 SkColorType ct = fDefaultPref;
reedbe08ace2014-07-08 11:15:59 -0700112 if (fPreserveSrcDepth) {
113 switch (srcDepth) {
114 case kIndex_SrcDepth:
115 ct = kIndex_8_SkColorType;
116 break;
117 case k8BitGray_SrcDepth:
118 ct = kN32_SkColorType;
119 break;
120 case k32Bit_SrcDepth:
121 ct = kN32_SkColorType;
122 break;
123 }
124 }
reedbfefc7c2014-06-12 17:40:00 -0700125 return ct;
reed@android.com3f1f06a2010-03-03 21:04:12 +0000126}
127
scroggo2a120802014-10-22 12:07:00 -0700128SkImageDecoder::Result SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref,
129 Mode mode) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130 // we reset this to false before calling onDecode
131 fShouldCancelDecode = false;
reedbfefc7c2014-06-12 17:40:00 -0700132 // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
reed@android.com3f1f06a2010-03-03 21:04:12 +0000133 fDefaultPref = pref;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134
commit-bot@chromium.orga936e372013-03-14 14:42:18 +0000135 // pass a temporary bitmap, so that if we return false, we are assured of
136 // leaving the caller's bitmap untouched.
scroggo2a120802014-10-22 12:07:00 -0700137 SkBitmap tmp;
138 const Result result = this->onDecode(stream, &tmp, mode);
139 if (kFailure != result) {
140 bm->swap(tmp);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000141 }
scroggo2a120802014-10-22 12:07:00 -0700142 return result;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143}
144
145///////////////////////////////////////////////////////////////////////////////
146
reedbfefc7c2014-06-12 17:40:00 -0700147bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref, Mode mode,
148 Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149 SkASSERT(file);
150 SkASSERT(bm);
151
scroggoa1193e42015-01-21 12:09:53 -0800152 SkAutoTDelete<SkStreamRewindable> stream(SkStream::NewFromFile(file));
mike@reedtribe.orgf3811622013-03-19 02:18:33 +0000153 if (stream.get()) {
154 if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) {
reeddedc2d82015-03-16 07:28:12 -0700155 if (SkPixelRef* pr = bm->pixelRef()) {
156 pr->setURI(file);
157 }
tomhudson@google.com1a366212012-01-03 14:42:08 +0000158 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000159 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160 }
161 return false;
162}
163
reedbfefc7c2014-06-12 17:40:00 -0700164bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref,
165 Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000166 if (0 == size) {
167 return false;
168 }
169 SkASSERT(buffer);
170
171 SkMemoryStream stream(buffer, size);
reed@android.comb3ade9d2009-06-15 13:04:45 +0000172 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000173}
174
reedbfefc7c2014-06-12 17:40:00 -0700175bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref,
176 Mode mode, Format* format) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000177 SkASSERT(stream);
178 SkASSERT(bm);
179
180 bool success = false;
181 SkImageDecoder* codec = SkImageDecoder::Factory(stream);
182
bsalomon49f085d2014-09-05 13:34:00 -0700183 if (codec) {
scroggo2a120802014-10-22 12:07:00 -0700184 success = codec->decode(stream, bm, pref, mode) != kFailure;
reed@android.comb3ade9d2009-06-15 13:04:45 +0000185 if (success && format) {
186 *format = codec->getFormat();
scroggo@google.com39edf4c2013-04-25 17:33:51 +0000187 if (kUnknown_Format == *format) {
188 if (stream->rewind()) {
189 *format = GetStreamFormat(stream);
190 }
191 }
reed@android.comb3ade9d2009-06-15 13:04:45 +0000192 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000193 delete codec;
194 }
195 return success;
196}
sugoib227e372014-10-16 13:10:57 -0700197
198bool SkImageDecoder::decodeYUV8Planes(SkStream* stream, SkISize componentSizes[3], void* planes[3],
199 size_t rowBytes[3], SkYUVColorSpace* colorSpace) {
200 // we reset this to false before calling onDecodeYUV8Planes
201 fShouldCancelDecode = false;
202
203 return this->onDecodeYUV8Planes(stream, componentSizes, planes, rowBytes, colorSpace);
204}