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