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