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