Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: src/codec/SkCodec_libbmp.cpp

Issue 947283002: Bmp Image Decoding (Closed) Base URL: https://skia.googlesource.com/skia.git@decode-leon-3
Patch Set: separate swizzler for masks Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "SkCodec_libbmp.h"
9 #include "SkColorPriv.h"
10 #include "SkEndian.h"
11 #include "SkStream.h"
12
13 /*
14 *
15 * Get a byte from the buffer
16 *
17 */
18 uint8_t get_byte(uint8_t* buffer, uint32_t i) {
19 return buffer[i];
20 }
21
22 /*
23 *
24 * Get a short from the buffer
25 *
26 */
27 uint16_t get_short(uint8_t* buffer, uint32_t i) {
28 uint16_t result;
29 memcpy(&result, &(buffer[i]), 2);
30 #ifdef SK_CPU_BENDIAN
31 return SkEndianSwap16(result);
32 #else
33 return result;
34 #endif
35 }
36
37 /*
38 *
39 * Get an int from the buffer
40 *
41 */
42 uint32_t get_int(uint8_t* buffer, uint32_t i) {
43 uint32_t result;
44 memcpy(&result, &(buffer[i]), 4);
45 #ifdef SK_CPU_BENDIAN
46 return SkEndianSwap32(result);
47 #else
48 return result;
49 #endif
50 }
51
52 static bool premul_and_unpremul(SkAlphaType dst, SkAlphaType src) {
53 return kPremul_SkAlphaType == dst && kUnpremul_SkAlphaType == src;
54 }
55
56 /*
57 *
58 * Checks if the conversion between the input image and the requested output
59 * image has been implemented
60 *
61 */
62 static bool conversion_possible(const SkImageInfo& dst,
63 const SkImageInfo& src) {
64 // TODO: Support more conversions
65 if (kN32_SkColorType != dst.colorType()) {
66 return false;
67 }
68 if (dst.alphaType() == src.alphaType()) {
69 return true;
70 }
71 return premul_and_unpremul(dst.alphaType(), src.alphaType())
72 || premul_and_unpremul(dst.alphaType(), src.alphaType());
73 }
74
75 /*
76 *
77 * Compute row bytes for an image
78 *
79 */
80 size_t compute_row_bytes(int width, uint32_t bitsPerPixel) {
81 if (bitsPerPixel < 16) {
82 SkASSERT(0 == 8 % bitsPerPixel);
scroggo 2015/03/11 14:23:10 This could be done once outside the if statement.
msarett 2015/03/11 18:53:05 The assert is actually slightly different. 8 % bpp
scroggo 2015/03/11 19:22:45 D'oh! Nvm.
83 const uint32_t pixelsPerByte = 8 / bitsPerPixel;
84 return (width + pixelsPerByte - 1) / pixelsPerByte;
85 } else {
86 SkASSERT(0 == bitsPerPixel % 8);
87 const uint32_t bytesPerPixel = bitsPerPixel / 8;
88 return width * bytesPerPixel;
89 }
90 }
91
92 /*
93 *
94 * Defines the version and type of the second bitmap header
95 *
96 */
97 enum BitmapHeaderType {
98 kInfoV1_BitmapHeaderType,
99 kInfoV2_BitmapHeaderType,
100 kInfoV3_BitmapHeaderType,
101 kInfoV4_BitmapHeaderType,
102 kInfoV5_BitmapHeaderType,
103 kOS2V1_BitmapHeaderType,
104 kOS2VX_BitmapHeaderType,
105 kUnknown_BitmapHeaderType
106 };
107
108 /*
109 *
110 * Possible bitmap compression types
111 *
112 */
113 enum BitmapCompressionMethod {
114 kNone_BitmapCompressionMethod = 0,
115 k8BitRLE_BitmapCompressionMethod = 1,
116 k4BitRLE_BitmapCompressionMethod = 2,
117 kBitMasks_BitmapCompressionMethod = 3,
118 kJpeg_BitmapCompressionMethod = 4,
119 kPng_BitmapCompressionMethod = 5,
120 kAlphaBitMasks_BitmapCompressionMethod = 6,
121 kCMYK_BitmapCompressionMethod = 11,
122 kCMYK8BitRLE_BitmapCompressionMethod = 12,
123 kCMYK4BitRLE_BitmapCompressionMethod = 13
124 };
125
126 /*
127 *
128 * Checks the start of the stream to see if the image is a bitmap
129 *
130 */
131 bool SkBmpCodec::IsBmp(SkStream* stream) {
132 // TODO: Support "IC", "PT", "CI", "CP", "BA"
133 // TODO: ICO files may contain a BMP and need to use this decoder
134 const char bmpSig[] = { 'B', 'M' };
135 char buffer[sizeof(bmpSig)];
136 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) &&
137 !memcmp(buffer, bmpSig, sizeof(bmpSig));
138 }
139
140 /*
141 *
142 * Assumes IsBmp was called and returned true
143 * Creates a bitmap decoder
144 * Reads enough of the stream to determine the image format
145 *
146 */
147 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
148 // Header size constants
149 static const uint32_t kBmpHeaderBytes = 14;
150 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
151 static const uint32_t kBmpOS2V1Bytes = 12;
152 static const uint32_t kBmpOS2V2Bytes = 64;
153 static const uint32_t kBmpInfoBaseBytes = 16;
154 static const uint32_t kBmpInfoV1Bytes = 40;
155 static const uint32_t kBmpInfoV2Bytes = 52;
156 static const uint32_t kBmpInfoV3Bytes = 56;
157 static const uint32_t kBmpInfoV4Bytes = 108;
158 static const uint32_t kBmpInfoV5Bytes = 124;
159 static const uint32_t kBmpMaskBytes = 12;
160
161 // Read the first header and the size of the second header
162 SkAutoTDeleteArray<uint8_t> hBuffer(
163 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour));
164 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
165 kBmpHeaderBytesPlusFour) {
166 SkDebugf("Error: unable to read first bitmap header.\n");
167 return NULL;
168 }
169
170 // The total bytes in the bmp file
171 // We only need to use this value for RLE decoding, so we will only check
172 // that it is valid in the RLE case.
173 const uint32_t totalBytes = get_int(hBuffer.get(), 2);
174
175 // The offset from the start of the file where the pixel data begins
176 const uint32_t offset = get_int(hBuffer.get(), 10);
177 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
178 SkDebugf("Error: invalid starting location for pixel data\n");
179 return NULL;
180 }
181
182 // The size of the second (info) header in bytes
183 // The size is the first field of the second header, so we have already
184 // read the first four infoBytes.
185 const uint32_t infoBytes = get_int(hBuffer.get(), 14);
186 if (infoBytes < kBmpOS2V1Bytes) {
187 SkDebugf("Error: invalid second header size.\n");
188 return NULL;
189 }
190 const uint32_t infoBytesRemaining = infoBytes - 4;
191 hBuffer.free();
192
193 // Read the second header
194 SkAutoTDeleteArray<uint8_t> iBuffer(
195 SkNEW_ARRAY(uint8_t, infoBytesRemaining));
196 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
197 SkDebugf("Error: unable to read second bitmap header.\n");
198 return NULL;
199 }
200
201 // The number of bits used per pixel in the pixel data
202 uint16_t bitsPerPixel;
203
204 // The compression method for the pixel data
205 uint32_t compression = kNone_BitmapCompressionMethod;
206
207 // Number of colors in the color table, defaults to 0 or max (see below)
208 uint32_t numColors = 0;
209
210 // Bytes per color in the color table, early versions use 3, most use 4
211 uint32_t bytesPerColor;
212
213 // The image width and height
214 int width, height;
215
216 // Determine image information depending on second header format
217 BitmapHeaderType headerType;
218 if (infoBytes >= kBmpInfoBaseBytes) {
219 // Check the version of the header
220 switch (infoBytes) {
221 case kBmpInfoV1Bytes:
222 headerType = kInfoV1_BitmapHeaderType;
223 break;
224 case kBmpInfoV2Bytes:
225 headerType = kInfoV2_BitmapHeaderType;
226 break;
227 case kBmpInfoV3Bytes:
228 headerType = kInfoV3_BitmapHeaderType;
229 break;
230 case kBmpInfoV4Bytes:
231 headerType = kInfoV4_BitmapHeaderType;
232 break;
233 case kBmpInfoV5Bytes:
234 headerType = kInfoV5_BitmapHeaderType;
235 break;
236 case 16:
237 case 20:
238 case 24:
239 case 28:
240 case 32:
241 case 36:
242 case 42:
243 case 46:
244 case 48:
245 case 60:
246 case kBmpOS2V2Bytes:
247 headerType = kOS2VX_BitmapHeaderType;
248 break;
249 default:
250 // We do not signal an error here because there is the
251 // possibility of new or undocumented bmp header types. Most
252 // of the newer versions of bmp headers are similar to and
253 // build off of the older versions, so we may still be able to
254 // decode the bmp.
255 SkDebugf("Warning: unknown bmp header format.\n");
256 headerType = kUnknown_BitmapHeaderType;
257 break;
258 }
259 // We check the size of the header before entering the if statement.
260 // We should not reach this point unless the size is large enough for
261 // these required fields.
262 SkASSERT(infoBytesRemaining >= 12);
263 width = get_int(iBuffer.get(), 0);
264 height = get_int(iBuffer.get(), 4);
265 //uint16_t planes = get_short(iBuffer, 8);
266 bitsPerPixel = get_short(iBuffer.get(), 10);
267
268 // Some versions do not have this field, so we check before
269 // overwriting the default value.
270 if (infoBytesRemaining >= 16) {
271 compression = get_int(iBuffer.get(), 12);
272 }
273
274 // Some versions do not have this field, so we check before
275 // overwriting the default value.
276 if (infoBytesRemaining >= 32) {
277 numColors = get_int(iBuffer.get(), 28);
278 }
279
280 bytesPerColor = 4;
281 } else if (infoBytes >= kBmpOS2V1Bytes) {
282 // The OS2V1 is treated separately because it has a unique format
283 headerType = kOS2V1_BitmapHeaderType;
284 width = (int) get_short(iBuffer.get(), 0);
285 height = (int) get_short(iBuffer.get(), 2);
286 bitsPerPixel = get_short(iBuffer.get(), 6);
287 bytesPerColor = 3;
288 } else {
289 // There are no valid bmp headers
290 SkDebugf("Error: second bitmap header size is invalid.\n");
291 return NULL;
292 }
293
294 // Check for valid dimensions from header
295 RowOrder rowOrder = kBottomUp_RowOrder;
296 if (height < 0) {
297 height = -height;
298 rowOrder = kTopDown_RowOrder;
299 }
300 static const uint32_t kBmpMaxDim = 1 << 16;
301 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) {
302 // TODO: Decide if we want to support really large bmps.
303 SkDebugf("Error: invalid bitmap dimensions.\n");
304 return NULL;
305 }
306
307 // Create mask struct
308 SkMaskSwizzler::InputMasks masks;
309 memset(&masks, 0, 4*sizeof(uint32_t));
310
311 // Determine the input compression format and set bit masks if necessary
312 uint32_t maskBytes = 0;
313 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat;
314 switch (compression) {
315 case kNone_BitmapCompressionMethod:
316 inputFormat = kStandard_BitmapInputFormat;
317 break;
318 case k8BitRLE_BitmapCompressionMethod:
319 if (bitsPerPixel != 8) {
320 SkDebugf("Warning: correcting invalid bitmap format.\n");
321 bitsPerPixel = 8;
322 }
323 inputFormat = kRLE_BitmapInputFormat;
324 break;
325 case k4BitRLE_BitmapCompressionMethod:
326 if (bitsPerPixel != 4) {
327 SkDebugf("Warning: correcting invalid bitmap format.\n");
328 bitsPerPixel = 4;
329 }
330 inputFormat = kRLE_BitmapInputFormat;
331 break;
332 case kAlphaBitMasks_BitmapCompressionMethod:
333 case kBitMasks_BitmapCompressionMethod:
334 // Load the masks
335 inputFormat = kBitMask_BitmapInputFormat;
336 switch (headerType) {
337 case kInfoV1_BitmapHeaderType: {
338 // The V1 header stores the bit masks after the header
339 SkAutoTDeleteArray<uint8_t> mBuffer(
340 SkNEW_ARRAY(uint8_t, kBmpMaskBytes));
341 if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
342 kBmpMaskBytes) {
343 SkDebugf("Error: unable to read bit masks.\n");
344 return NULL;
345 }
346 maskBytes = kBmpMaskBytes;
347 masks.red = get_int(mBuffer.get(), 0);
scroggo 2015/03/11 14:23:10 Could any of these values be invalid? Or are all v
msarett 2015/03/11 18:53:05 In this version, minimal checking was performed.
348 masks.green = get_int(mBuffer.get(), 4);
349 masks.blue = get_int(mBuffer.get(), 8);
350 break;
351 }
352 case kInfoV2_BitmapHeaderType:
353 case kInfoV3_BitmapHeaderType:
354 case kInfoV4_BitmapHeaderType:
355 case kInfoV5_BitmapHeaderType:
356 // Header types are matched based on size. If the header
357 // is V2+, we are guaranteed to be able at least this size.
358 SkASSERT(infoBytesRemaining >= 48);
359 masks.red = get_int(iBuffer.get(), 36);
360 masks.green = get_int(iBuffer.get(), 40);
361 masks.blue = get_int(iBuffer.get(), 44);
362 break;
363 case kOS2VX_BitmapHeaderType:
364 // TODO: Decide if we intend to support this.
365 // It is unsupported in the previous version and
366 // in chromium. I have not come across a test case
367 // that uses this format.
368 SkDebugf("Error: huffman format unsupported.\n");
369 return NULL;
370 default:
371 SkDebugf("Error: invalid bmp bit masks header.\n");
372 return NULL;
373 }
374 break;
375 case kJpeg_BitmapCompressionMethod:
376 if (24 == bitsPerPixel) {
377 inputFormat = kRLE_BitmapInputFormat;
378 break;
379 }
380 // Fall through
381 case kPng_BitmapCompressionMethod:
382 // TODO: Decide if we intend to support this.
383 // It is unsupported in the previous version and
384 // in chromium. I think it is used mostly for printers.
385 SkDebugf("Error: compression format not supported.\n");
386 return NULL;
387 case kCMYK_BitmapCompressionMethod:
388 case kCMYK8BitRLE_BitmapCompressionMethod:
389 case kCMYK4BitRLE_BitmapCompressionMethod:
390 // TODO: Same as above.
391 SkDebugf("Error: CMYK not supported for bitmap decoding.\n");
392 return NULL;
393 default:
394 SkDebugf("Error: invalid format for bitmap decoding.\n");
395 return NULL;
396 }
397
398 // Most versions of bmps should be rendered as opaque. Either they do
399 // not have an alpha channel, or they expect the alpha channel to be
400 // ignored. V4+ bmp files introduce an alpha mask and allow the creator
401 // of the image to use the alpha channels. However, many of these images
402 // leave the alpha channel blank and expect to be rendered as opaque. For
403 // this reason, we set the alpha type to kUnknown for V4+ bmps and figure
404 // out the alpha type during the decode.
405 SkAlphaType alphaType = kOpaque_SkAlphaType;
406 if (kInfoV4_BitmapHeaderType == headerType ||
407 kInfoV5_BitmapHeaderType == headerType) {
408 // Header types are matched based on size. If the header is
409 // V4+, we are guaranteed to be able ro read at least this size.
scroggo 2015/03/11 14:23:10 to* read
msarett 2015/03/11 18:53:05 Fixed
410 SkASSERT(infoBytesRemaining > 52);
411 masks.alpha = get_int(iBuffer.get(), 48);
412 if (masks.alpha != 0) {
413 alphaType = kUnpremul_SkAlphaType;
414 }
415 }
416 iBuffer.free();
417
418 // Check for valid bits per pixel input
419 switch (bitsPerPixel) {
420 // In addition to more standard pixel compression formats, bmp supports
421 // the use of bit masks to determine pixel components. The standard
422 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
423 // which does not map well to any Skia color formats. For this reason,
424 // we will always enable mask mode with 16 bits per pixel.
425 case 16:
426 if (kBitMask_BitmapInputFormat != inputFormat) {
427 masks.red = 0x7C00;
428 masks.green = 0x03E0;
429 masks.blue = 0x001F;
430 inputFormat = kBitMask_BitmapInputFormat;
431 }
432 break;
433 case 1:
434 case 2:
435 case 4:
436 case 8:
437 case 24:
438 case 32:
439 break;
440 default:
441 SkDebugf("Error: invalid input value for bits per pixel.\n");
442 return NULL;
443 }
444
445 // Process the color table
446 uint32_t colorBytes = 0;
447 SkPMColor* colorTable = NULL;
448 if (bitsPerPixel < 16) {
449 // Verify the number of colors for the color table
450 const int maxColors = 1 << bitsPerPixel;
451 // Zero is a default for maxColors
452 // Also set numColors to maxColors when input is too large
453 if (numColors <= 0 || numColors > maxColors) {
454 numColors = maxColors;
455 }
456 colorTable = SkNEW_ARRAY(SkPMColor, maxColors);
457
458 // Construct the color table
459 colorBytes = numColors * bytesPerColor;
460 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
461 if (stream->read(cBuffer.get(), colorBytes) != colorBytes) {
462 SkDebugf("Error: unable to read color table.\n");
463 return NULL;
464 }
465
466 // Fill in the color table
467 uint32_t i = 0;
468 for (; i < numColors; i++) {
469 uint8_t blue = get_byte(cBuffer.get(), i*bytesPerColor);
470 uint8_t green = get_byte(cBuffer.get(), i*bytesPerColor + 1);
471 uint8_t red = get_byte(cBuffer.get(), i*bytesPerColor + 2);
472 uint8_t alpha = 0xFF;
473 if (kOpaque_SkAlphaType != alphaType) {
474 alpha = (masks.alpha >> 24) &
475 get_byte(cBuffer.get(), i*bytesPerColor + 3);
476 }
477 colorTable[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
478 }
479
480 // To avoid segmentation faults on bad pixel data, fill the end of the
481 // color table with black. This is the same the behavior as the
482 // chromium decoder.
483 for (; i < maxColors; i++) {
484 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
485 }
486 } else {
487 // We will not use the color table if bitsPerPixel >= 16, but if there
488 // is a color table, we may need to skip the color table bytes.
489 // We will assume that the maximum color table size is the same as when
490 // there are 8 bits per pixel (the largest color table actually used).
491 // Color tables for greater than 8 bits per pixel are somewhat
492 // undocumented. It is indicated that they may exist to store a list
493 // of colors for optimization on devices with limited color display
494 // capacity. While we do not know for sure, we will guess that any
495 // value of numColors greater than this maximum is invalid.
496 if (numColors <= (1 << 8)) {
497 colorBytes = numColors * bytesPerColor;
498 if (stream->skip(colorBytes) != colorBytes) {
499 SkDebugf("Error: Could not skip color table bytes.\n");
500 return NULL;
501 }
502 }
503 }
504
505 // Ensure that the stream now points to the start of the pixel array
506 uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes + colorBytes;
507
508 // Check that we have not read past the pixel array offset
509 if(bytesRead > offset) {
510 // This may occur on OS 2.1 and other old versions where the color
511 // table defaults to max size, and the bmp tries to use a smaller color
512 // table. This is invalid, and our decision is to indicate an error,
513 // rather than try to guess the intended size of the color table and
514 // rewind the stream to display the image.
515 SkDebugf("Error: pixel data offset less than header size.\n");
516 return NULL;
517 }
518
519 // Skip to the start of the pixel array
520 if (stream->skip(offset - bytesRead) != offset - bytesRead) {
521 SkDebugf("Error: unable to skip to image data.\n");
522 return NULL;
523 }
524
525 // Remaining bytes is only used for RLE
526 const int remainingBytes = totalBytes - offset;
527 if (remainingBytes <= 0 && kRLE_BitmapInputFormat == inputFormat) {
528 SkDebugf("Error: RLE requires valid input size.\n");
529 return NULL;
530 }
531
532 // Return the codec
533 // We will use ImageInfo to store width, height, and alpha type. The Skia
534 // color types do not match with the many possible bmp input color types,
535 // so we will ignore this field and depend on other parameters for input
536 // information.
537 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
538 kUnknown_SkColorType, alphaType);
539 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
540 inputFormat, masks, colorTable, rowOrder,
541 remainingBytes));
542 }
543
544 /*
545 *
546 * Creates an instance of the decoder
547 * Called only by NewFromStream
548 *
549 */
550 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
551 uint16_t bitsPerPixel, BitmapInputFormat inputFormat,
552 SkMaskSwizzler::InputMasks masks, SkPMColor* colorTable,
553 RowOrder rowOrder,
554 const uint32_t remainingBytes)
555 : INHERITED(info, stream)
556 , fBitsPerPixel(bitsPerPixel)
557 , fInputFormat(inputFormat)
558 , fBitMasks(masks)
559 , fColorTable(colorTable)
560 , fRowOrder(rowOrder)
561 , fRemainingBytes(remainingBytes)
562 {}
563
564 /*
565 *
566 * Initiates the bitmap decode
567 *
568 */
569 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
570 void* dst, size_t dstRowBytes,
571 SkPMColor*, int*) {
572 if (!this->couldRewindIfNeeded()) {
573 return kCouldNotRewind;
574 }
575 if (dstInfo.dimensions() != this->getOriginalInfo().dimensions()) {
576 SkDebugf("Error: scaling not supported.\n");
577 return kInvalidScale;
578 }
579 if (!conversion_possible(dstInfo, this->getOriginalInfo())) {
580 SkDebugf("Error: cannot convert input type to output type.\n");
581 return kInvalidConversion;
582 }
583
584 switch (fInputFormat) {
585 case kBitMask_BitmapInputFormat:
586 return decodeMask(dstInfo, dst, dstRowBytes);
587 case kRLE_BitmapInputFormat:
588 return decodeRLE(dstInfo, dst, dstRowBytes);
589 case kStandard_BitmapInputFormat:
590 return decode(dstInfo, dst, dstRowBytes);
591 default:
592 SkASSERT(false);
593 return kInvalidInput;
594 }
595 }
596
597 /*
598 *
599 * Performs the bitmap decoding for bit masks input format
600 *
601 */
602 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
603 void* dst, uint32_t dstRowBytes) {
604 // Set constant values
605 const int width = dstInfo.width();
606 const int height = dstInfo.height();
607 const size_t paddedRowBytes = SkAlign4(
scroggo 2015/03/11 14:23:09 nit: Now that unpaddedRowBytes is no longer in thi
msarett 2015/03/11 18:53:05 You are correct. Fixed.
608 compute_row_bytes(width, fBitsPerPixel));
609 const uint32_t alphaMask = fBitMasks.alpha;
610
611 // Allocate space for a row buffer and a source for the swizzler
612 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, paddedRowBytes));
613
614 // Get the destination start row and delta
615 SkPMColor* dstRow;
616 int32_t delta;
617 if (kTopDown_RowOrder == fRowOrder) {
618 dstRow = (SkPMColor*) dst;
619 delta = dstRowBytes;
620 } else {
621 dstRow = (SkPMColor*) SkTAddOffset<void>(dst, (height-1) * dstRowBytes);
622 delta = -dstRowBytes;
623 }
624
625 // Create the swizzler
626 SkMaskSwizzler* swizzler = SkMaskSwizzler::CreateMaskSwizzler(
627 dstInfo, fBitMasks, fBitsPerPixel);
628
629 // Iterate over rows of the image
630 bool transparent = true;
631 for (uint32_t y = 0; y < height; y++) {
632 // Read a row of the input
633 if (stream()->read(srcBuffer.get(), paddedRowBytes) != paddedRowBytes) {
634 SkDebugf("Warning: incomplete input stream.\n");
635 return kIncompleteInput;
636 }
637
638 // Decode the row in destination format
639 SkSwizzler::ResultAlpha r = swizzler->next(dstRow, srcBuffer.get());
640 transparent &= (SkSwizzler::kTransparent_ResultAlpha == r);
641
642 // Move to the next row
643 dstRow = SkTAddOffset<SkPMColor>(dstRow, delta);
644 }
645
646 // Many fully transparent bmp images are intended to be opaque. Here, we
647 // correct for this possibility.
648 SkPMColor* dstPtr = (SkPMColor*) dst;
649 if (transparent) {
650 for (uint32_t y = 0; y < height; y++) {
651 for (uint32_t x = 0; x < width; x++) {
652 dstPtr[y * dstRowBytes + x] |= 0xFF000000;
scroggo 2015/03/11 14:23:09 nit: We could probably do this faster without doin
msarett 2015/03/11 18:53:05 Agreed. Done.
653 }
654 }
655 }
656
657 // Finished decoding the entire image
658 return kSuccess;
659 }
660
661 /*
662 *
663 * Set an RLE pixel using the color table
664 *
665 */
666 void SkBmpCodec::setRLEPixel(SkPMColor* dst, uint32_t dstRowBytes, int height,
667 uint32_t x, uint32_t y, uint8_t index) {
668 if (kBottomUp_RowOrder == fRowOrder) {
669 y = height - y - 1;
670 }
671 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, y * dstRowBytes);
672 dstRow[x] = fColorTable.get()[index];
673 }
674
675 /*
676 *
677 * Performs the bitmap decoding for RLE input format
678 * RLE decoding is performed all at once, rather than a one row at a time
679 *
680 */
681 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
682 void* dst, uint32_t dstRowBytes) {
683 // Set RLE flags
684 static const uint8_t RLE_ESCAPE = 0;
685 static const uint8_t RLE_EOL = 0;
686 static const uint8_t RLE_EOF = 1;
687 static const uint8_t RLE_DELTA = 2;
688
689 // Set constant values
690 const int width = dstInfo.width();
691 const int height = dstInfo.height();
692
693 // Input buffer parameters
694 uint32_t currByte = 0;
695 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRemainingBytes));
696 uint32_t totalBytes = stream()->read(buffer.get(), fRemainingBytes);
697 if (totalBytes < fRemainingBytes) {
698 SkDebugf("Warning: incomplete RLE file.\n");
699 } else if (totalBytes <= 0) {
700 SkDebugf("Error: could not read RLE image data.\n");
701 return kInvalidInput;
702 }
703
704 // Destination parameters
705 uint32_t x = 0;
706 uint32_t y = 0;
707 // If the code skips pixels, remaining pixels are transparent or black
708 // TODO: Skip this if memory was already zeroed.
709 memset(dst, 0, dstRowBytes * height);
710 SkPMColor* dstPtr = (SkPMColor*) dst;
711
712 while (true) {
713 // Every entry takes at least two bytes
714 if (totalBytes - currByte < 2) {
715 SkDebugf("Warning: incomplete RLE input.\n");
716 return kIncompleteInput;
717 }
718
719 // Read the next two bytes. These bytes have different meanings
720 // depending on their values. In the first interpretation, the first
721 // byte is an escape flag and the second byte indicates what special
722 // task to perform.
723 const uint8_t flag = buffer.get()[currByte++];
724 const uint8_t task = buffer.get()[currByte++];
725
726 // If we have reached a row that is beyond the image size, and the RLE
727 // code does not indicate end of file, abort and signal a warning.
728 if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) {
729 SkDebugf("Warning: invalid RLE input.\n");
730 return kIncompleteInput;
731 }
732
733 // Perform decoding
734 if (RLE_ESCAPE == flag) {
735 switch (task) {
736 case RLE_EOL:
737 x = 0;
738 y++;
739 break;
740 case RLE_EOF:
741 return kSuccess;
742 case RLE_DELTA: {
743 // Two bytes are needed to specify delta
744 if (totalBytes - currByte < 2) {
745 SkDebugf("Warning: incomplete RLE input\n");
746 return kIncompleteInput;
747 }
748 // Modify x and y
749 const uint8_t dx = buffer.get()[currByte++];
750 const uint8_t dy = buffer.get()[currByte++];
751 x += dx;
752 y += dy;
753 if (x > width || y > height) {
754 SkDebugf("Warning: invalid RLE input.\n");
755 return kIncompleteInput;
756 }
757 break;
758 }
759 default: {
760 // If task does not match any of the above signals, it
761 // indicates that we have a sequence of non-RLE pixels.
762 // Furthermore, the value of task is equal to the number
763 // of pixels to interpret.
764 uint8_t numPixels = task;
765 const size_t unpaddedBytes = compute_row_bytes(numPixels,
scroggo 2015/03/11 14:23:10 How about "rowBytes"?
msarett 2015/03/11 18:53:05 Done.
766 fBitsPerPixel);
767 const size_t paddedBytes = SkAlign2(unpaddedBytes);
768 if (x + numPixels > width ||
769 totalBytes - currByte < paddedBytes) {
scroggo 2015/03/11 14:23:10 Can you explain this check? I'm having trouble fol
msarett 2015/03/11 18:53:05 I added a comment. // Abort if setting numPixels m
770 SkDebugf("Warning: invalid RLE input.\n");
771 return kIncompleteInput;
772 }
773 // Set count number of pixels
774 while (numPixels > 0) {
775 switch(fBitsPerPixel) {
776 case 4: {
777 uint8_t val = buffer.get()[currByte++];
778 setRLEPixel(dstPtr, dstRowBytes, height, x++, y,
779 val >> 4);
780 numPixels--;
781 if (numPixels != 0) {
782 setRLEPixel(dstPtr, dstRowBytes, height,
783 x++, y, val & 0xF);
784 numPixels--;
785 }
786 break;
787 }
788 case 8:
789 setRLEPixel(dstPtr, dstRowBytes, height, x++, y,
790 buffer.get()[currByte++]);
791 numPixels--;
792 break;
793 case 24: {
794 uint8_t blue = buffer.get()[currByte++];
795 uint8_t green = buffer.get()[currByte++];
796 uint8_t red = buffer.get()[currByte++];
797 SkPMColor color = SkPackARGB32NoCheck(
798 0xFF, red, green, blue);
799 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(
800 dstPtr, y * dstRowBytes);
801 dstRow[x++] = color;
802 numPixels--;
803 }
804 default:
805 SkASSERT(false);
806 return kInvalidInput;
807 }
808 }
809 // Skip a byte if necessary to maintain alignment
810 if (unpaddedBytes & 1) {
811 currByte++;
812 }
813 break;
814 }
815 }
816 } else {
817 // If the first byte read is not a flag, it indicates the number of
818 // pixels to set in RLE mode.
819 const uint8_t numPixels = flag;
820 const uint32_t endX = SkTMin<uint32_t>(x + numPixels,
821 (uint32_t) width);
822
823 if (24 == fBitsPerPixel) {
824 // In RLE24, the second byte read is part of the pixel color.
825 // There are two more required bytes to finish encoding the
826 // color.
827 if (totalBytes - currByte < 2) {
828 SkDebugf("Warning: incomplete RLE input\n");
829 return kIncompleteInput;
830 }
831
832 // Fill the pixels up to endX with the specified color
833 uint8_t blue = task;
834 uint8_t green = buffer.get()[currByte++];
835 uint8_t red = buffer.get()[currByte++];
836 SkPMColor color = SkPackARGB32NoCheck(0xFF, red, green, blue);
837 SkPMColor* dstRow =
838 SkTAddOffset<SkPMColor>(dstPtr, y * dstRowBytes);
839 while (x < endX) {
840 dstRow[x++] = color;
841 }
842 } else {
843 // In RLE8 or RLE4, the second byte read gives the index in the
844 // color table to look up the pixel color.
845 // RLE8 has one color index that gets repeated
846 // RLE4 has two color indexes in the upper and lower 4 bits of
847 // the bytes, which are alternated
848 uint8_t indices[2] = { task, task };
849 if (4 == fBitsPerPixel) {
850 indices[0] >>= 4;
851 indices[1] &= 0xf;
852 }
853
854 // Set the indicated number of pixels
855 for (int which = 0; x < endX; x++) {
856 setRLEPixel(dstPtr, dstRowBytes, height, x, y,
857 indices[which]);
858 which = !which;
859 }
860 }
861 }
862 }
863 }
864
865 /*
866 *
867 * Performs the bitmap decoding for standard input format
868 *
869 */
870 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
871 void* dst, uint32_t dstRowBytes) {
872 // Set constant values
873 const int width = dstInfo.width();
874 const int height = dstInfo.height();
875 const size_t paddedRowBytes = SkAlign4(
scroggo 2015/03/11 14:23:10 nit: rowBytes
msarett 2015/03/11 18:53:05 Done.
876 compute_row_bytes(width, fBitsPerPixel));
877 const uint32_t alphaMask = fBitMasks.alpha;
878
879 // Get swizzler configuration
880 SkSwizzler::SrcConfig config;
881 switch (fBitsPerPixel) {
882 case 1:
883 config = SkSwizzler::kIndex1;
884 break;
885 case 2:
886 config = SkSwizzler::kIndex2;
887 break;
888 case 4:
889 config = SkSwizzler::kIndex4;
890 break;
891 case 8:
892 config = SkSwizzler::kIndex;
893 break;
894 case 24:
895 config = SkSwizzler::kBGR;
896 break;
897 case 32:
898 if (alphaMask == 0) {
899 config = SkSwizzler::kBGRX;
900 } else {
901 config = SkSwizzler::kBGRA;
902 }
903 break;
904 default:
905 SkASSERT(false);
906 return kInvalidInput;
907 }
908
909 // Create swizzler
910 SkSwizzler* swizzler = SkSwizzler::CreateSwizzler(config, fColorTable.get(),
911 dstInfo, dst, dstRowBytes, false);
912
913 // Allocate space for a row buffer and a source for the swizzler
914 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, paddedRowBytes));
915
916 // Iterate over rows of the image
917 bool transparent = true;
918 for (uint32_t y = 0; y < height; y++) {
919 // Read a row of the input
920 if (stream()->read(srcBuffer.get(), paddedRowBytes) != paddedRowBytes) {
921 SkDebugf("Warning: incomplete input stream.\n");
922 return kIncompleteInput;
923 }
924
925 // Decode the row in destination format
926 uint32_t row;
927 if (kTopDown_RowOrder == fRowOrder) {
928 row = y;
929 } else {
930 row = height - 1 - y;
931 }
932 SkSwizzler::ResultAlpha r = swizzler->next(srcBuffer.get(), row);
933 transparent &= (SkSwizzler::kTransparent_ResultAlpha == r);
934 }
935
936 // Now we adjust the output image with some additional behavior that
937 // SkSwizzler does not support. Firstly, all bmp images that contain
938 // alpha are masked by the alpha mask. Secondly, many fully transparent
939 // bmp images are intended to be opaque. Here, we make those corrections.
940 SkPMColor* dstPtr = (SkPMColor*) dst;
941 if (alphaMask != 0) {
942 for (uint32_t y = 0; y < height; y++) {
943 for (uint32_t x = 0; x < width; x++) {
944 if (transparent) {
945 dstPtr[y * dstRowBytes + x] |= 0xFF000000;
946 } else {
947 dstPtr[y * dstRowBytes + x] &= alphaMask;
948 }
949 }
950 }
951 }
952
953 // Finished decoding the entire image
954 return kSuccess;
955 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698