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