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

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