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/codec/SkBmpDecoder.h"
11 #include "include/core/SkData.h"
12 #include "include/core/SkImageInfo.h"
13 #include "include/core/SkRefCnt.h"
14 #include "include/core/SkSize.h"
15 #include "include/core/SkStream.h"
16 #include "include/private/SkEncodedInfo.h"
17 #include "include/private/base/SkAlign.h"
18 #include "src/codec/SkBmpMaskCodec.h"
19 #include "src/codec/SkBmpRLECodec.h"
20 #include "src/codec/SkBmpStandardCodec.h"
21 #include "src/codec/SkCodecPriv.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 */
31 enum BmpHeaderType {
32 kInfoV1_BmpHeaderType,
33 kInfoV2_BmpHeaderType,
34 kInfoV3_BmpHeaderType,
35 kInfoV4_BmpHeaderType,
36 kInfoV5_BmpHeaderType,
37 kOS2V1_BmpHeaderType,
38 kOS2VX_BmpHeaderType,
39 kUnknown_BmpHeaderType
40 };
41
42 /*
43 * Possible bitmap compression types
44 */
45 enum BmpCompressionMethod {
46 kNone_BmpCompressionMethod = 0,
47 k8BitRLE_BmpCompressionMethod = 1,
48 k4BitRLE_BmpCompressionMethod = 2,
49 kBitMasks_BmpCompressionMethod = 3,
50 kJpeg_BmpCompressionMethod = 4,
51 kPng_BmpCompressionMethod = 5,
52 kAlphaBitMasks_BmpCompressionMethod = 6,
53 kCMYK_BmpCompressionMethod = 11,
54 kCMYK8BitRLE_BmpCompressionMethod = 12,
55 kCMYK4BitRLE_BmpCompressionMethod = 13
56 };
57
58 /*
59 * Used to define the input format of the bmp
60 */
61 enum BmpInputFormat {
62 kStandard_BmpInputFormat,
63 kRLE_BmpInputFormat,
64 kBitMask_BmpInputFormat,
65 kUnknown_BmpInputFormat
66 };
67
68 /*
69 * Checks the start of the stream to see if the image is a bitmap
70 */
IsBmp(const void * buffer,size_t bytesRead)71 bool 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 */
MakeFromStream(std::unique_ptr<SkStream> stream,Result * result)82 std::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 */
MakeFromIco(std::unique_ptr<SkStream> stream,Result * result)91 std::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
96 static constexpr uint32_t kBmpHeaderBytes = 14;
97 static constexpr uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
98 static constexpr uint32_t kBmpOS2V1Bytes = 12;
99 static constexpr uint32_t kBmpOS2V2Bytes = 64;
100 static constexpr uint32_t kBmpInfoBaseBytes = 16;
101 static constexpr uint32_t kBmpInfoV1Bytes = 40;
102 static constexpr uint32_t kBmpInfoV2Bytes = 52;
103 static constexpr uint32_t kBmpInfoV3Bytes = 56;
104 static constexpr uint32_t kBmpInfoV4Bytes = 108;
105 static constexpr uint32_t kBmpInfoV5Bytes = 124;
106 static constexpr uint32_t kBmpMaskBytes = 12;
107
get_header_type(size_t infoBytes)108 static BmpHeaderType get_header_type(size_t infoBytes) {
109 if (infoBytes >= kBmpInfoBaseBytes) {
110 // Check the version of the header
111 switch (infoBytes) {
112 case kBmpInfoV1Bytes:
113 return kInfoV1_BmpHeaderType;
114 case kBmpInfoV2Bytes:
115 return kInfoV2_BmpHeaderType;
116 case kBmpInfoV3Bytes:
117 return kInfoV3_BmpHeaderType;
118 case kBmpInfoV4Bytes:
119 return kInfoV4_BmpHeaderType;
120 case kBmpInfoV5Bytes:
121 return kInfoV5_BmpHeaderType;
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:
133 return kOS2VX_BmpHeaderType;
134 default:
135 SkCodecPrintf("Error: unknown bmp header format.\n");
136 return kUnknown_BmpHeaderType;
137 }
138 } if (infoBytes >= kBmpOS2V1Bytes) {
139 // The OS2V1 is treated separately because it has a unique format
140 return kOS2V1_BmpHeaderType;
141 } else {
142 // There are no valid bmp headers
143 SkCodecPrintf("Error: second bitmap header size is invalid.\n");
144 return kUnknown_BmpHeaderType;
145 }
146 }
147
ReadHeader(SkStream * stream,bool inIco,std::unique_ptr<SkCodec> * codecOut)148 SkCodec::Result SkBmpCodec::ReadHeader(SkStream* stream, bool inIco,
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) !=
164 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);
171 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
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) {
240 case kInfoV1_BmpHeaderType:
241 case kInfoV2_BmpHeaderType:
242 case kInfoV3_BmpHeaderType:
243 case kInfoV4_BmpHeaderType:
244 case kInfoV5_BmpHeaderType:
245 case kOS2VX_BmpHeaderType:
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;
267 case kOS2V1_BmpHeaderType:
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;
274 case kUnknown_BmpHeaderType:
275 // We'll exit above in this case.
276 SkASSERT(false);
277 return kInvalidInput;
278 }
279
280 // Check for valid dimensions from header
281 SkCodec::SkScanlineOrder rowOrder = SkCodec::kBottomUp_SkScanlineOrder;
282 if (height < 0) {
283 // We can't negate INT32_MIN.
284 if (height == INT32_MIN) {
285 return kInvalidInput;
286 }
287
288 height = -height;
289 rowOrder = SkCodec::kTopDown_SkScanlineOrder;
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;
310 BmpInputFormat inputFormat = kUnknown_BmpInputFormat;
311 switch (compression) {
312 case kNone_BmpCompressionMethod:
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;
327 case k8BitRLE_BmpCompressionMethod:
328 if (bitsPerPixel != 8) {
329 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
330 bitsPerPixel = 8;
331 }
332 inputFormat = kRLE_BmpInputFormat;
333 break;
334 case k4BitRLE_BmpCompressionMethod:
335 if (bitsPerPixel != 4) {
336 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
337 bitsPerPixel = 4;
338 }
339 inputFormat = kRLE_BmpInputFormat;
340 break;
341 case kAlphaBitMasks_BmpCompressionMethod:
342 case kBitMasks_BmpCompressionMethod:
343 // Load the masks
344 inputFormat = kBitMask_BmpInputFormat;
345 switch (headerType) {
346 case kInfoV1_BmpHeaderType: {
347 // The V1 header stores the bit masks after the header
348 uint8_t buffer[kBmpMaskBytes];
349 if (stream->read(buffer, kBmpMaskBytes) != 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 }
359 case kInfoV2_BmpHeaderType:
360 case kInfoV3_BmpHeaderType:
361 case kInfoV4_BmpHeaderType:
362 case kInfoV5_BmpHeaderType:
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;
392 case kOS2VX_BmpHeaderType:
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;
404 case kJpeg_BmpCompressionMethod:
405 if (24 == bitsPerPixel) {
406 inputFormat = kRLE_BmpInputFormat;
407 break;
408 }
409 [[fallthrough]];
410 case kPng_BmpCompressionMethod:
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;
416 case kCMYK_BmpCompressionMethod:
417 case kCMYK8BitRLE_BmpCompressionMethod:
418 case kCMYK4BitRLE_BmpCompressionMethod:
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) {
441 case kStandard_BmpInputFormat: {
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.
446 SkEncodedInfo::Alpha alpha = inIco ? SkEncodedInfo::kBinary_Alpha :
447 SkEncodedInfo::kOpaque_Alpha;
448 bool isOpaque = true;
449
450 SkEncodedInfo::Color color;
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) {
461 color = SkEncodedInfo::kBGRA_Color;
462 bitsPerComponent = 8;
463 } else {
464 color = SkEncodedInfo::kPalette_Color;
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.
471 color = inIco ? SkEncodedInfo::kBGRA_Color : SkEncodedInfo::kBGR_Color;
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;
479 alpha = SkEncodedInfo::kUnpremul_Alpha;
480 color = SkEncodedInfo::kBGRA_Color;
481 } else {
482 color = SkEncodedInfo::kBGRX_Color;
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()
503 ? kSuccess : kInvalidInput;
504 }
505 return kSuccess;
506 }
507
508 case kBitMask_BmpInputFormat: {
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.
546 SkEncodedInfo::Color color;
547 SkEncodedInfo::Alpha alpha;
548 if (masks->getAlphaMask()) {
549 color = SkEncodedInfo::kBGRA_Color;
550 alpha = SkEncodedInfo::kUnpremul_Alpha;
551 } else {
552 color = SkEncodedInfo::kBGR_Color;
553 alpha = SkEncodedInfo::kOpaque_Alpha;
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()
560 ? kSuccess : kInvalidInput;
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.
586 auto info = SkEncodedInfo::Make(width, height, SkEncodedInfo::kBGRA_Color,
587 SkEncodedInfo::kBinary_Alpha, 8);
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 */
MakeFromStream(std::unique_ptr<SkStream> stream,Result * result,bool inIco)605 std::unique_ptr<SkCodec> SkBmpCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
606 Result* result, bool inIco) {
607 SkASSERT(result);
608 if (!stream) {
609 *result = SkCodec::kInvalidInput;
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
SkBmpCodec(SkEncodedInfo && info,std::unique_ptr<SkStream> stream,uint16_t bitsPerPixel,SkCodec::SkScanlineOrder rowOrder)621 SkBmpCodec::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
onRewind()630 bool SkBmpCodec::onRewind() {
631 return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr) == kSuccess;
632 }
633
getDstRow(int32_t y,int32_t height) const634 int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) const {
635 if (SkCodec::kTopDown_SkScanlineOrder == fRowOrder) {
636 return y;
637 }
638 SkASSERT(SkCodec::kBottomUp_SkScanlineOrder == fRowOrder);
639 return height - y - 1;
640 }
641
prepareToDecode(const SkImageInfo & dstInfo,const SkCodec::Options & options)642 SkCodec::Result SkBmpCodec::prepareToDecode(const SkImageInfo& dstInfo,
643 const SkCodec::Options& options) {
644 return this->onPrepareToDecode(dstInfo, options);
645 }
646
onStartScanlineDecode(const SkImageInfo & dstInfo,const SkCodec::Options & options)647 SkCodec::Result SkBmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
648 const SkCodec::Options& options) {
649 return prepareToDecode(dstInfo, options);
650 }
651
onGetScanlines(void * dst,int count,size_t rowBytes)652 int 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
skipRows(int count)660 bool SkBmpCodec::skipRows(int count) {
661 const size_t bytesToSkip = count * fSrcRowBytes;
662 return this->stream()->skip(bytesToSkip) == bytesToSkip;
663 }
664
onSkipScanlines(int count)665 bool SkBmpCodec::onSkipScanlines(int count) {
666 return this->skipRows(count);
667 }
668
669 namespace SkBmpDecoder {
IsBmp(const void * data,size_t len)670 bool IsBmp(const void* data, size_t len) {
671 return SkBmpCodec::IsBmp(data, len);
672 }
673
Decode(std::unique_ptr<SkStream> stream,SkCodec::Result * outResult,SkCodecs::DecodeContext)674 std::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
Decode(sk_sp<SkData> data,SkCodec::Result * outResult,SkCodecs::DecodeContext)684 std::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
696