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(nullptr) 19 , fAllocator(nullptr) 20 , fSampleSize(1) 21 , fDefaultPref(kUnknown_SkColorType) 22 , fPreserveSrcDepth(false) 23 , fDitherImage(true) 24 , fSkipWritingZeroes(false) 25 , fPreferQualityOverSpeed(false) 26 , fRequireUnpremultipliedColors(false) { 27} 28 29SkImageDecoder::~SkImageDecoder() { 30 SkSafeUnref(fPeeker); 31 SkSafeUnref(fAllocator); 32} 33 34void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) { 35 if (nullptr == other) { 36 return; 37 } 38 other->setPeeker(fPeeker); 39 other->setAllocator(fAllocator); 40 other->setSampleSize(fSampleSize); 41 other->setPreserveSrcDepth(fPreserveSrcDepth); 42 other->setDitherImage(fDitherImage); 43 other->setSkipWritingZeroes(fSkipWritingZeroes); 44 other->setPreferQualityOverSpeed(fPreferQualityOverSpeed); 45 other->setRequireUnpremultipliedColors(fRequireUnpremultipliedColors); 46} 47 48SkImageDecoder::Format SkImageDecoder::getFormat() const { 49 return kUnknown_Format; 50} 51 52const char* SkImageDecoder::getFormatName() const { 53 return GetFormatName(this->getFormat()); 54} 55 56const char* SkImageDecoder::GetFormatName(Format format) { 57 switch (format) { 58 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"; 66 case kPKM_Format: 67 return "PKM"; 68 case kKTX_Format: 69 return "KTX"; 70 case kASTC_Format: 71 return "ASTC"; 72 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: 81 SkDEBUGFAIL("Invalid format type!"); 82 } 83 return "Unknown Format"; 84} 85 86SkPngChunkReader* SkImageDecoder::setPeeker(SkPngChunkReader* peeker) { 87 SkRefCnt_SafeAssign(fPeeker, peeker); 88 return peeker; 89} 90 91SkBitmap::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 103bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap, 104 SkColorTable* ctable) const { 105 return bitmap->tryAllocPixels(fAllocator, ctable); 106} 107 108/////////////////////////////////////////////////////////////////////////////// 109 110SkColorType SkImageDecoder::getPrefColorType(SrcDepth srcDepth, bool srcHasAlpha) const { 111 SkColorType ct = fDefaultPref; 112 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 } 125 return ct; 126} 127 128SkImageDecoder::Result SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref, 129 Mode mode) { 130 // we reset this to false before calling onDecode 131 fShouldCancelDecode = false; 132 // assign this, for use by getPrefColorType(), in case fUsePrefTable is false 133 fDefaultPref = pref; 134 135 // pass a temporary bitmap, so that if we return false, we are assured of 136 // leaving the caller's bitmap untouched. 137 SkBitmap tmp; 138 const Result result = this->onDecode(stream, &tmp, mode); 139 if (kFailure != result) { 140 bm->swap(tmp); 141 } 142 return result; 143} 144 145/////////////////////////////////////////////////////////////////////////////// 146 147bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref, Mode mode, 148 Format* format) { 149 SkASSERT(file); 150 SkASSERT(bm); 151 152 SkAutoTDelete<SkStreamRewindable> stream(SkStream::NewFromFile(file)); 153 if (stream.get()) { 154 if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) { 155 if (SkPixelRef* pr = bm->pixelRef()) { 156 pr->setURI(file); 157 } 158 return true; 159 } 160 } 161 return false; 162} 163 164bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref, 165 Mode mode, Format* format) { 166 if (0 == size) { 167 return false; 168 } 169 SkASSERT(buffer); 170 171 SkMemoryStream stream(buffer, size); 172 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); 173} 174 175bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref, 176 Mode mode, Format* format) { 177 SkASSERT(stream); 178 SkASSERT(bm); 179 180 bool success = false; 181 SkImageDecoder* codec = SkImageDecoder::Factory(stream); 182 183 if (codec) { 184 success = codec->decode(stream, bm, pref, mode) != kFailure; 185 if (success && format) { 186 *format = codec->getFormat(); 187 if (kUnknown_Format == *format) { 188 if (stream->rewind()) { 189 *format = GetStreamFormat(stream); 190 } 191 } 192 } 193 delete codec; 194 } 195 return success; 196} 197 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} 205