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  */
21 class SkBmpCodec : public SkCodec {
22 public:
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 
38 protected:
39 
40     SkBmpCodec(const SkImageInfo& info, SkStream* stream, uint16_t bitsPerPixel,
41             SkCodec::SkScanlineOrder rowOrder);
42 
onGetEncodedFormat()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      */
inIco()58     bool inIco() const {
59         return this->onInIco();
60     }
61 
onInIco()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      */
bitsPerPixel()82     uint16_t bitsPerPixel() const { return fBitsPerPixel; }
onGetScanlineOrder()83     SkScanlineOrder onGetScanlineOrder() const override { return fRowOrder; }
srcRowBytes()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 
105 private:
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