/* libs/graphics/images/SkImageDecoder.cpp ** ** Copyright 2006, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #include "SkImageDecoder.h" #include "SkBitmap.h" #include "SkPixelRef.h" #include "SkStream.h" #include "SkTemplates.h" static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config; SkBitmap::Config SkImageDecoder::GetDeviceConfig() { return gDeviceConfig; } void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config) { gDeviceConfig = config; } /////////////////////////////////////////////////////////////////////////////// SkImageDecoder::SkImageDecoder() : fPeeker(NULL), fChooser(NULL), fAllocator(NULL), fSampleSize(1), fDitherImage(true) { } SkImageDecoder::~SkImageDecoder() { fPeeker->safeUnref(); fChooser->safeUnref(); fAllocator->safeUnref(); } SkImageDecoder::Format SkImageDecoder::getFormat() const { return kUnknown_Format; } SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) { SkRefCnt_SafeAssign(fPeeker, peeker); return peeker; } SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) { SkRefCnt_SafeAssign(fChooser, chooser); return chooser; } SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) { SkRefCnt_SafeAssign(fAllocator, alloc); return alloc; } void SkImageDecoder::setSampleSize(int size) { if (size < 1) { size = 1; } fSampleSize = size; } bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width, int height) const { Chooser* chooser = fChooser; if (NULL == chooser) { // no chooser, we just say YES to decoding :) return true; } chooser->begin(1); chooser->inspect(0, config, width, height); return chooser->choose() == 0; } bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) const { return bitmap->allocPixels(fAllocator, ctable); } /////////////////////////////////////////////////////////////////////////////// bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkBitmap::Config pref, Mode mode) { // pass a temporary bitmap, so that if we return false, we are assured of // leaving the caller's bitmap untouched. SkBitmap tmp; // we reset this to false before calling onDecode fShouldCancelDecode = false; if (!this->onDecode(stream, &tmp, pref, mode)) { return false; } if (tmp.config() != pref && tmp.canCopyTo(pref)) { if (mode == kDecodeBounds_Mode) { tmp.setConfig(pref, tmp.width(), tmp.height()); } else if (mode == kDecodePixels_Mode) { SkBitmap tmp2; if (tmp.copyTo(&tmp2, pref, this->getAllocator())) { tmp.swap(tmp2); } } } bm->swap(tmp); return true; } /////////////////////////////////////////////////////////////////////////////// bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkBitmap::Config pref, Mode mode, Format* format) { SkASSERT(file); SkASSERT(bm); SkFILEStream stream(file); if (stream.isValid()) { if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) { bm->pixelRef()->setURI(file); } return true; } return false; } bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkBitmap::Config pref, Mode mode, Format* format) { if (0 == size) { return false; } SkASSERT(buffer); SkMemoryStream stream(buffer, size); return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); } bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm, SkBitmap::Config pref, Mode mode, Format* format) { SkASSERT(stream); SkASSERT(bm); bool success = false; SkImageDecoder* codec = SkImageDecoder::Factory(stream); if (NULL != codec) { success = codec->decode(stream, bm, pref, mode); if (success && format) { *format = codec->getFormat(); } delete codec; } return success; }