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

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

Powered by Google App Engine
This is Rietveld 408576698