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 "include/codec/SkCodec.h"
11 #include "include/core/SkColorSpace.h"
12 #include "include/core/SkImageInfo.h"
13 #include "include/core/SkStream.h"
14 #include "include/core/SkTypes.h"
15 #include "src/codec/SkColorTable.h"
16 #include "src/codec/SkSwizzler.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 std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*);
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 std::unique_ptr<SkCodec> MakeFromIco(std::unique_ptr<SkStream>, Result*);
38 
39 protected:
40 
41     SkBmpCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream>,
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.
48      * On kSuccess, if codecOut is not nullptr, it will be set to a new SkBmpCodec.
49      */
50     static Result ReadHeader(SkStream*, bool inIco, std::unique_ptr<SkCodec>* codecOut);
51 
52     bool onRewind() override;
53 
54     /*
55      * Returns whether this BMP is part of an ICO image.
56      */
inIco()57     bool inIco() const {
58         return this->onInIco();
59     }
60 
onInIco()61     virtual bool onInIco() const {
62         return false;
63     }
64 
65     /*
66      * Get the destination row number corresponding to the encoded row number.
67      * For kTopDown, we simply return y, but for kBottomUp, the rows will be
68      * decoded in reverse order.
69      *
70      * @param y      Iterates from 0 to height, indicating the current row.
71      * @param height The height of the current subset of the image that we are
72      *               decoding.  This is generally equal to the full height
73      *               when we want to decode the full or one when we are
74      *               sampling.
75      */
76     int32_t getDstRow(int32_t y, int32_t height) const;
77 
78     /*
79      * Accessors used by subclasses
80      */
bitsPerPixel()81     uint16_t bitsPerPixel() const { return fBitsPerPixel; }
onGetScanlineOrder()82     SkScanlineOrder onGetScanlineOrder() const override { return fRowOrder; }
srcRowBytes()83     size_t srcRowBytes() const { return fSrcRowBytes; }
84 
85     /*
86      * To be overriden by bmp subclasses, which provide unique implementations.
87      * Performs subclass specific setup.
88      *
89      * @param dstInfo         Contains output information.  Height specifies
90      *                        the total number of rows that will be decoded.
91      * @param options         Additonal options to pass to the decoder.
92      */
93     virtual SkCodec::Result onPrepareToDecode(const SkImageInfo& dstInfo,
94             const SkCodec::Options& options) = 0;
95     SkCodec::Result prepareToDecode(const SkImageInfo& dstInfo,
96             const SkCodec::Options& options);
97 
xformBuffer()98     uint32_t* xformBuffer() const { return fXformBuffer.get(); }
resetXformBuffer(int count)99     void resetXformBuffer(int count) { fXformBuffer.reset(new uint32_t[count]); }
100 
101     /*
102      * BMPs are typically encoded as BGRA/BGR so this is a more efficient choice
103      * than RGBA.
104      */
105     static constexpr SkColorType kXformSrcColorType = kBGRA_8888_SkColorType;
106     static constexpr auto kXformSrcColorFormat = skcms_PixelFormat_BGRA_8888;
107 
108 private:
109 
110     /*
111      * Creates a bmp decoder
112      * Reads enough of the stream to determine the image format
113      */
114     static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*, bool inIco);
115 
116     /*
117      * Decodes the next dstInfo.height() lines.
118      *
119      * onGetPixels() uses this for full image decodes.
120      * SkScaledCodec::onGetPixels() uses the scanline decoder to call this with
121      * dstInfo.height() = 1, in order to implement sampling.
122      * A potential future use is to allow the caller to decode a subset of the
123      * lines in the image.
124      *
125      * @param dstInfo     Contains output information.  Height specifies the
126      *                    number of rows to decode at this time.
127      * @param dst         Memory location to store output pixels
128      * @param dstRowBytes Bytes in a row of the destination
129      * @return            Number of rows successfully decoded
130      */
131     virtual int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes,
132             const Options& opts) = 0;
133 
134     virtual bool skipRows(int count);
135 
136     Result onStartScanlineDecode(const SkImageInfo& dstInfo,
137             const SkCodec::Options&) override;
138 
139     int onGetScanlines(void* dst, int count, size_t rowBytes) override;
140 
141     bool onSkipScanlines(int count) override;
142 
143     const uint16_t              fBitsPerPixel;
144     const SkScanlineOrder       fRowOrder;
145     const size_t                fSrcRowBytes;
146     std::unique_ptr<uint32_t[]> fXformBuffer;
147 
148     typedef SkCodec INHERITED;
149 };
150 
151 #endif
152