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