Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkBmpCodec.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
11#include "include/core/SkData.h"
14#include "include/core/SkSize.h"
22#include "src/core/SkMasks.h"
23
24#include <cstring>
25#include <memory>
26#include <utility>
27
28/*
29 * Defines the version and type of the second bitmap header
30 */
41
42/*
43 * Possible bitmap compression types
44 */
57
58/*
59 * Used to define the input format of the bmp
60 */
67
68/*
69 * Checks the start of the stream to see if the image is a bitmap
70 */
71bool SkBmpCodec::IsBmp(const void* buffer, size_t bytesRead) {
72 // TODO: Support "IC", "PT", "CI", "CP", "BA"
73 const char bmpSig[] = { 'B', 'M' };
74 return bytesRead >= sizeof(bmpSig) && !memcmp(buffer, bmpSig, sizeof(bmpSig));
75}
76
77/*
78 * Assumes IsBmp was called and returned true
79 * Creates a bmp decoder
80 * Reads enough of the stream to determine the image format
81 */
82std::unique_ptr<SkCodec> SkBmpCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
83 Result* result) {
84 return SkBmpCodec::MakeFromStream(std::move(stream), result, false);
85}
86
87/*
88 * Creates a bmp decoder for a bmp embedded in ico
89 * Reads enough of the stream to determine the image format
90 */
91std::unique_ptr<SkCodec> SkBmpCodec::MakeFromIco(std::unique_ptr<SkStream> stream, Result* result) {
92 return SkBmpCodec::MakeFromStream(std::move(stream), result, true);
93}
94
95// Header size constants
96static constexpr uint32_t kBmpHeaderBytes = 14;
97static constexpr uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
98static constexpr uint32_t kBmpOS2V1Bytes = 12;
99static constexpr uint32_t kBmpOS2V2Bytes = 64;
100static constexpr uint32_t kBmpInfoBaseBytes = 16;
101static constexpr uint32_t kBmpInfoV1Bytes = 40;
102static constexpr uint32_t kBmpInfoV2Bytes = 52;
103static constexpr uint32_t kBmpInfoV3Bytes = 56;
104static constexpr uint32_t kBmpInfoV4Bytes = 108;
105static constexpr uint32_t kBmpInfoV5Bytes = 124;
106static constexpr uint32_t kBmpMaskBytes = 12;
107
108static BmpHeaderType get_header_type(size_t infoBytes) {
109 if (infoBytes >= kBmpInfoBaseBytes) {
110 // Check the version of the header
111 switch (infoBytes) {
112 case kBmpInfoV1Bytes:
114 case kBmpInfoV2Bytes:
116 case kBmpInfoV3Bytes:
118 case kBmpInfoV4Bytes:
120 case kBmpInfoV5Bytes:
122 case 16:
123 case 20:
124 case 24:
125 case 28:
126 case 32:
127 case 36:
128 case 42:
129 case 46:
130 case 48:
131 case 60:
132 case kBmpOS2V2Bytes:
134 default:
135 SkCodecPrintf("Error: unknown bmp header format.\n");
137 }
138 } if (infoBytes >= kBmpOS2V1Bytes) {
139 // The OS2V1 is treated separately because it has a unique format
141 } else {
142 // There are no valid bmp headers
143 SkCodecPrintf("Error: second bitmap header size is invalid.\n");
145 }
146}
147
149 std::unique_ptr<SkCodec>* codecOut) {
150 // The total bytes in the bmp file
151 // We only need to use this value for RLE decoding, so we will only
152 // check that it is valid in the RLE case.
153 uint32_t totalBytes;
154 // The offset from the start of the file where the pixel data begins
155 uint32_t offset;
156 // The size of the second (info) header in bytes
157 uint32_t infoBytes;
158
159 // Bmps embedded in Icos skip the first Bmp header
160 if (!inIco) {
161 // Read the first header and the size of the second header
162 uint8_t hBuffer[kBmpHeaderBytesPlusFour];
163 if (stream->read(hBuffer, kBmpHeaderBytesPlusFour) !=
165 SkCodecPrintf("Error: unable to read first bitmap header.\n");
166 return kIncompleteInput;
167 }
168
169 totalBytes = get_int(hBuffer, 2);
170 offset = get_int(hBuffer, 10);
172 SkCodecPrintf("Error: invalid starting location for pixel data\n");
173 return kInvalidInput;
174 }
175
176 // The size of the second (info) header in bytes
177 // The size is the first field of the second header, so we have already
178 // read the first four infoBytes.
179 infoBytes = get_int(hBuffer, 14);
180 if (infoBytes < kBmpOS2V1Bytes) {
181 SkCodecPrintf("Error: invalid second header size.\n");
182 return kInvalidInput;
183 }
184 } else {
185 // This value is only used by RLE compression. Bmp in Ico files do not
186 // use RLE. If the compression field is incorrectly signaled as RLE,
187 // we will catch this and signal an error below.
188 totalBytes = 0;
189
190 // Bmps in Ico cannot specify an offset. We will always assume that
191 // pixel data begins immediately after the color table. This value
192 // will be corrected below.
193 offset = 0;
194
195 // Read the size of the second header
196 uint8_t hBuffer[4];
197 if (stream->read(hBuffer, 4) != 4) {
198 SkCodecPrintf("Error: unable to read size of second bitmap header.\n");
199 return kIncompleteInput;
200 }
201 infoBytes = get_int(hBuffer, 0);
202 if (infoBytes < kBmpOS2V1Bytes) {
203 SkCodecPrintf("Error: invalid second header size.\n");
204 return kInvalidInput;
205 }
206 }
207
208 // Determine image information depending on second header format
209 const BmpHeaderType headerType = get_header_type(infoBytes);
210 if (kUnknown_BmpHeaderType == headerType) {
211 return kInvalidInput;
212 }
213
214 // We already read the first four bytes of the info header to get the size
215 const uint32_t infoBytesRemaining = infoBytes - 4;
216
217 // Read the second header
218 std::unique_ptr<uint8_t[]> iBuffer(new uint8_t[infoBytesRemaining]);
219 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
220 SkCodecPrintf("Error: unable to read second bitmap header.\n");
221 return kIncompleteInput;
222 }
223
224 // The number of bits used per pixel in the pixel data
225 uint16_t bitsPerPixel;
226
227 // The compression method for the pixel data
228 uint32_t compression = kNone_BmpCompressionMethod;
229
230 // Number of colors in the color table, defaults to 0 or max (see below)
231 uint32_t numColors = 0;
232
233 // Bytes per color in the color table, early versions use 3, most use 4
234 uint32_t bytesPerColor;
235
236 // The image width and height
237 int width, height;
238
239 switch (headerType) {
246 // We check the size of the header before entering the if statement.
247 // We should not reach this point unless the size is large enough for
248 // these required fields.
249 SkASSERT(infoBytesRemaining >= 12);
250 width = get_int(iBuffer.get(), 0);
251 height = get_int(iBuffer.get(), 4);
252 bitsPerPixel = get_short(iBuffer.get(), 10);
253
254 // Some versions do not have these fields, so we check before
255 // overwriting the default value.
256 if (infoBytesRemaining >= 16) {
257 compression = get_int(iBuffer.get(), 12);
258 if (infoBytesRemaining >= 32) {
259 numColors = get_int(iBuffer.get(), 28);
260 }
261 }
262
263 // All of the headers that reach this point, store color table entries
264 // using 4 bytes per pixel.
265 bytesPerColor = 4;
266 break;
268 // The OS2V1 is treated separately because it has a unique format
269 width = (int) get_short(iBuffer.get(), 0);
270 height = (int) get_short(iBuffer.get(), 2);
271 bitsPerPixel = get_short(iBuffer.get(), 6);
272 bytesPerColor = 3;
273 break;
275 // We'll exit above in this case.
276 SkASSERT(false);
277 return kInvalidInput;
278 }
279
280 // Check for valid dimensions from header
282 if (height < 0) {
283 // We can't negate INT32_MIN.
284 if (height == INT32_MIN) {
285 return kInvalidInput;
286 }
287
288 height = -height;
290 }
291 // The height field for bmp in ico is double the actual height because they
292 // contain an XOR mask followed by an AND mask
293 if (inIco) {
294 height /= 2;
295 }
296
297 // Arbitrary maximum. Matches Chromium.
298 constexpr int kMaxDim = 1 << 16;
299 if (width <= 0 || height <= 0 || width >= kMaxDim || height >= kMaxDim) {
300 SkCodecPrintf("Error: invalid bitmap dimensions.\n");
301 return kInvalidInput;
302 }
303
304 // Create mask struct
305 SkMasks::InputMasks inputMasks;
306 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
307
308 // Determine the input compression format and set bit masks if necessary
309 uint32_t maskBytes = 0;
311 switch (compression) {
313 inputFormat = kStandard_BmpInputFormat;
314
315 // In addition to more standard pixel compression formats, bmp supports
316 // the use of bit masks to determine pixel components. The standard
317 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
318 // which does not map well to any Skia color formats. For this reason,
319 // we will always enable mask mode with 16 bits per pixel.
320 if (16 == bitsPerPixel) {
321 inputMasks.red = 0x7C00;
322 inputMasks.green = 0x03E0;
323 inputMasks.blue = 0x001F;
324 inputFormat = kBitMask_BmpInputFormat;
325 }
326 break;
328 if (bitsPerPixel != 8) {
329 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
330 bitsPerPixel = 8;
331 }
332 inputFormat = kRLE_BmpInputFormat;
333 break;
335 if (bitsPerPixel != 4) {
336 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
337 bitsPerPixel = 4;
338 }
339 inputFormat = kRLE_BmpInputFormat;
340 break;
343 // Load the masks
344 inputFormat = kBitMask_BmpInputFormat;
345 switch (headerType) {
347 // The V1 header stores the bit masks after the header
348 uint8_t buffer[kBmpMaskBytes];
350 SkCodecPrintf("Error: unable to read bit inputMasks.\n");
351 return kIncompleteInput;
352 }
353 maskBytes = kBmpMaskBytes;
354 inputMasks.red = get_int(buffer, 0);
355 inputMasks.green = get_int(buffer, 4);
356 inputMasks.blue = get_int(buffer, 8);
357 break;
358 }
363 // Header types are matched based on size. If the header
364 // is V2+, we are guaranteed to be able to read at least
365 // this size.
366 SkASSERT(infoBytesRemaining >= 48);
367 inputMasks.red = get_int(iBuffer.get(), 36);
368 inputMasks.green = get_int(iBuffer.get(), 40);
369 inputMasks.blue = get_int(iBuffer.get(), 44);
370
371 if (kInfoV2_BmpHeaderType == headerType ||
372 (kInfoV3_BmpHeaderType == headerType && !inIco)) {
373 break;
374 }
375
376 // V3+ bmp files introduce an alpha mask and allow the creator of the image
377 // to use the alpha channels. However, many of these images leave the
378 // alpha channel blank and expect to be rendered as opaque. This is the
379 // case for almost all V3 images, so we ignore the alpha mask. For V4+
380 // images in kMask mode, we will use the alpha mask. Additionally, V3
381 // bmp-in-ico expect us to use the alpha mask.
382 //
383 // skbug.com/4116: We should perhaps also apply the alpha mask in kStandard
384 // mode. We just haven't seen any images that expect this
385 // behavior.
386 //
387 // Header types are matched based on size. If the header is
388 // V3+, we are guaranteed to be able to read at least this size.
389 SkASSERT(infoBytesRemaining >= 52);
390 inputMasks.alpha = get_int(iBuffer.get(), 48);
391 break;
393 // TODO: Decide if we intend to support this.
394 // It is unsupported in the previous version and
395 // in chromium. I have not come across a test case
396 // that uses this format.
397 SkCodecPrintf("Error: huffman format unsupported.\n");
398 return kUnimplemented;
399 default:
400 SkCodecPrintf("Error: invalid bmp bit masks header.\n");
401 return kInvalidInput;
402 }
403 break;
405 if (24 == bitsPerPixel) {
406 inputFormat = kRLE_BmpInputFormat;
407 break;
408 }
409 [[fallthrough]];
411 // TODO: Decide if we intend to support this.
412 // It is unsupported in the previous version and
413 // in chromium. I think it is used mostly for printers.
414 SkCodecPrintf("Error: compression format not supported.\n");
415 return kUnimplemented;
419 // TODO: Same as above.
420 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n");
421 return kUnimplemented;
422 default:
423 SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
424 return kInvalidInput;
425 }
426 iBuffer.reset();
427
428 // Calculate the number of bytes read so far
429 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
430 if (!inIco && offset < bytesRead) {
431 // TODO (msarett): Do we really want to fail if the offset in the header is invalid?
432 // Seems like we can just assume that the offset is zero and try to decode?
433 // Maybe we don't want to try to decode corrupt images?
434 SkCodecPrintf("Error: pixel data offset less than header size.\n");
435 return kInvalidInput;
436 }
437
438
439
440 switch (inputFormat) {
442 // BMPs are generally opaque, however BMPs-in-ICOs may contain
443 // a transparency mask after the image. Therefore, we mark the
444 // alpha as kBinary if the BMP is contained in an ICO.
445 // We use |isOpaque| to indicate if the BMP itself is opaque.
448 bool isOpaque = true;
449
451 uint8_t bitsPerComponent;
452 switch (bitsPerPixel) {
453 // Palette formats
454 case 1:
455 case 2:
456 case 4:
457 case 8:
458 // In the case of ICO, kBGRA is actually the closest match,
459 // since we will need to apply a transparency mask.
460 if (inIco) {
462 bitsPerComponent = 8;
463 } else {
465 bitsPerComponent = (uint8_t) bitsPerPixel;
466 }
467 break;
468 case 24:
469 // In the case of ICO, kBGRA is actually the closest match,
470 // since we will need to apply a transparency mask.
472 bitsPerComponent = 8;
473 break;
474 case 32:
475 // 32-bit BMP-in-ICOs actually use the alpha channel in place of a
476 // transparency mask.
477 if (inIco) {
478 isOpaque = false;
481 } else {
483 }
484 bitsPerComponent = 8;
485 break;
486 default:
487 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
488 return kInvalidInput;
489 }
490
491 if (codecOut) {
492 // We require streams to have a memory base for Bmp-in-Ico decodes.
493 SkASSERT(!inIco || nullptr != stream->getMemoryBase());
494
495 // Set the image info and create a codec.
496 auto info = SkEncodedInfo::Make(width, height, color, alpha, bitsPerComponent);
497 *codecOut = std::make_unique<SkBmpStandardCodec>(std::move(info),
498 std::unique_ptr<SkStream>(stream),
499 bitsPerPixel, numColors, bytesPerColor,
500 offset - bytesRead, rowOrder, isOpaque,
501 inIco);
502 return static_cast<SkBmpStandardCodec*>(codecOut->get())->didCreateSrcBuffer()
504 }
505 return kSuccess;
506 }
507
509 // Bmp-in-Ico must be standard mode
510 if (inIco) {
511 SkCodecPrintf("Error: Icos may not use bit mask format.\n");
512 return kInvalidInput;
513 }
514
515 switch (bitsPerPixel) {
516 case 16:
517 case 24:
518 case 32:
519 break;
520 default:
521 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
522 return kInvalidInput;
523 }
524
525 // Skip to the start of the pixel array.
526 // We can do this here because there is no color table to read
527 // in bit mask mode.
528 if (stream->skip(offset - bytesRead) != offset - bytesRead) {
529 SkCodecPrintf("Error: unable to skip to image data.\n");
530 return kIncompleteInput;
531 }
532
533 if (codecOut) {
534 // Check that input bit masks are valid and create the masks object
535 SkASSERT(bitsPerPixel % 8 == 0);
536 std::unique_ptr<SkMasks> masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel/8));
537 if (nullptr == masks) {
538 SkCodecPrintf("Error: invalid input masks.\n");
539 return kInvalidInput;
540 }
541
542 // Masked bmps are not a great fit for SkEncodedInfo, since they have
543 // arbitrary component orderings and bits per component. Here we choose
544 // somewhat reasonable values - it's ok that we don't match exactly
545 // because SkBmpMaskCodec has its own mask swizzler anyway.
548 if (masks->getAlphaMask()) {
551 } else {
554 }
555 auto info = SkEncodedInfo::Make(width, height, color, alpha, 8);
556 *codecOut = std::make_unique<SkBmpMaskCodec>(std::move(info),
557 std::unique_ptr<SkStream>(stream), bitsPerPixel,
558 masks.release(), rowOrder);
559 return static_cast<SkBmpMaskCodec*>(codecOut->get())->didCreateSrcBuffer()
561 }
562 return kSuccess;
563 }
564
565 case kRLE_BmpInputFormat: {
566 // We should not reach this point without a valid value of bitsPerPixel.
567 SkASSERT(4 == bitsPerPixel || 8 == bitsPerPixel || 24 == bitsPerPixel);
568
569 // Check for a valid number of total bytes when in RLE mode
570 if (totalBytes <= offset) {
571 SkCodecPrintf("Error: RLE requires valid input size.\n");
572 return kInvalidInput;
573 }
574
575 // Bmp-in-Ico must be standard mode
576 // When inIco is true, this line cannot be reached, since we
577 // require that RLE Bmps have a valid number of totalBytes, and
578 // Icos skip the header that contains totalBytes.
579 SkASSERT(!inIco);
580
581 if (codecOut) {
582 // RLE inputs may skip pixels, leaving them as transparent. This
583 // is uncommon, but we cannot be certain that an RLE bmp will be
584 // opaque or that we will be able to represent it with a palette.
585 // For that reason, we always indicate that we are kBGRA.
588 *codecOut = std::make_unique<SkBmpRLECodec>(std::move(info),
589 std::unique_ptr<SkStream>(stream), bitsPerPixel,
590 numColors, bytesPerColor, offset - bytesRead,
591 rowOrder);
592 }
593 return kSuccess;
594 }
595 default:
596 SkASSERT(false);
597 return kInvalidInput;
598 }
599}
600
601/*
602 * Creates a bmp decoder
603 * Reads enough of the stream to determine the image format
604 */
605std::unique_ptr<SkCodec> SkBmpCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
606 Result* result, bool inIco) {
608 if (!stream) {
610 return nullptr;
611 }
612 std::unique_ptr<SkCodec> codec;
613 *result = ReadHeader(stream.get(), inIco, &codec);
614 if (codec) {
615 // codec has taken ownership of stream, so we do not need to delete it.
616 stream.release();
617 }
618 return kSuccess == *result ? std::move(codec) : nullptr;
619}
620
621SkBmpCodec::SkBmpCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream> stream,
622 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder)
623 : INHERITED(std::move(info), kXformSrcColorFormat, std::move(stream))
624 , fBitsPerPixel(bitsPerPixel)
625 , fRowOrder(rowOrder)
626 , fSrcRowBytes(SkAlign4(compute_row_bytes(this->dimensions().width(), fBitsPerPixel)))
627 , fXformBuffer(nullptr)
628{}
629
631 return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr) == kSuccess;
632}
633
634int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) const {
635 if (SkCodec::kTopDown_SkScanlineOrder == fRowOrder) {
636 return y;
637 }
639 return height - y - 1;
640}
641
643 const SkCodec::Options& options) {
644 return this->onPrepareToDecode(dstInfo, options);
645}
646
651
652int SkBmpCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
653 // Create a new image info representing the portion of the image to decode
654 SkImageInfo rowInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);
655
656 // Decode the requested rows
657 return this->decodeRows(rowInfo, dst, rowBytes, this->options());
658}
659
661 const size_t bytesToSkip = count * fSrcRowBytes;
662 return this->stream()->skip(bytesToSkip) == bytesToSkip;
663}
664
666 return this->skipRows(count);
667}
668
669namespace SkBmpDecoder {
670bool IsBmp(const void* data, size_t len) {
671 return SkBmpCodec::IsBmp(data, len);
672}
673
674std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream> stream,
675 SkCodec::Result* outResult,
676 SkCodecs::DecodeContext) {
677 SkCodec::Result resultStorage;
678 if (!outResult) {
679 outResult = &resultStorage;
680 }
681 return SkBmpCodec::MakeFromStream(std::move(stream), outResult);
682}
683
684std::unique_ptr<SkCodec> Decode(sk_sp<SkData> data,
685 SkCodec::Result* outResult,
686 SkCodecs::DecodeContext) {
687 if (!data) {
688 if (outResult) {
689 *outResult = SkCodec::kInvalidInput;
690 }
691 return nullptr;
692 }
693 return Decode(SkMemoryStream::Make(std::move(data)), outResult, nullptr);
694}
695} // namespace SkBmpDecoder
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
int count
SkColor4f color
static constexpr T SkAlign4(T x)
Definition SkAlign.h:16
#define SkASSERT(cond)
Definition SkAssert.h:116
static constexpr uint32_t kBmpHeaderBytes
static constexpr uint32_t kBmpHeaderBytesPlusFour
static BmpHeaderType get_header_type(size_t infoBytes)
static constexpr uint32_t kBmpInfoV2Bytes
static constexpr uint32_t kBmpInfoV3Bytes
static constexpr uint32_t kBmpOS2V1Bytes
static constexpr uint32_t kBmpInfoBaseBytes
static constexpr uint32_t kBmpOS2V2Bytes
static constexpr uint32_t kBmpInfoV4Bytes
static constexpr uint32_t kBmpInfoV5Bytes
static constexpr uint32_t kBmpInfoV1Bytes
BmpCompressionMethod
@ kCMYK8BitRLE_BmpCompressionMethod
@ kAlphaBitMasks_BmpCompressionMethod
@ k8BitRLE_BmpCompressionMethod
@ k4BitRLE_BmpCompressionMethod
@ kCMYK_BmpCompressionMethod
@ kBitMasks_BmpCompressionMethod
@ kJpeg_BmpCompressionMethod
@ kNone_BmpCompressionMethod
@ kPng_BmpCompressionMethod
@ kCMYK4BitRLE_BmpCompressionMethod
static constexpr uint32_t kBmpMaskBytes
BmpInputFormat
@ kUnknown_BmpInputFormat
@ kRLE_BmpInputFormat
@ kBitMask_BmpInputFormat
@ kStandard_BmpInputFormat
BmpHeaderType
@ kOS2VX_BmpHeaderType
@ kInfoV1_BmpHeaderType
@ kUnknown_BmpHeaderType
@ kOS2V1_BmpHeaderType
@ kInfoV4_BmpHeaderType
@ kInfoV3_BmpHeaderType
@ kInfoV5_BmpHeaderType
@ kInfoV2_BmpHeaderType
static size_t compute_row_bytes(int width, uint32_t bitsPerPixel)
static uint32_t get_int(const uint8_t *buffer, uint32_t i)
#define SkCodecPrintf(...)
Definition SkCodecPriv.h:23
static uint16_t get_short(const uint8_t *buffer, uint32_t i)
Type::kYUV Type::kRGBA() int(0.7 *637)
bool onSkipScanlines(int count) override
virtual int decodeRows(const SkImageInfo &dstInfo, void *dst, size_t dstRowBytes, const Options &opts)=0
static std::unique_ptr< SkCodec > MakeFromIco(std::unique_ptr< SkStream >, Result *)
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, Result *)
SkBmpCodec(SkEncodedInfo &&info, std::unique_ptr< SkStream >, uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder)
virtual SkCodec::Result onPrepareToDecode(const SkImageInfo &dstInfo, const SkCodec::Options &options)=0
virtual bool skipRows(int count)
bool onRewind() override
int32_t getDstRow(int32_t y, int32_t height) const
SkCodec::Result prepareToDecode(const SkImageInfo &dstInfo, const SkCodec::Options &options)
Result onStartScanlineDecode(const SkImageInfo &dstInfo, const SkCodec::Options &) override
static bool IsBmp(const void *, size_t)
uint16_t bitsPerPixel() const
Definition SkBmpCodec.h:87
static Result ReadHeader(SkStream *, bool inIco, std::unique_ptr< SkCodec > *codecOut)
int onGetScanlines(void *dst, int count, size_t rowBytes) override
bool inIco() const
Definition SkBmpCodec.h:63
const SkImageInfo & dstInfo() const
Definition SkCodec.h:878
SkStream * stream()
Definition SkCodec.h:865
SkScanlineOrder
Definition SkCodec.h:575
@ kBottomUp_SkScanlineOrder
Definition SkCodec.h:604
@ kTopDown_SkScanlineOrder
Definition SkCodec.h:581
@ kIncompleteInput
Definition SkCodec.h:84
@ kInvalidInput
Definition SkCodec.h:109
@ kUnimplemented
Definition SkCodec.h:123
@ kSuccess
Definition SkCodec.h:80
const Options & options() const
Definition SkCodec.h:880
static SkMasks * CreateMasks(InputMasks masks, int bytesPerPixel)
Definition SkMasks.cpp:126
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 const void * getMemoryBase()
Definition SkStream.h:141
virtual size_t read(void *buffer, size_t size)=0
static const uint8_t buffer[]
GAsyncResult * result
double y
SK_API bool IsBmp(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
Point offset
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)
SkImageInfo makeWH(int newWidth, int newHeight) const