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 */
22class SkBmpCodec : public SkCodec {
23public:
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
39protected:
40
41 SkBmpCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream>,
42 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder);
43
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 */
57 bool inIco() const {
58 return this->onInIco();
59 }
60
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 */
81 uint16_t bitsPerPixel() const { return fBitsPerPixel; }
82 SkScanlineOrder onGetScanlineOrder() const override { return fRowOrder; }
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
98 uint32_t* xformBuffer() const { return fXformBuffer.get(); }
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
108private:
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