Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkWbmpCodec.cpp
Go to the documentation of this file.
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
9
14#include "include/core/SkData.h"
17#include "include/core/SkSize.h"
22#include "modules/skcms/skcms.h"
24
25#include <utility>
26
27using namespace skia_private;
28
29// Each bit represents a pixel, so width is actually a number of bits.
30// A row will always be stored in bytes, so we round width up to the
31// nearest multiple of 8 to get the number of bits actually in the row.
32// We then divide by 8 to convert to bytes.
33static inline size_t get_src_row_bytes(int width) {
34 return SkAlign8(width) >> 3;
35}
36
37static inline bool valid_color_type(const SkImageInfo& dstInfo) {
38 switch (dstInfo.colorType()) {
43 return true;
45 return dstInfo.colorSpace();
46 default:
47 return false;
48 }
49}
50
51static bool read_byte(SkStream* stream, uint8_t* data)
52{
53 return stream->read(data, 1) == 1;
54}
55
56// http://en.wikipedia.org/wiki/Variable-length_quantity
57static bool read_mbf(SkStream* stream, uint64_t* value) {
58 uint64_t n = 0;
59 uint8_t data;
60 const uint64_t kLimit = 0xFE00000000000000;
61 SkASSERT(kLimit == ~((~static_cast<uint64_t>(0)) >> 7));
62 do {
63 if (n & kLimit) { // Will overflow on shift by 7.
64 return false;
65 }
66 if (stream->read(&data, 1) != 1) {
67 return false;
68 }
69 n = (n << 7) | (data & 0x7F);
70 } while (data & 0x80);
71 *value = n;
72 return true;
73}
74
75static bool read_header(SkStream* stream, SkISize* size) {
76 {
77 uint8_t data;
78 if (!read_byte(stream, &data) || data != 0) { // unknown type
79 return false;
80 }
81 if (!read_byte(stream, &data) || (data & 0x9F)) { // skip fixed header
82 return false;
83 }
84 }
85
86 uint64_t width, height;
87 if (!read_mbf(stream, &width) || width > 0xFFFF || !width) {
88 return false;
89 }
90 if (!read_mbf(stream, &height) || height > 0xFFFF || !height) {
91 return false;
92 }
93 if (size) {
95 }
96 return true;
97}
98
100 return read_header(this->stream(), nullptr);
101}
102
103bool SkWbmpCodec::readRow(uint8_t* row) {
104 return this->stream()->read(row, fSrcRowBytes) == fSrcRowBytes;
105}
106
107SkWbmpCodec::SkWbmpCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream> stream)
108 // Wbmp does not need a colorXform, so choose an arbitrary srcFormat.
110 std::move(stream))
111 , fSrcRowBytes(get_src_row_bytes(this->dimensions().width()))
112 , fSwizzler(nullptr)
113{}
114
118
119bool SkWbmpCodec::conversionSupported(const SkImageInfo& dst, bool srcIsOpaque,
120 bool /*needsColorXform*/) {
121 return valid_color_type(dst) && valid_alpha(dst.alphaType(), srcIsOpaque);
122}
123
125 void* dst,
126 size_t rowBytes,
127 const Options& options,
128 int* rowsDecoded) {
129 if (options.fSubset) {
130 // Subsets are not supported.
131 return kUnimplemented;
132 }
133
134 // Initialize the swizzler
135 std::unique_ptr<SkSwizzler> swizzler = SkSwizzler::Make(this->getEncodedInfo(), nullptr, info,
136 options);
137 SkASSERT(swizzler);
138
139 // Perform the decode
140 SkISize size = info.dimensions();
141 AutoTMalloc<uint8_t> src(fSrcRowBytes);
142 void* dstRow = dst;
143 for (int y = 0; y < size.height(); ++y) {
144 if (!this->readRow(src.get())) {
145 *rowsDecoded = y;
146 return kIncompleteInput;
147 }
148 swizzler->swizzle(dstRow, src.get());
149 dstRow = SkTAddOffset<void>(dstRow, rowBytes);
150 }
151 return kSuccess;
152}
153
154bool SkWbmpCodec::IsWbmp(const void* buffer, size_t bytesRead) {
155 SkMemoryStream stream(buffer, bytesRead, false);
156 return read_header(&stream, nullptr);
157}
158
159std::unique_ptr<SkCodec> SkWbmpCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
160 Result* result) {
162 if (!stream) {
164 return nullptr;
165 }
166 SkISize size;
167 if (!read_header(stream.get(), &size)) {
168 // This already succeeded in IsWbmp, so this stream was corrupted in/
169 // after rewind.
171 return nullptr;
172 }
173 *result = kSuccess;
174 auto info = SkEncodedInfo::Make(size.width(), size.height(), SkEncodedInfo::kGray_Color,
176 return std::unique_ptr<SkCodec>(new SkWbmpCodec(std::move(info), std::move(stream)));
177}
178
179int SkWbmpCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
180 void* dstRow = dst;
181 for (int y = 0; y < count; ++y) {
182 if (!this->readRow(fSrcBuffer.get())) {
183 return y;
184 }
185 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
186 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
187 }
188 return count;
189}
190
192 const size_t bytesToSkip = count * fSrcRowBytes;
193 return this->stream()->skip(bytesToSkip) == bytesToSkip;
194}
195
197 const Options& options) {
198 if (options.fSubset) {
199 // Subsets are not supported.
200 return kUnimplemented;
201 }
202
203 fSwizzler = SkSwizzler::Make(this->getEncodedInfo(), nullptr, dstInfo, options);
204 SkASSERT(fSwizzler);
205
206 fSrcBuffer.reset(fSrcRowBytes);
207
208 return kSuccess;
209}
210
211namespace SkWbmpDecoder {
212bool IsWbmp(const void* data, size_t len) {
213 return SkWbmpCodec::IsWbmp(data, len);
214}
215
216std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream> stream,
217 SkCodec::Result* outResult,
218 SkCodecs::DecodeContext) {
219 SkCodec::Result resultStorage;
220 if (!outResult) {
221 outResult = &resultStorage;
222 }
223 return SkWbmpCodec::MakeFromStream(std::move(stream), outResult);
224}
225
226std::unique_ptr<SkCodec> Decode(sk_sp<SkData> data,
227 SkCodec::Result* outResult,
228 SkCodecs::DecodeContext) {
229 if (!data) {
230 if (outResult) {
231 *outResult = SkCodec::kInvalidInput;
232 }
233 return nullptr;
234 }
235 return Decode(SkMemoryStream::Make(std::move(data)), outResult, nullptr);
236}
237} // namespace SkWbmpDecoder
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
int count
static constexpr T SkAlign8(T x)
Definition SkAlign.h:17
#define SkASSERT(cond)
Definition SkAssert.h:116
static bool valid_alpha(SkAlphaType dstAlpha, bool srcIsOpaque)
Definition SkCodecPriv.h:90
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition SkColorType.h:26
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
Definition SkColorType.h:38
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
Definition SkColorType.h:35
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
Definition SkColorType.h:22
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
SkEncodedImageFormat
static SkCodec::Result read_header(SkStream *stream, SkPngChunkReader *chunkReader, SkCodec **outCodec, png_structp *png_ptrp, png_infop *info_ptrp)
#define INHERITED(method,...)
constexpr int32_t SkToS32(S x)
Definition SkTo.h:25
static bool read_mbf(SkStream *stream, uint64_t *value)
static bool read_byte(SkStream *stream, uint8_t *data)
static size_t get_src_row_bytes(int width)
static bool valid_color_type(const SkImageInfo &dstInfo)
static bool read_header(SkStream *stream, SkISize *size)
SkStream * stream()
Definition SkCodec.h:865
const SkEncodedInfo & getEncodedInfo() const
Definition SkCodec.h:788
@ kIncompleteInput
Definition SkCodec.h:84
@ kInvalidInput
Definition SkCodec.h:109
@ kCouldNotRewind
Definition SkCodec.h:114
@ kUnimplemented
Definition SkCodec.h:123
@ kSuccess
Definition SkCodec.h:80
const Options & options() const
Definition SkCodec.h:880
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
Definition SkStream.cpp:314
size_t skip(size_t size)
Definition SkStream.h:51
virtual size_t read(void *buffer, size_t size)=0
static std::unique_ptr< SkSwizzler > Make(const SkEncodedInfo &encodedInfo, const SkPMColor *ctable, const SkImageInfo &dstInfo, const SkCodec::Options &, const SkIRect *frame=nullptr)
SkEncodedImageFormat onGetEncodedFormat() const override
Result onStartScanlineDecode(const SkImageInfo &dstInfo, const Options &options) override
static bool IsWbmp(const void *, size_t)
bool conversionSupported(const SkImageInfo &dst, bool srcIsOpaque, bool needsXform) override
bool onRewind() override
bool onSkipScanlines(int count) override
int onGetScanlines(void *dst, int count, size_t dstRowBytes) override
Result onGetPixels(const SkImageInfo &, void *, size_t, const Options &, int *) override
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, Result *)
T * reset(size_t count=0)
static const uint8_t buffer[]
uint8_t value
GAsyncResult * result
double y
SK_API bool IsWbmp(const void *, size_t)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
Definition ref_ptr.h:256
int32_t height
int32_t width
skcms_PixelFormat
const SkIRect * fSubset
Definition SkCodec.h:347
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
SkColorSpace * colorSpace() const
SkColorType colorType() const