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 "SkColorPriv.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 */
NewFromStream(SkStream * stream)70 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
71 return SkBmpCodec::NewFromStream(stream, false);
72 }
73
74 /*
75 * Creates a bmp decoder for a bmp embedded in ico
76 * Reads enough of the stream to determine the image format
77 */
NewFromIco(SkStream * stream)78 SkCodec* SkBmpCodec::NewFromIco(SkStream* stream) {
79 return SkBmpCodec::NewFromStream(stream, true);
80 }
81
82 // Header size constants
83 static const uint32_t kBmpHeaderBytes = 14;
84 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
85 static const uint32_t kBmpOS2V1Bytes = 12;
86 static const uint32_t kBmpOS2V2Bytes = 64;
87 static const uint32_t kBmpInfoBaseBytes = 16;
88 static const uint32_t kBmpInfoV1Bytes = 40;
89 static const uint32_t kBmpInfoV2Bytes = 52;
90 static const uint32_t kBmpInfoV3Bytes = 56;
91 static const uint32_t kBmpInfoV4Bytes = 108;
92 static const uint32_t kBmpInfoV5Bytes = 124;
93 static const uint32_t kBmpMaskBytes = 12;
94
get_header_type(size_t infoBytes)95 static BmpHeaderType get_header_type(size_t infoBytes) {
96 if (infoBytes >= kBmpInfoBaseBytes) {
97 // Check the version of the header
98 switch (infoBytes) {
99 case kBmpInfoV1Bytes:
100 return kInfoV1_BmpHeaderType;
101 case kBmpInfoV2Bytes:
102 return kInfoV2_BmpHeaderType;
103 case kBmpInfoV3Bytes:
104 return kInfoV3_BmpHeaderType;
105 case kBmpInfoV4Bytes:
106 return kInfoV4_BmpHeaderType;
107 case kBmpInfoV5Bytes:
108 return kInfoV5_BmpHeaderType;
109 case 16:
110 case 20:
111 case 24:
112 case 28:
113 case 32:
114 case 36:
115 case 42:
116 case 46:
117 case 48:
118 case 60:
119 case kBmpOS2V2Bytes:
120 return kOS2VX_BmpHeaderType;
121 default:
122 SkCodecPrintf("Error: unknown bmp header format.\n");
123 return kUnknown_BmpHeaderType;
124 }
125 } if (infoBytes >= kBmpOS2V1Bytes) {
126 // The OS2V1 is treated separately because it has a unique format
127 return kOS2V1_BmpHeaderType;
128 } else {
129 // There are no valid bmp headers
130 SkCodecPrintf("Error: second bitmap header size is invalid.\n");
131 return kUnknown_BmpHeaderType;
132 }
133 }
134
135 /*
136 * Read enough of the stream to initialize the SkBmpCodec. Returns a bool
137 * representing success or failure. If it returned true, and codecOut was
138 * not nullptr, it will be set to a new SkBmpCodec.
139 * Does *not* take ownership of the passed in SkStream.
140 */
ReadHeader(SkStream * stream,bool inIco,SkCodec ** codecOut)141 bool SkBmpCodec::ReadHeader(SkStream* stream, bool inIco, SkCodec** codecOut) {
142 // The total bytes in the bmp file
143 // We only need to use this value for RLE decoding, so we will only
144 // check that it is valid in the RLE case.
145 uint32_t totalBytes;
146 // The offset from the start of the file where the pixel data begins
147 uint32_t offset;
148 // The size of the second (info) header in bytes
149 uint32_t infoBytes;
150
151 // Bmps embedded in Icos skip the first Bmp header
152 if (!inIco) {
153 // Read the first header and the size of the second header
154 std::unique_ptr<uint8_t[]> hBuffer(new uint8_t[kBmpHeaderBytesPlusFour]);
155 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
156 kBmpHeaderBytesPlusFour) {
157 SkCodecPrintf("Error: unable to read first bitmap header.\n");
158 return false;
159 }
160
161 totalBytes = get_int(hBuffer.get(), 2);
162 offset = get_int(hBuffer.get(), 10);
163 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
164 SkCodecPrintf("Error: invalid starting location for pixel data\n");
165 return false;
166 }
167
168 // The size of the second (info) header in bytes
169 // The size is the first field of the second header, so we have already
170 // read the first four infoBytes.
171 infoBytes = get_int(hBuffer.get(), 14);
172 if (infoBytes < kBmpOS2V1Bytes) {
173 SkCodecPrintf("Error: invalid second header size.\n");
174 return false;
175 }
176 } else {
177 // This value is only used by RLE compression. Bmp in Ico files do not
178 // use RLE. If the compression field is incorrectly signaled as RLE,
179 // we will catch this and signal an error below.
180 totalBytes = 0;
181
182 // Bmps in Ico cannot specify an offset. We will always assume that
183 // pixel data begins immediately after the color table. This value
184 // will be corrected below.
185 offset = 0;
186
187 // Read the size of the second header
188 std::unique_ptr<uint8_t[]> hBuffer(new uint8_t[4]);
189 if (stream->read(hBuffer.get(), 4) != 4) {
190 SkCodecPrintf("Error: unable to read size of second bitmap header.\n");
191 return false;
192 }
193 infoBytes = get_int(hBuffer.get(), 0);
194 if (infoBytes < kBmpOS2V1Bytes) {
195 SkCodecPrintf("Error: invalid second header size.\n");
196 return false;
197 }
198 }
199
200 // Determine image information depending on second header format
201 const BmpHeaderType headerType = get_header_type(infoBytes);
202 if (kUnknown_BmpHeaderType == headerType) {
203 return false;
204 }
205
206 // We already read the first four bytes of the info header to get the size
207 const uint32_t infoBytesRemaining = infoBytes - 4;
208
209 // Read the second header
210 std::unique_ptr<uint8_t[]> iBuffer(new uint8_t[infoBytesRemaining]);
211 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
212 SkCodecPrintf("Error: unable to read second bitmap header.\n");
213 return false;
214 }
215
216 // The number of bits used per pixel in the pixel data
217 uint16_t bitsPerPixel;
218
219 // The compression method for the pixel data
220 uint32_t compression = kNone_BmpCompressionMethod;
221
222 // Number of colors in the color table, defaults to 0 or max (see below)
223 uint32_t numColors = 0;
224
225 // Bytes per color in the color table, early versions use 3, most use 4
226 uint32_t bytesPerColor;
227
228 // The image width and height
229 int width, height;
230
231 switch (headerType) {
232 case kInfoV1_BmpHeaderType:
233 case kInfoV2_BmpHeaderType:
234 case kInfoV3_BmpHeaderType:
235 case kInfoV4_BmpHeaderType:
236 case kInfoV5_BmpHeaderType:
237 case kOS2VX_BmpHeaderType:
238 // We check the size of the header before entering the if statement.
239 // We should not reach this point unless the size is large enough for
240 // these required fields.
241 SkASSERT(infoBytesRemaining >= 12);
242 width = get_int(iBuffer.get(), 0);
243 height = get_int(iBuffer.get(), 4);
244 bitsPerPixel = get_short(iBuffer.get(), 10);
245
246 // Some versions do not have these fields, so we check before
247 // overwriting the default value.
248 if (infoBytesRemaining >= 16) {
249 compression = get_int(iBuffer.get(), 12);
250 if (infoBytesRemaining >= 32) {
251 numColors = get_int(iBuffer.get(), 28);
252 }
253 }
254
255 // All of the headers that reach this point, store color table entries
256 // using 4 bytes per pixel.
257 bytesPerColor = 4;
258 break;
259 case kOS2V1_BmpHeaderType:
260 // The OS2V1 is treated separately because it has a unique format
261 width = (int) get_short(iBuffer.get(), 0);
262 height = (int) get_short(iBuffer.get(), 2);
263 bitsPerPixel = get_short(iBuffer.get(), 6);
264 bytesPerColor = 3;
265 break;
266 case kUnknown_BmpHeaderType:
267 // We'll exit above in this case.
268 SkASSERT(false);
269 return false;
270 }
271
272 // Check for valid dimensions from header
273 SkCodec::SkScanlineOrder rowOrder = SkCodec::kBottomUp_SkScanlineOrder;
274 if (height < 0) {
275 height = -height;
276 rowOrder = SkCodec::kTopDown_SkScanlineOrder;
277 }
278 // The height field for bmp in ico is double the actual height because they
279 // contain an XOR mask followed by an AND mask
280 if (inIco) {
281 height /= 2;
282 }
283
284 // Arbitrary maximum. Matches Chromium.
285 constexpr int kMaxDim = 1 << 16;
286 if (width <= 0 || height <= 0 || width >= kMaxDim || height >= kMaxDim) {
287 SkCodecPrintf("Error: invalid bitmap dimensions.\n");
288 return false;
289 }
290
291 // Create mask struct
292 SkMasks::InputMasks inputMasks;
293 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
294
295 // Determine the input compression format and set bit masks if necessary
296 uint32_t maskBytes = 0;
297 BmpInputFormat inputFormat = kUnknown_BmpInputFormat;
298 switch (compression) {
299 case kNone_BmpCompressionMethod:
300 inputFormat = kStandard_BmpInputFormat;
301
302 // In addition to more standard pixel compression formats, bmp supports
303 // the use of bit masks to determine pixel components. The standard
304 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
305 // which does not map well to any Skia color formats. For this reason,
306 // we will always enable mask mode with 16 bits per pixel.
307 if (16 == bitsPerPixel) {
308 inputMasks.red = 0x7C00;
309 inputMasks.green = 0x03E0;
310 inputMasks.blue = 0x001F;
311 inputFormat = kBitMask_BmpInputFormat;
312 }
313 break;
314 case k8BitRLE_BmpCompressionMethod:
315 if (bitsPerPixel != 8) {
316 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
317 bitsPerPixel = 8;
318 }
319 inputFormat = kRLE_BmpInputFormat;
320 break;
321 case k4BitRLE_BmpCompressionMethod:
322 if (bitsPerPixel != 4) {
323 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
324 bitsPerPixel = 4;
325 }
326 inputFormat = kRLE_BmpInputFormat;
327 break;
328 case kAlphaBitMasks_BmpCompressionMethod:
329 case kBitMasks_BmpCompressionMethod:
330 // Load the masks
331 inputFormat = kBitMask_BmpInputFormat;
332 switch (headerType) {
333 case kInfoV1_BmpHeaderType: {
334 // The V1 header stores the bit masks after the header
335 std::unique_ptr<uint8_t[]> mBuffer(new uint8_t[kBmpMaskBytes]);
336 if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
337 kBmpMaskBytes) {
338 SkCodecPrintf("Error: unable to read bit inputMasks.\n");
339 return false;
340 }
341 maskBytes = kBmpMaskBytes;
342 inputMasks.red = get_int(mBuffer.get(), 0);
343 inputMasks.green = get_int(mBuffer.get(), 4);
344 inputMasks.blue = get_int(mBuffer.get(), 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 false;
387 default:
388 SkCodecPrintf("Error: invalid bmp bit masks header.\n");
389 return false;
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 false;
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 false;
410 default:
411 SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
412 return false;
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 false;
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 false;
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 const SkEncodedInfo info = SkEncodedInfo::Make(color, alpha, bitsPerComponent);
485 *codecOut = new SkBmpStandardCodec(width, height, info, stream, bitsPerPixel,
486 numColors, bytesPerColor, offset - bytesRead, rowOrder, isOpaque, inIco);
487 }
488 return true;
489 }
490
491 case kBitMask_BmpInputFormat: {
492 // Bmp-in-Ico must be standard mode
493 if (inIco) {
494 SkCodecPrintf("Error: Icos may not use bit mask format.\n");
495 return false;
496 }
497
498 switch (bitsPerPixel) {
499 case 16:
500 case 24:
501 case 32:
502 break;
503 default:
504 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
505 return false;
506 }
507
508 // Skip to the start of the pixel array.
509 // We can do this here because there is no color table to read
510 // in bit mask mode.
511 if (stream->skip(offset - bytesRead) != offset - bytesRead) {
512 SkCodecPrintf("Error: unable to skip to image data.\n");
513 return false;
514 }
515
516 if (codecOut) {
517 // Check that input bit masks are valid and create the masks object
518 std::unique_ptr<SkMasks> masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
519 if (nullptr == masks) {
520 SkCodecPrintf("Error: invalid input masks.\n");
521 return false;
522 }
523
524 // Masked bmps are not a great fit for SkEncodedInfo, since they have
525 // arbitrary component orderings and bits per component. Here we choose
526 // somewhat reasonable values - it's ok that we don't match exactly
527 // because SkBmpMaskCodec has its own mask swizzler anyway.
528 SkEncodedInfo::Color color;
529 SkEncodedInfo::Alpha alpha;
530 if (masks->getAlphaMask()) {
531 color = SkEncodedInfo::kBGRA_Color;
532 alpha = SkEncodedInfo::kUnpremul_Alpha;
533 } else {
534 color = SkEncodedInfo::kBGR_Color;
535 alpha = SkEncodedInfo::kOpaque_Alpha;
536 }
537 const SkEncodedInfo info = SkEncodedInfo::Make(color, alpha, 8);
538 *codecOut = new SkBmpMaskCodec(width, height, info, stream, bitsPerPixel,
539 masks.release(), rowOrder);
540 }
541 return true;
542 }
543
544 case kRLE_BmpInputFormat: {
545 // We should not reach this point without a valid value of bitsPerPixel.
546 SkASSERT(4 == bitsPerPixel || 8 == bitsPerPixel || 24 == bitsPerPixel);
547
548 // Check for a valid number of total bytes when in RLE mode
549 if (totalBytes <= offset) {
550 SkCodecPrintf("Error: RLE requires valid input size.\n");
551 return false;
552 }
553
554 // Bmp-in-Ico must be standard mode
555 // When inIco is true, this line cannot be reached, since we
556 // require that RLE Bmps have a valid number of totalBytes, and
557 // Icos skip the header that contains totalBytes.
558 SkASSERT(!inIco);
559
560 if (codecOut) {
561 // RLE inputs may skip pixels, leaving them as transparent. This
562 // is uncommon, but we cannot be certain that an RLE bmp will be
563 // opaque or that we will be able to represent it with a palette.
564 // For that reason, we always indicate that we are kBGRA.
565 const SkEncodedInfo info = SkEncodedInfo::Make(SkEncodedInfo::kBGRA_Color,
566 SkEncodedInfo::kBinary_Alpha, 8);
567 *codecOut = new SkBmpRLECodec(width, height, info, stream, bitsPerPixel, numColors,
568 bytesPerColor, offset - bytesRead, rowOrder);
569 }
570 return true;
571 }
572 default:
573 SkASSERT(false);
574 return false;
575 }
576 }
577
578 /*
579 * Creates a bmp decoder
580 * Reads enough of the stream to determine the image format
581 */
NewFromStream(SkStream * stream,bool inIco)582 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool inIco) {
583 std::unique_ptr<SkStream> streamDeleter(stream);
584 SkCodec* codec = nullptr;
585 if (ReadHeader(stream, inIco, &codec)) {
586 // codec has taken ownership of stream, so we do not need to
587 // delete it.
588 SkASSERT(codec);
589 streamDeleter.release();
590 return codec;
591 }
592 return nullptr;
593 }
594
SkBmpCodec(int width,int height,const SkEncodedInfo & info,SkStream * stream,uint16_t bitsPerPixel,SkCodec::SkScanlineOrder rowOrder)595 SkBmpCodec::SkBmpCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream,
596 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder)
597 : INHERITED(width, height, info, stream, SkColorSpace::MakeSRGB())
598 , fBitsPerPixel(bitsPerPixel)
599 , fRowOrder(rowOrder)
600 , fSrcRowBytes(SkAlign4(compute_row_bytes(width, fBitsPerPixel)))
601 , fXformBuffer(nullptr)
602 {}
603
onRewind()604 bool SkBmpCodec::onRewind() {
605 return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr);
606 }
607
getDstRow(int32_t y,int32_t height) const608 int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) const {
609 if (SkCodec::kTopDown_SkScanlineOrder == fRowOrder) {
610 return y;
611 }
612 SkASSERT(SkCodec::kBottomUp_SkScanlineOrder == fRowOrder);
613 return height - y - 1;
614 }
615
prepareToDecode(const SkImageInfo & dstInfo,const SkCodec::Options & options,SkPMColor inputColorPtr[],int * inputColorCount)616 SkCodec::Result SkBmpCodec::prepareToDecode(const SkImageInfo& dstInfo,
617 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) {
618 if (!conversion_possible(dstInfo, this->getInfo()) ||
619 !this->initializeColorXform(dstInfo, options.fPremulBehavior))
620 {
621 return kInvalidConversion;
622 }
623
624 return this->onPrepareToDecode(dstInfo, options, inputColorPtr, inputColorCount);
625 }
626
onStartScanlineDecode(const SkImageInfo & dstInfo,const SkCodec::Options & options,SkPMColor inputColorPtr[],int * inputColorCount)627 SkCodec::Result SkBmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
628 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) {
629 return prepareToDecode(dstInfo, options, inputColorPtr, inputColorCount);
630 }
631
onGetScanlines(void * dst,int count,size_t rowBytes)632 int SkBmpCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
633 // Create a new image info representing the portion of the image to decode
634 SkImageInfo rowInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);
635
636 // Decode the requested rows
637 return this->decodeRows(rowInfo, dst, rowBytes, this->options());
638 }
639
skipRows(int count)640 bool SkBmpCodec::skipRows(int count) {
641 const size_t bytesToSkip = count * fSrcRowBytes;
642 return this->stream()->skip(bytesToSkip) == bytesToSkip;
643 }
644
onSkipScanlines(int count)645 bool SkBmpCodec::onSkipScanlines(int count) {
646 return this->skipRows(count);
647 }
648
applyColorXform(const SkImageInfo & dstInfo,void * dst,void * src) const649 void SkBmpCodec::applyColorXform(const SkImageInfo& dstInfo, void* dst, void* src) const {
650 SkColorSpaceXform* xform = this->colorXform();
651 if (xform) {
652 const SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType());
653 const SkColorSpaceXform::ColorFormat srcFormat = select_xform_format(kXformSrcColorType);
654 const SkAlphaType alphaType = select_xform_alpha(dstInfo.alphaType(),
655 this->getInfo().alphaType());
656 SkAssertResult(xform->apply(dstFormat, dst, srcFormat, src, dstInfo.width(),
657 alphaType));
658 }
659 }
660