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
20class SkStream;
21struct SkEncodedInfo;
22struct SkImageInfo;
23
24/*
25 * This class enables code sharing between its bmp codec subclasses. The
26 * subclasses actually do the work.
27 */
28class SkBmpCodec : public SkCodec {
29public:
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
45protected:
46
47 SkBmpCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream>,
48 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder);
49
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 */
63 bool inIco() const {
64 return this->onInIco();
65 }
66
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 */
87 uint16_t bitsPerPixel() const { return fBitsPerPixel; }
88 SkScanlineOrder onGetScanlineOrder() const override { return fRowOrder; }
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
104 uint32_t* xformBuffer() const { return fXformBuffer.get(); }
105 void resetXformBuffer(int count) { fXformBuffer.reset(p: 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
114private:
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

source code of flutter_engine/third_party/skia/src/codec/SkBmpCodec.h