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

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: Improved clarity of swizzler with regard to weird alpha 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 "SkColorTable.h"
11 #include "SkEndian.h"
12 #include "SkStream.h"
13
14 /*
15 *
16 * Get a byte from the buffer
17 *
18 */
19 uint8_t get_byte(uint8_t* buffer, uint32_t i) {
20 return buffer[i];
21 }
22
23 /*
24 *
25 * Get a short from the buffer
26 *
27 */
28 uint16_t get_short(uint8_t* buffer, uint32_t i) {
29 uint16_t result;
30 memcpy(&result, &(buffer[i]), 2);
31 #ifdef SK_CPU_BENDIAN
32 return SkEndianSwap16(result);
33 #else
34 return result;
35 #endif
36 }
37
38 /*
39 *
40 * Get an int from the buffer
41 *
42 */
43 uint32_t get_int(uint8_t* buffer, uint32_t i) {
44 uint32_t result;
45 memcpy(&result, &(buffer[i]), 4);
46 #ifdef SK_CPU_BENDIAN
47 return SkEndianSwap32(result);
48 #else
49 return result;
50 #endif
51 }
52
53 /*
54 *
55 * Defines the version and type of the second bitmap header
56 *
57 */
58 enum BitmapHeaderType {
59 kInfoV1_BitmapHeaderType,
60 kInfoV2_BitmapHeaderType,
61 kInfoV3_BitmapHeaderType,
62 kInfoV4_BitmapHeaderType,
63 kInfoV5_BitmapHeaderType,
64 kOS2V1_BitmapHeaderType,
65 kOS2VX_BitmapHeaderType,
66 kUnknown_BitmapHeaderType
67 };
68
69 /*
70 *
71 * Possible bitmap compression types
72 *
73 */
74 enum BitmapCompressionMethod {
75 kNone_BitmapCompressionMethod = 0,
76 k8BitRLE_BitmapCompressionMethod = 1,
77 k4BitRLE_BitmapCompressionMethod = 2,
78 kBitMasks_BitmapCompressionMethod = 3,
79 kJpeg_BitmapCompressionMethod = 4,
80 kPng_BitmapCompressionMethod = 5,
81 kAlphaBitMasks_BitmapCompressionMethod = 6,
82 kCMYK_BitmapCompressionMethod = 11,
83 kCMYK8BitRLE_BitmapCompressionMethod = 12,
84 kCMYK4BitRLE_BitmapCompressionMethod = 13
85 };
86
87 /*
88 *
89 * Checks the start of the stream to see if the image is a bitmap
90 *
91 */
92 bool SkBmpCodec::IsBmp(SkStream* stream) {
93 // TODO: Support "IC", "PT", "CI", "CP", "BA"
94 // TODO: ICO files may contain a BMP and need to use this decoder
95 const char bmpSig[] = { 'B', 'M' };
96 char buffer[sizeof(bmpSig)];
97 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) &&
98 !memcmp(buffer, bmpSig, sizeof(bmpSig));
99 }
100
101 /*
102 *
103 * Assumes IsBmp was called and returned true
104 * Creates a bitmap decoder
105 * Reads enough of the stream to determine the image format
106 *
107 */
108 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
109 // Header size constants
110 static const uint32_t kBmpHeaderBytes = 14;
111 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
112 static const uint32_t kBmpOS2V1Bytes = 12;
113 static const uint32_t kBmpOS2V2Bytes = 64;
114 static const uint32_t kBmpInfoBaseBytes = 16;
115 static const uint32_t kBmpInfoV1Bytes = 40;
116 static const uint32_t kBmpInfoV2Bytes = 52;
117 static const uint32_t kBmpInfoV3Bytes = 56;
118 static const uint32_t kBmpInfoV4Bytes = 108;
119 static const uint32_t kBmpInfoV5Bytes = 124;
120 static const uint32_t kBmpMaskBytes = 12;
121
122 // Read the first header and the size of the second header
123 SkAutoTDeleteArray<uint8_t> hBuffer(
124 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour));
125 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
126 kBmpHeaderBytesPlusFour) {
127 SkDebugf("Error: unable to read first bitmap header.\n");
128 return NULL;
129 }
130 //uint16_t signature = get_short(hBuffer, 0);
scroggo 2015/03/04 17:10:30 Can these be removed?
131
132 // The total bytes in the bmp file
133 // We only need to use this value for RLE decoding, so we will only check
134 // that it is valid in the RLE case.
135 const uint32_t totalBytes = get_int(hBuffer.get(), 2);
136
137 //uint32_t reserved = get_int(hBuffer, 6);
138
139 // The offset from the start of the file where the pixel data begins
140 const uint32_t offset = get_int(hBuffer.get(), 10);
141 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
142 SkDebugf("Error: invalid starting location for pixel data\n");
143 return NULL;
144 }
145
146 // The size of the second (info) header in bytes
147 // The size is the first field of the second header, so we have already
148 // read the first four infoBytes.
149 const uint32_t infoBytes = get_int(hBuffer.get(), 14);
150 if (infoBytes < kBmpOS2V1Bytes) {
151 SkDebugf("Error: invalid second header size.\n");
152 return NULL;
153 }
154 const uint32_t infoBytesRemaining = infoBytes - 4;
155 hBuffer.free();
156
157 // Read the second header
158 SkAutoTDeleteArray<uint8_t> iBuffer(
159 SkNEW_ARRAY(uint8_t, infoBytesRemaining));
160 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
161 SkDebugf("Error: unable to read second bitmap header.\n");
162 return NULL;
163 }
164
165 // The number of bits used per pixel in the pixel data
166 uint16_t bitsPerPixel;
167
168 // The compression method for the pixel data
169 uint32_t compression = kNone_BitmapCompressionMethod;
170
171 // Number of colors in the color table, defaults to 0 or max (see below)
172 uint32_t numColors = 0;
173
174 // Bytes per color in the color table, early versions use 3, most use 4
175 uint32_t bytesPerColor;
176
177 // The image width and height
178 int width, height;
179
180 // Determine image information depending on second header format
181 BitmapHeaderType headerType;
182 if (infoBytes >= kBmpInfoBaseBytes) {
183 // Check the version of the header
184 switch (infoBytes) {
185 case kBmpInfoV1Bytes:
186 headerType = kInfoV1_BitmapHeaderType;
187 break;
188 case kBmpInfoV2Bytes:
189 headerType = kInfoV2_BitmapHeaderType;
190 break;
191 case kBmpInfoV3Bytes:
192 headerType = kInfoV3_BitmapHeaderType;
193 break;
194 case kBmpInfoV4Bytes:
195 headerType = kInfoV4_BitmapHeaderType;
196 break;
197 case kBmpInfoV5Bytes:
198 headerType = kInfoV5_BitmapHeaderType;
199 break;
200 case 16:
201 case 20:
202 case 24:
203 case 28:
204 case 32:
205 case 36:
206 case 42:
207 case 46:
208 case 48:
209 case 60:
210 case kBmpOS2V2Bytes:
211 headerType = kOS2VX_BitmapHeaderType;
212 break;
213 default:
214 // We do not signal an error here because there is the
215 // possibility of new or undocumented bmp header types. Most
216 // of the newer versions of bmp headers are similar to and
217 // build off of the older versions, so we may still be able to
218 // decode the bmp.
219 SkDebugf("Warning: unknown bmp header format.\n");
220 headerType = kUnknown_BitmapHeaderType;
221 break;
222 }
223 // We check the size of the header before entering the if statement.
224 // We should not reach this point unless the size is large enough for
225 // these required fields.
226 SkASSERT(infoBytesRemaining >= 12);
227 width = get_int(iBuffer.get(), 0);
228 height = get_int(iBuffer.get(), 4);
229 //uint16_t planes = get_short(iBuffer, 8);
230 bitsPerPixel = get_short(iBuffer.get(), 10);
231
232 // Some versions do not have this field, so we check before
233 // overwriting the default value.
234 if (infoBytesRemaining >= 16) {
235 compression = get_int(iBuffer.get(), 12);
236 }
237 //uint32_t imageBytes = get_int(iBuffer, 16);
238 //uint32_t horizontalResolution = get_int(iBuffer, 20);
239 //uint32_t verticalResolution = get_int(iBuffer, 24);
240
241 // Some versions do not have this field, so we check before
242 // overwriting the default value.
243 if (infoBytesRemaining >= 32) {
244 numColors = get_int(iBuffer.get(), 28);
245 }
246 //uint32_t importantColors = get_int(iBuffer, infoBytes - 4, 32);
247 bytesPerColor = 4;
248 } else if (infoBytes >= kBmpOS2V1Bytes) {
249 // The OS2V1 is treated separately because it has a unique format
250 headerType = kOS2V1_BitmapHeaderType;
251 width = (int) get_short(iBuffer.get(), 0);
252 height = (int) get_short(iBuffer.get(), 2);
253 //uint16_t planes = get_short(iBuffer.get(), 4);
254 bitsPerPixel = get_short(iBuffer.get(), 6);
255 bytesPerColor = 3;
256 } else {
257 // There are no valid bmp headers
258 SkDebugf("Error: second bitmap header size is invalid.\n");
259 return NULL;
260 }
261
262 // Check for valid dimensions from header
263 static const uint32_t kBmpMaxDim = 1 << 16;
scroggo 2015/03/04 17:10:30 nit: This could be after the next if statement (it
264 SkSwizzler::RowOrder rowOrder = SkSwizzler::kBottomUp_RowOrder;
265 if (height < 0) {
266 height = -height;
267 rowOrder = SkSwizzler::kTopDown_RowOrder;
268 }
269 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) {
270 // TODO: Decide if we want to support really large bmps.
271 SkDebugf("Error: invalid bitmap dimensions.\n");
272 return NULL;
273 }
274
275 // Create mask struct
276 SkSwizzler::ColorMasks masks;
277 masks.redMask = 0;
scroggo 2015/03/04 17:10:30 Maybe ColorMasks should have a constructor? (Or we
278 masks.greenMask = 0;
279 masks.blueMask = 0;
280 masks.alphaMask = 0;
281
282 // Determine the input compression format and set bit masks if necessary
283 uint32_t maskBytes = 0;
284 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat;
285 switch (compression) {
286 case kNone_BitmapCompressionMethod:
287 inputFormat = kStandard_BitmapInputFormat;
288 // Always respect alpha mask in V4+
289 if (kInfoV4_BitmapHeaderType == headerType ||
290 kInfoV5_BitmapHeaderType == headerType) {
291 // Header types are matched based on size. If the header is
292 // V4+, we are guaranteed to be able at least this size.
293 SkASSERT(infoBytesRemaining > 52);
294 masks.alphaMask = get_int(iBuffer.get(), 48);
295 }
296 break;
297 case k8BitRLE_BitmapCompressionMethod:
298 if (bitsPerPixel != 8) {
299 SkDebugf("Warning: correcting invalid bitmap format.\n");
300 bitsPerPixel = 8;
301 }
302 inputFormat = kRLE_BitmapInputFormat;
303 break;
304 case k4BitRLE_BitmapCompressionMethod:
305 if (bitsPerPixel != 4) {
306 SkDebugf("Warning: correcting invalid bitmap format.\n");
307 bitsPerPixel = 4;
308 }
309 inputFormat = kRLE_BitmapInputFormat;
310 break;
311 case kAlphaBitMasks_BitmapCompressionMethod:
312 case kBitMasks_BitmapCompressionMethod:
313 // Load the masks
314 inputFormat = kBitMask_BitmapInputFormat;
315 switch (headerType) {
316 case kInfoV1_BitmapHeaderType: {
317 // The V1 header stores the bit masks after the header
318 SkAutoTDeleteArray<uint8_t> mBuffer(
319 SkNEW_ARRAY(uint8_t, kBmpMaskBytes));
320 if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
321 kBmpMaskBytes) {
322 SkDebugf("Error: unable to read bit masks.\n");
323 return NULL;
324 }
325 maskBytes = kBmpMaskBytes;
326 masks.redMask = get_int(mBuffer.get(), 0);
327 masks.greenMask = get_int(mBuffer.get(), 4);
328 masks.blueMask = get_int(mBuffer.get(), 8);
329 break;
330 }
331 case kInfoV4_BitmapHeaderType:
332 case kInfoV5_BitmapHeaderType:
333 // Header types are matched based on size. If the header
334 // is V4+, we are guaranteed to be able at least this size.
335 SkASSERT(infoBytesRemaining >= 52);
336 masks.alphaMask = get_int(iBuffer.get(), 48);
337 // Intentional fall through
338 case kInfoV2_BitmapHeaderType:
339 case kInfoV3_BitmapHeaderType:
340 // Header types are matched based on size. If the header
341 // is V2+, we are guaranteed to be able at least this size.
342 SkASSERT(infoBytesRemaining >= 48);
343 masks.redMask = get_int(iBuffer.get(), 36);
344 masks.greenMask = get_int(iBuffer.get(), 40);
345 masks.blueMask = get_int(iBuffer.get(), 44);
346 break;
347 case kOS2VX_BitmapHeaderType:
348 // TODO: Decide if we intend to support this.
349 // It is unsupported in the previous version and
350 // in chromium. I have not come across a test case
351 // that uses this format.
352 SkDebugf("Error: huffman format unsupported.\n");
353 return NULL;
354 default:
355 SkDebugf("Error: invalid bmp bit masks header.\n");
356 return NULL;
357 }
358 break;
359 case kJpeg_BitmapCompressionMethod:
360 if (24 == bitsPerPixel) {
361 inputFormat = kRLE_BitmapInputFormat;
362 break;
363 }
364 case kPng_BitmapCompressionMethod:
365 // TODO: Decide if we intend to support this.
366 // It is unsupported in the previous version and
367 // in chromium. I think it is used mostly for printers.
368 SkDebugf("Error: compression format not supported.\n");
369 return NULL;
370 case kCMYK_BitmapCompressionMethod:
371 case kCMYK8BitRLE_BitmapCompressionMethod:
372 case kCMYK4BitRLE_BitmapCompressionMethod:
373 // TODO: Same as above.
374 SkDebugf("Error: CMYK not supported for bitmap decoding.\n");
375 return NULL;
376 default:
377 SkDebugf("Error: invalid format for bitmap decoding.\n");
378 return NULL;
379 }
380 iBuffer.free();
381
382 // Check for valid bits per pixel input
383 switch (bitsPerPixel) {
384 // In addition to more standard pixel compression formats, bmp supports
385 // the use of bit masks to determine pixel components. The bmp standard
386 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
387 // which does not map well to any Skia color formats. For this reason,
388 // we will always enable mask mode with 16 bits per pixel.
389 case 16:
390 if (kBitMask_BitmapInputFormat != inputFormat) {
391 masks.redMask = 0x7C00;
392 masks.greenMask = 0x03E0;
393 masks.blueMask = 0x001F;
394 }
395 break;
396 case 1:
397 case 2:
398 case 4:
399 case 8:
400 case 24:
401 case 32:
402 break;
403 default:
404 SkDebugf("Error: invalid input value for bits per pixel.\n");
405 return NULL;
406 }
407
408 // Process the color table
409 uint32_t colorBytes = 0;
410 SkPMColor* colorTable = NULL;
411 if (bitsPerPixel < 16) {
412 // Verify the number of colors for the color table
413 const int maxColors = 1 << bitsPerPixel;
414 // Zero is a default for maxColors
415 // Also set numColors to maxColors when input is too large
416 if (numColors <= 0 || numColors > maxColors) {
417 numColors = maxColors;
418 }
419 colorTable = SkNEW_ARRAY(SkPMColor, maxColors);
420
421 // Construct the color table
422 colorBytes = numColors * bytesPerColor;
423 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
424 if (stream->read(cBuffer.get(), colorBytes) != colorBytes) {
425 SkDebugf("Error: unable to read color table.\n");
426 return NULL;
427 }
428 // We must respect the alpha channel for V4 and V5. However, if it is
429 // all zeros, we will display the image as opaque rather than
430 // transparent. This may require redoing some of the processing.
431 bool seenNonZeroAlpha = false;
432 uint32_t i = 0;
433 for (; i < numColors; i++) {
434 uint8_t blue = get_byte(cBuffer.get(), i*bytesPerColor);
435 uint8_t green = get_byte(cBuffer.get(), i*bytesPerColor + 1);
436 uint8_t red = get_byte(cBuffer.get(), i*bytesPerColor + 2);
437 uint8_t alpha = 0xFF;
438 if (kInfoV4_BitmapHeaderType == headerType ||
439 kInfoV5_BitmapHeaderType == headerType) {
440 alpha = (masks.alphaMask >> 24) &
441 get_byte(cBuffer.get(), i*bytesPerColor + 3);
442 if (!alpha && !seenNonZeroAlpha) {
443 alpha = 0xFF;
444 } else {
445 // If we see a non-zero alpha, we restart the loop
446 seenNonZeroAlpha = true;
447 i = -1;
scroggo 2015/03/04 17:10:30 don't you want a 'continue' here? Otherwise, won't
448 }
449 }
450 colorTable[i] = SkPreMultiplyColor(SkColorSetARGBInline(alpha,
scroggo 2015/03/04 17:10:30 As stated in an earlier patch set, you don't need
msarett 2015/03/05 23:13:17 Sorry I missed this. Had the wrong code in so man
451 red, green, blue));
452 }
453 // To avoid segmentation faults on bad pixel data, fill the end of the
454 // color table with black. This is the same the behavior as the
455 // chromium decoder.
456 for (; i < maxColors; i++) {
457 colorTable[i] = SkPackARGB32(0xFF, 0, 0, 0);
458 }
459 } else {
460 // We will not use the color table if bitsPerPixel >= 16, but if there
461 // is a color table, we may need to skip the color table bytes.
462 // We will assume that the maximum color table size is the same as when
463 // there are 8 bits per pixel (the largest color table actually used).
464 // Color tables for greater than 8 bits per pixel are somewhat
465 // undocumented. It is indicated that they may exist to store a list
466 // of colors for optimization on devices with limited color display
467 // capacity. While we do not know for sure, we will guess that any
468 // value of numColors greater than this maximum is invalid.
469 if (numColors <= (1 << 8)) {
470 colorBytes = numColors * bytesPerColor;
471 if (stream->skip(colorBytes) != colorBytes) {
472 SkDebugf("Error: Could not skip color table bytes.\n");
473 return NULL;
474 }
475 }
476 }
477
478 // Ensure that the stream now points to the start of the pixel array
479 uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes + colorBytes;
480
481 // Check that we have not read past the pixel array offset
482 if(bytesRead > offset) {
483 // This may occur on OS 2.1 and other old versions where the color
484 // table defaults to max size, and the bmp tries to use a smaller color
485 // table. This is invalid, and our decision is to indicate an error,
486 // rather than try to guess the intended size of the color table and
487 // rewind the stream to display the image.
488 SkDebugf("Error: pixel data offset less than header size.\n");
489 return NULL;
490 }
491
492 // Skip to the start of the pixel array
493 if (stream->skip(offset - bytesRead) != offset - bytesRead) {
494 SkDebugf("Error: unable to skip to image data.\n");
495 return NULL;
496 }
497
498 // Remaining bytes is only used for RLE
499 const int remainingBytes = totalBytes - offset;
500 if (remainingBytes <= 0 && kRLE_BitmapInputFormat == inputFormat) {
501 SkDebugf("Error: RLE requires valid input size.\n");
502 return NULL;
503 }
504
505 // Return the codec
506 // Use of image info for input format does not make sense given
507 // that the possible bitmap input formats do not match up with
508 // Skia color types. Instead we use ImageInfo for width and height,
509 // and other fields for input format information.
510 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
511 kN32_SkColorType, kPremul_SkAlphaType);
scroggo 2015/03/04 17:10:30 At this point, isn't it possible to know (at least
512 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
513 inputFormat, masks, colorTable, rowOrder,
514 remainingBytes));
515 }
516
517 /*
518 *
519 * Creates an instance of the decoder
520 * Called only by NewFromStream
521 *
522 */
523 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
524 uint16_t bitsPerPixel, BitmapInputFormat inputFormat,
525 SkSwizzler::ColorMasks masks, SkPMColor* colorTable,
526 SkSwizzler::RowOrder rowOrder,
527 const uint32_t remainingBytes)
528 : INHERITED(info, stream)
529 , fBitsPerPixel(bitsPerPixel)
530 , fInputFormat(inputFormat)
531 , fBitMasks(masks)
532 , fColorTable(colorTable)
533 , fRowOrder(rowOrder)
534 , fRemainingBytes(remainingBytes)
535 {}
536
537 /*
538 *
539 * Initiates the bitmap decode
540 *
541 */
542 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
543 void* dst, size_t dstRowBytes,
544 SkPMColor*, int*) {
545 // This version of the decoder does not support scaling
546 if (dstInfo.dimensions() != getOriginalInfo().dimensions()) {
scroggo 2015/03/04 17:10:30 You'll need to do other checks, for example whethe
547 SkDebugf("Error: scaling not supported.\n");
548 return kInvalidScale;
549 }
550
551 switch (fInputFormat) {
552 case kRLE_BitmapInputFormat:
553 return decodeRLE(dstInfo, dst, dstRowBytes);
554 case kBitMask_BitmapInputFormat:
555 case kStandard_BitmapInputFormat:
556 return decode(dstInfo, dst, dstRowBytes);
557 default:
558 SkDebugf("Error: unknown bitmap input format.\n");
scroggo 2015/03/04 17:10:30 When does this happen? Can we skip creating an SkB
559 return kInvalidInput;
560 }
561 }
562
563 /*
564 *
565 * Performs the bitmap decoding for standard and bit masks input format
566 *
567 */
568 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
569 void* dst, uint32_t dstRowBytes) {
570 // Set constant values
571 const int width = dstInfo.width();
572 const int height = dstInfo.height();
573 const uint32_t pixelsPerByte = 8 / fBitsPerPixel;
574 const uint32_t bytesPerPixel = fBitsPerPixel / 8;
575 const uint32_t unpaddedRowBytes = fBitsPerPixel < 16 ?
576 (width + pixelsPerByte - 1) / pixelsPerByte : width * bytesPerPixel;
577 const uint32_t paddedRowBytes = (unpaddedRowBytes + 3) & (~3);
scroggo 2015/03/04 17:10:30 You're probably not familiar with it, but I believ
578 const uint32_t alphaMask = fBitMasks.alphaMask;
579
580 // Get swizzler configuration
581 SkSwizzler::SrcConfig config;
582 switch (fBitsPerPixel) {
583 case 1:
584 config = SkSwizzler::kIndex1;
585 break;
586 case 2:
587 config = SkSwizzler::kIndex2;
588 break;
589 case 4:
590 config = SkSwizzler::kIndex4;
591 break;
592 case 8:
593 config = SkSwizzler::kIndex;
594 break;
595 case 16:
596 config = SkSwizzler::kMask16;
597 break;
598 case 24:
599 if (kBitMask_BitmapInputFormat == fInputFormat) {
600 config = SkSwizzler::kMask24;
601 } else {
602 config = SkSwizzler::kBGR;
603 }
604 break;
605 case 32:
606 if (kBitMask_BitmapInputFormat == fInputFormat) {
607 config = SkSwizzler::kMask32;
608 } else if (!alphaMask) {
609 config = SkSwizzler::kBGRX;
610 } else {
611 config = SkSwizzler::kBGRA;
612 }
613 break;
614 default:
615 SkASSERT(false);
616 return kInvalidInput;
617 }
618
619 // If alphaOption is kNormal, it indicates that the image will be
620 // considered as encoded. If kTransparentAsOpaque, we will respect the
621 // value of the alpha channel if it is nonzero for any of the pixels.
622 // However, if it is always zero, we will consider the image opaque instead
623 // of transparent. This may require redoing some of the decoding.
624 SkSwizzler::AlphaOption alphaOption;
625 if (fBitsPerPixel < 16) {
626 alphaOption = SkSwizzler::kNormal_AlphaOption;
627 } else if (alphaMask) {
628 alphaOption = SkSwizzler::kTransparentAsOpaque_AlphaOption;
629 } else {
630 alphaOption = SkSwizzler::kOpaque_AlphaOption;
631 }
632
633 // Create swizzler
634 SkSwizzler* swizzler = SkSwizzler::CreateSwizzler(config, fColorTable.get(),
635 dstInfo, dst, dstRowBytes, false, fBitMasks, alphaOption,
636 fRowOrder);
637
638 // Allocate space for a row buffer and a source for the swizzler
639 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, paddedRowBytes));
640
641 // Iterate over rows of the image
642 for (uint32_t y = 0; y < height; y++) {
643 // Read a row of the input
644 if (stream()->read(srcBuffer.get(), paddedRowBytes) != paddedRowBytes) {
645 return kIncompleteInput;
646 }
647
648 // Decode the row in destination format
649 swizzler->next(srcBuffer.get());
650 }
651
652 // Finished decoding the entire image
653 return kSuccess;
654 }
655
656 /*
657 *
658 * Set an RLE pixel using the color table
659 *
660 */
661 void SkBmpCodec::setRLEPixel(SkPMColor* dst, uint32_t dstRowBytes, int height,
662 uint32_t x, uint32_t y, uint8_t index) {
663 if (SkSwizzler::kBottomUp_RowOrder == fRowOrder) {
664 y = height - y - 1;
665 }
666 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, y * dstRowBytes);
667 dstRow[x] = fColorTable.get()[index];
668 }
669
670 /*
671 *
672 * Performs the bitmap decoding for RLE input format
673 * RLE decoding is performed all at once, rather than a one row at a time
674 *
675 */
676 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
677 void* dst, uint32_t dstRowBytes) {
678 // Set RLE flags
679 static const uint8_t RLE_ESCAPE = 0;
680 static const uint8_t RLE_EOL = 0;
681 static const uint8_t RLE_EOF = 1;
682 static const uint8_t RLE_DELTA = 2;
683
684 // Set constant values
685 const int width = dstInfo.width();
686 const int height = dstInfo.height();
687 const uint32_t pixelsPerByte = 8 / fBitsPerPixel;
688 const uint32_t bytesPerPixel = fBitsPerPixel / 8;
689
690 // Input buffer parameters
691 uint32_t i = 0;
scroggo 2015/03/04 17:10:30 It looks like in this case, "i" means "bytesRead"?
692 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRemainingBytes));
693 uint32_t totalBytes = stream()->read(buffer.get(), fRemainingBytes);
694 if (totalBytes < fRemainingBytes) {
695 SkDebugf("Warning: incomplete RLE file.\n");
696 } else if (totalBytes <= 0) {
697 SkDebugf("Error: could not read RLE image data.\n");
698 return kInvalidInput;
699 }
700
701 // Destination parameters
702 uint32_t x = 0;
703 uint32_t y = 0;
704 // If the code skips pixels, remaining pixels are transparent or black
705 // TODO: Skip this is memory was already zeroed.
scroggo 2015/03/04 17:10:30 if*
706 memset(dst, 0, dstRowBytes * height);
707 SkPMColor* dstPtr = (SkPMColor*) dst;
708
709 while (true) {
710 // Every entry takes at least two bytes
711 if (totalBytes - i < 2) {
712 SkDebugf("Warning: incomplete RLE input.\n");
713 return kIncompleteInput;
714 }
715
716 // Read the two bytes and verify we have not reached end of image
717 const uint8_t count = buffer.get()[i++];
scroggo 2015/03/04 17:10:30 Can you elaborate what these variables mean? IIUC,
718 const uint8_t code = buffer.get()[i++];
719 if ((count || (code != RLE_EOF)) && y >= height) {
scroggo 2015/03/04 17:10:30 I'm having trouble following this line. Is it bas
720 SkDebugf("Warning: invalid RLE input.\n");
721 return kIncompleteInput;
722 }
723
724 // Perform decoding
725 if (RLE_ESCAPE == count) {
726 switch (code) {
727 case RLE_EOL:
728 x = 0;
729 y++;
730 break;
731 case RLE_EOF:
732 return kSuccess;
733 case RLE_DELTA: {
734 // Two bytes are needed to specify delta
735 if (totalBytes - i < 2) {
736 SkDebugf("Warning: incomplete RLE input\n");
737 return kIncompleteInput;
738 }
739 // Modify x and y
740 const uint8_t dx = buffer.get()[i++];
741 const uint8_t dy = buffer.get()[i++];
742 x += dx;
743 y += dy;
744 if (x > width || y > height) {
745 SkDebugf("Warning: invalid RLE input.\n");
746 return kIncompleteInput;
747 }
748 break;
749 }
750 default: { // Absolute mode
751 // Check that we have enough bytes and that there are
752 // enough pixels remaining in the row
753 const uint32_t unpaddedBytes = fBitsPerPixel < 16 ?
754 (code + pixelsPerByte - 1) / pixelsPerByte :
755 code * bytesPerPixel;
756 const uint32_t paddedBytes =
757 (unpaddedBytes + 1) & (~1);
scroggo 2015/03/04 17:10:30 I think you can use SkAlign2 here.
758 if (x + code > width || totalBytes - i < paddedBytes) {
scroggo 2015/03/04 17:10:30 So in this case, does code mean a number of pixels
759 SkDebugf("Warning: invalid RLE input.\n");
760 return kIncompleteInput;
761 }
762 // Use the color table to set the coded number of pixels
763 uint8_t num = code;
764 while (num > 0) {
765 switch(fBitsPerPixel) {
766 case 4: {
767 uint8_t val = buffer.get()[i++];
768 setRLEPixel(dstPtr, dstRowBytes, height, x++, y,
769 val >> 4);
770 num--;
771 if (num) {
772 setRLEPixel(dstPtr, dstRowBytes, height,
773 x++, y, val & 0xF);
774 num--;
775 }
776 break;
777 }
778 case 8:
779 setRLEPixel(dstPtr, dstRowBytes, height, x++, y,
780 buffer.get()[i++]);
781 num--;
782 break;
783 case 24: {
784 uint8_t blue = buffer.get()[i++];
785 uint8_t green = buffer.get()[i++];
786 uint8_t red = buffer.get()[i++];
787 SkPMColor color = SkPreMultiplyARGB(
788 0xFF, red, green, blue);
789 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(
790 dstPtr, y * dstRowBytes);
791 dstRow[x++] = color;
792 num--;
793 }
794 default:
795 SkASSERT(false);
796 return kInvalidInput;
797 }
798 }
799 // Skip a byte if necessary to maintain alignment
800 if (unpaddedBytes & 1) {
801 i++;
802 }
803 break;
804 }
805 }
806 } else { // Encoded mode
807 // Ensure we do not move past the end of the row
808 const uint32_t endX = SkTMin<uint32_t>(x + count, (uint32_t) width);
809
810 if (24 == fBitsPerPixel) {
811 // Check that there is enough data
812 if (totalBytes - i < 2) {
813 SkDebugf("Warning: incomplete RLE input\n");
814 return kIncompleteInput;
815 }
816
817 // Fill the pixels up to endX with the specified color
818 uint8_t blue = code;
819 uint8_t green = buffer.get()[i++];
820 uint8_t red = buffer.get()[i++];
821 SkPMColor color = SkPackARGB32(0xFF, red, green, blue);
822 SkPMColor* dstRow =
823 SkTAddOffset<SkPMColor>(dstPtr, y * dstRowBytes);
824 while (x < endX) {
825 dstRow[x++] = color;
826 }
827 } else {
828 // RLE8 has one color index that gets repeated
829 // RLE4 has two color indexes in the upper and lower 4 bits of
830 // the bytes, which are alternated
831 uint8_t indices[2] = { code, code };
832 if (4 == fBitsPerPixel) {
833 indices[0] >>= 4;
834 indices[1] &= 0xf;
835 }
836
837 // Set the indicated number of pixels
838 for (int which = 0; x < endX; x++) {
839 setRLEPixel(dstPtr, dstRowBytes, height, x, y,
840 indices[which]);
841 which = !which;
842 }
843 }
844 }
845 }
846 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698