180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2007 The Android Open Source Project 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "bmpdecoderhelper.h" 110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#include "SkColorPriv.h" 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkImageDecoder.h" 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkScaledBitmapSampler.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkStream.h" 150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#include "SkStreamHelpers.h" 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTDArray.h" 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkBMPImageDecoder : public SkImageDecoder { 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBMPImageDecoder() {} 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 22096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger virtual Format getFormat() const SK_OVERRIDE { 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return kBMP_Format; 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprotected: 27096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE; 28096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger 29096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerprivate: 30096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger typedef SkImageDecoder INHERITED; 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruDEFINE_DECODER_CREATOR(BMPImageDecoder); 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerstatic bool is_bmp(SkStreamRewindable* stream) { 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static const char kBmpMagic[] = { 'B', 'M' }; 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 40e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru char buffer[sizeof(kBmpMagic)]; 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return stream->read(buffer, sizeof(kBmpMagic)) == sizeof(kBmpMagic) && 447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger !memcmp(buffer, kBmpMagic, sizeof(kBmpMagic)); 457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerstatic SkImageDecoder* sk_libbmp_dfactory(SkStreamRewindable* stream) { 487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (is_bmp(stream)) { 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkNEW(SkBMPImageDecoder); 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerstatic SkImageDecoder_DecodeReg gReg(sk_libbmp_dfactory); 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerstatic SkImageDecoder::Format get_format_bmp(SkStreamRewindable* stream) { 577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (is_bmp(stream)) { 587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return SkImageDecoder::kBMP_Format; 597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return SkImageDecoder::kUnknown_Format; 617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 630a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerstatic SkImageDecoder_FormatReg gFormatReg(get_format_bmp); 647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkBmpDecoderCallback : public image_codec::BmpDecoderCallback { 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // we don't copy the bitmap, just remember the pointer 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBmpDecoderCallback(bool justBounds) : fJustBounds(justBounds) {} 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // override from BmpDecoderCallback 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru virtual uint8* SetSize(int width, int height) { 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fWidth = width; 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fHeight = height; 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fJustBounds) { 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fRGB.setCount(width * height * 3); // 3 == r, g, b 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return fRGB.begin(); 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int width() const { return fWidth; } 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int height() const { return fHeight; } 86096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger const uint8_t* rgb() const { return fRGB.begin(); } 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate: 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkTDArray<uint8_t> fRGB; 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int fWidth; 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int fHeight; 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool fJustBounds; 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // First read the entire stream, so that all of the data can be passed to 970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // the BmpDecoderHelper. 980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 990a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Allocated space used to hold the data. 1000a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkAutoMalloc storage; 1010a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // Byte length of all of the data. 1020a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger const size_t length = CopyStreamToStorage(&storage, stream); 1030a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (0 == length) { 1040a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return 0; 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const bool justBounds = SkImageDecoder::kDecodeBounds_Mode == mode; 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBmpDecoderCallback callback(justBounds); 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Now decode the BMP into callback's rgb() array [r,g,b, r,g,b, ...] 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru { 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru image_codec::BmpDecoderHelper helper; 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const int max_pixels = 16383*16383; // max width*height 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!helper.DecodeImage((const char*)storage.get(), length, 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru max_pixels, &callback)) { 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // we don't need this anymore, so free it now (before we try to allocate 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // the bitmap's pixels) rather than waiting for its destructor 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru storage.free(); 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int width = callback.width(); 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int height = callback.height(); 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false); 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // only accept prefConfig if it makes sense for us 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (SkBitmap::kARGB_4444_Config != config && 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBitmap::kRGB_565_Config != config) { 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru config = SkBitmap::kARGB_8888_Config; 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScaledBitmapSampler sampler(width, height, getSampleSize()); 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0, 1370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger kOpaque_SkAlphaType); 13858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (justBounds) { 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!this->allocPixelRef(bm, NULL)) { 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoLockPixels alp(*bm); 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) { 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const int srcRowBytes = width * 3; 15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const int dstHeight = sampler.scaledHeight(); 15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* srcRow = callback.rgb(); 15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru srcRow += sampler.srcY0() * srcRowBytes; 15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int y = 0; y < dstHeight; y++) { 15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sampler.next(srcRow); 16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru srcRow += sampler.srcDY() * srcRowBytes; 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 164