1/*
2 * Copyright 2015 Google Inc.
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#ifndef SkBmpCodec_DEFINED
8#define SkBmpCodec_DEFINED
9
10#include "SkCodec.h"
11#include "SkColorTable.h"
12#include "SkImageInfo.h"
13#include "SkStream.h"
14#include "SkSwizzler.h"
15#include "SkTypes.h"
16
17/*
18 * This class enables code sharing between its bmp codec subclasses.  The
19 * subclasses actually do the work.
20 */
21class SkBmpCodec : public SkCodec {
22public:
23    static bool IsBmp(const void*, size_t);
24
25    /*
26     * Assumes IsBmp was called and returned true
27     * Creates a bmp decoder
28     * Reads enough of the stream to determine the image format
29     */
30    static SkCodec* NewFromStream(SkStream*);
31
32    /*
33     * Creates a bmp decoder for a bmp embedded in ico
34     * Reads enough of the stream to determine the image format
35     */
36    static SkCodec* NewFromIco(SkStream*);
37
38protected:
39
40    SkBmpCodec(const SkImageInfo& info, SkStream* stream, uint16_t bitsPerPixel,
41            SkCodec::SkScanlineOrder rowOrder);
42
43    SkEncodedFormat onGetEncodedFormat() const override { return kBMP_SkEncodedFormat; }
44
45    /*
46     * Read enough of the stream to initialize the SkBmpCodec. Returns a bool
47     * representing success or failure. If it returned true, and codecOut was
48     * not nullptr, it will be set to a new SkBmpCodec.
49     * Does *not* take ownership of the passed in SkStream.
50     */
51    static bool ReadHeader(SkStream*, bool inIco, SkCodec** codecOut);
52
53    bool onRewind() override;
54
55    /*
56     * Returns whether this BMP is part of an ICO image.
57     */
58    bool inIco() const {
59        return this->onInIco();
60    }
61
62    virtual bool onInIco() const {
63        return false;
64    }
65
66    /*
67     * Get the destination row number corresponding to the encoded row number.
68     * For kTopDown, we simply return y, but for kBottomUp, the rows will be
69     * decoded in reverse order.
70     *
71     * @param y      Iterates from 0 to height, indicating the current row.
72     * @param height The height of the current subset of the image that we are
73     *               decoding.  This is generally equal to the full height
74     *               when we want to decode the full or one when we are
75     *               sampling.
76     */
77    int32_t getDstRow(int32_t y, int32_t height) const;
78
79    /*
80     * Accessors used by subclasses
81     */
82    uint16_t bitsPerPixel() const { return fBitsPerPixel; }
83    SkScanlineOrder onGetScanlineOrder() const override { return fRowOrder; }
84    size_t srcRowBytes() const { return fSrcRowBytes; }
85
86    /*
87     * To be overriden by bmp subclasses, which provide unique implementations.
88     * Performs subclass specific setup.
89     *
90     * @param dstInfo         Contains output information.  Height specifies
91     *                        the total number of rows that will be decoded.
92     * @param options         Additonal options to pass to the decoder.
93     * @param inputColorPtr   Client-provided memory for a color table.  Must
94     *                        be enough for 256 colors.  This will be
95     *                        populated with colors if the encoded image uses
96     *                        a color table.
97     * @param inputColorCount If the encoded image uses a color table, this
98     *                        will be set to the number of colors in the
99     *                        color table.
100     */
101    virtual SkCodec::Result prepareToDecode(const SkImageInfo& dstInfo,
102            const SkCodec::Options& options, SkPMColor inputColorPtr[],
103            int* inputColorCount) = 0;
104
105private:
106
107    /*
108     * Creates a bmp decoder
109     * Reads enough of the stream to determine the image format
110     */
111    static SkCodec* NewFromStream(SkStream*, bool inIco);
112
113    /*
114     * Decodes the next dstInfo.height() lines.
115     *
116     * onGetPixels() uses this for full image decodes.
117     * SkScaledCodec::onGetPixels() uses the scanline decoder to call this with
118     * dstInfo.height() = 1, in order to implement sampling.
119     * A potential future use is to allow the caller to decode a subset of the
120     * lines in the image.
121     *
122     * @param dstInfo     Contains output information.  Height specifies the
123     *                    number of rows to decode at this time.
124     * @param dst         Memory location to store output pixels
125     * @param dstRowBytes Bytes in a row of the destination
126     * @return            Number of rows successfully decoded
127     */
128    virtual int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes,
129            const Options& opts) = 0;
130
131    virtual bool skipRows(int count);
132
133    Result onStartScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options&,
134            SkPMColor inputColorPtr[], int* inputColorCount) override;
135
136    int onGetScanlines(void* dst, int count, size_t rowBytes) override;
137
138    bool onSkipScanlines(int count) override;
139
140    const uint16_t          fBitsPerPixel;
141    const SkScanlineOrder   fRowOrder;
142    const size_t            fSrcRowBytes;
143
144    typedef SkCodec INHERITED;
145};
146
147#endif
148