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"
11404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III#include "SkColorPriv.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkImageDecoder.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkScaledBitmapSampler.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkStream.h"
15404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III#include "SkStreamHelpers.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTDArray.h"
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTRegistry.h"
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkBMPImageDecoder : public SkImageDecoder {
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBMPImageDecoder() {}
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    virtual Format getFormat() const SK_OVERRIDE {
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return kBMP_Format;
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprotected:
28096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE;
29096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
30096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerprivate:
31096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    typedef SkImageDecoder INHERITED;
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruDEFINE_DECODER_CREATOR(BMPImageDecoder);
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic bool is_bmp(SkStream* stream) {
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const char kBmpMagic[] = { 'B', 'M' };
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char buffer[sizeof(kBmpMagic)];
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return stream->read(buffer, sizeof(kBmpMagic)) == sizeof(kBmpMagic) &&
457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        !memcmp(buffer, kBmpMagic, sizeof(kBmpMagic));
467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic SkImageDecoder* sk_libbmp_dfactory(SkStream* stream) {
497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (is_bmp(stream)) {
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkNEW(SkBMPImageDecoder);
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return NULL;
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_libbmp_dfactory);
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic SkImageDecoder::Format get_format_bmp(SkStream* stream) {
587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (is_bmp(stream)) {
597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return SkImageDecoder::kBMP_Format;
607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return SkImageDecoder::kUnknown_Format;
627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_bmp);
657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkBmpDecoderCallback : public image_codec::BmpDecoderCallback {
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we don't copy the bitmap, just remember the pointer
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBmpDecoderCallback(bool justBounds) : fJustBounds(justBounds) {}
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // override from BmpDecoderCallback
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual uint8* SetSize(int width, int height) {
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fWidth = width;
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fHeight = height;
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fJustBounds) {
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return NULL;
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fRGB.setCount(width * height * 3);  // 3 == r, g, b
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return fRGB.begin();
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int width() const { return fWidth; }
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int height() const { return fHeight; }
87096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    const uint8_t* rgb() const { return fRGB.begin(); }
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTDArray<uint8_t> fRGB;
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int fWidth;
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int fHeight;
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool fJustBounds;
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
97404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III    // First read the entire stream, so that all of the data can be passed to
98404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III    // the BmpDecoderHelper.
99404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III
100404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III    // Allocated space used to hold the data.
101404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III    SkAutoMalloc storage;
102404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III    // Byte length of all of the data.
103404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III    const size_t length = CopyStreamToStorage(&storage, stream);
104404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III    if (0 == length) {
105404e5726adadda5aedc12705f662aa471981ec3fLeon Scroggins III        return 0;
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const bool justBounds = SkImageDecoder::kDecodeBounds_Mode == mode;
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBmpDecoderCallback callback(justBounds);
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Now decode the BMP into callback's rgb() array [r,g,b, r,g,b, ...]
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        image_codec::BmpDecoderHelper helper;
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const int max_pixels = 16383*16383; // max width*height
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!helper.DecodeImage((const char*)storage.get(), length,
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                max_pixels, &callback)) {
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we don't need this anymore, so free it now (before we try to allocate
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // the bitmap's pixels) rather than waiting for its destructor
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    storage.free();
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int width = callback.width();
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int height = callback.height();
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // only accept prefConfig if it makes sense for us
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkBitmap::kARGB_4444_Config != config &&
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkBitmap::kRGB_565_Config != config) {
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        config = SkBitmap::kARGB_8888_Config;
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScaledBitmapSampler sampler(width, height, getSampleSize());
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
13858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bm->setIsOpaque(true);
13958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (justBounds) {
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!this->allocPixelRef(bm, NULL)) {
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoLockPixels alp(*bm);
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15034835907d8ed21079a9ee09e0e16082a98637d42Leon Scroggins III    if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) {
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const int srcRowBytes = width * 3;
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const int dstHeight = sampler.scaledHeight();
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const uint8_t* srcRow = callback.rgb();
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    srcRow += sampler.srcY0() * srcRowBytes;
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int y = 0; y < dstHeight; y++) {
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sampler.next(srcRow);
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        srcRow += sampler.srcDY() * srcRowBytes;
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
165