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

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: clarified ownership of SkMasks* 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
scroggo 2015/03/11 21:14:26 Maybe add a comment that these are unsafe, and ass
msarett 2015/03/12 14:06:46 Yes I agree, I made this more clear.
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) {
scroggo 2015/03/11 21:14:25 // TODO: Share with other codecs (unless this is
msarett 2015/03/12 14:06:46 I have added this method to SkCodec.h (unfortunate
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);
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);
scroggo 2015/03/11 21:14:26 Any reason to leave this here?
msarett 2015/03/12 14:06:47 Sorry I must have forgotten to delete this.
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) {
scroggo 2015/03/11 21:14:25 Maybe this should go inside the previous if statem
msarett 2015/03/12 14:06:47 Yes that makes sense.
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 int 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 SkMasks::InputMasks inputMasks;
309 memset(&inputMasks, 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 inputMasks.\n");
344 return NULL;
345 }
346 maskBytes = kBmpMaskBytes;
347 inputMasks.red = get_int(mBuffer.get(), 0);
348 inputMasks.green = get_int(mBuffer.get(), 4);
349 inputMasks.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.
scroggo 2015/03/11 21:14:26 able to read*
msarett 2015/03/12 14:06:46 Nice catch. How does this error keep coming back?
scroggo 2015/03/12 15:19:57 Haha, I don't know, but I know when I rebase I som
358 SkASSERT(infoBytesRemaining >= 48);
359 inputMasks.red = get_int(iBuffer.get(), 36);
360 inputMasks.green = get_int(iBuffer.get(), 40);
361 inputMasks.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 to read at least this size.
410 SkASSERT(infoBytesRemaining > 52);
411 inputMasks.alpha = get_int(iBuffer.get(), 48);
412 if (inputMasks.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 inputMasks.red = 0x7C00;
428 inputMasks.green = 0x03E0;
429 inputMasks.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 // Check that input bit masks are valid and create the masks object
446 SkAutoTDelete<SkMasks>
447 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
448 if (NULL == masks) {
449 SkDebugf("Error: invalid input masks.\n");
450 return NULL;
451 }
452
453 // Process the color table
454 uint32_t colorBytes = 0;
455 SkPMColor* colorTable = NULL;
456 if (bitsPerPixel < 16) {
457 // Verify the number of colors for the color table
458 const uint32_t maxColors = 1 << bitsPerPixel;
459 // Zero is a default for maxColors
460 // Also set numColors to maxColors when input is too large
461 if (numColors <= 0 || numColors > maxColors) {
462 numColors = maxColors;
463 }
464 colorTable = SkNEW_ARRAY(SkPMColor, maxColors);
465
466 // Construct the color table
467 colorBytes = numColors * bytesPerColor;
468 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
469 if (stream->read(cBuffer.get(), colorBytes) != colorBytes) {
470 SkDebugf("Error: unable to read color table.\n");
471 return NULL;
472 }
473
474 // Fill in the color table
475 uint32_t i = 0;
476 for (; i < numColors; i++) {
477 uint8_t blue = get_byte(cBuffer.get(), i*bytesPerColor);
478 uint8_t green = get_byte(cBuffer.get(), i*bytesPerColor + 1);
479 uint8_t red = get_byte(cBuffer.get(), i*bytesPerColor + 2);
480 uint8_t alpha = 0xFF;
481 if (kOpaque_SkAlphaType != alphaType) {
482 alpha = (inputMasks.alpha >> 24) &
483 get_byte(cBuffer.get(), i*bytesPerColor + 3);
484 }
485 colorTable[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
scroggo 2015/03/11 21:14:25 So these colors are unpremultiplied? Can you add a
msarett 2015/03/12 14:06:47 Yes. I hope that I am following your convention b
scroggo 2015/03/12 15:19:57 But it appears there is no way to get premul. Does
486 }
487
488 // To avoid segmentation faults on bad pixel data, fill the end of the
489 // color table with black. This is the same the behavior as the
490 // chromium decoder.
491 for (; i < maxColors; i++) {
492 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
493 }
494 } else {
495 // We will not use the color table if bitsPerPixel >= 16, but if there
496 // is a color table, we may need to skip the color table bytes.
497 // We will assume that the maximum color table size is the same as when
498 // there are 8 bits per pixel (the largest color table actually used).
499 // Color tables for greater than 8 bits per pixel are somewhat
500 // undocumented. It is indicated that they may exist to store a list
501 // of colors for optimization on devices with limited color display
502 // capacity. While we do not know for sure, we will guess that any
503 // value of numColors greater than this maximum is invalid.
scroggo 2015/03/11 21:14:25 If numColors is greater than the maximum, is the r
msarett 2015/03/12 14:06:46 No idea. Your guess is as good as mine. I think
scroggo 2015/03/12 15:19:57 Come to think of it, what do we accomplish with th
504 if (numColors <= (1 << 8)) {
505 colorBytes = numColors * bytesPerColor;
506 if (stream->skip(colorBytes) != colorBytes) {
507 SkDebugf("Error: Could not skip color table bytes.\n");
508 return NULL;
509 }
510 }
511 }
512
513 // Ensure that the stream now points to the start of the pixel array
514 uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes + colorBytes;
515
516 // Check that we have not read past the pixel array offset
517 if(bytesRead > offset) {
518 // This may occur on OS 2.1 and other old versions where the color
519 // table defaults to max size, and the bmp tries to use a smaller color
520 // table. This is invalid, and our decision is to indicate an error,
521 // rather than try to guess the intended size of the color table and
522 // rewind the stream to display the image.
523 SkDebugf("Error: pixel data offset less than header size.\n");
524 return NULL;
525 }
526
527 // Skip to the start of the pixel array
528 if (stream->skip(offset - bytesRead) != offset - bytesRead) {
529 SkDebugf("Error: unable to skip to image data.\n");
530 return NULL;
531 }
532
533 // Remaining bytes is only used for RLE
534 const int remainingBytes = totalBytes - offset;
535 if (remainingBytes <= 0 && kRLE_BitmapInputFormat == inputFormat) {
536 SkDebugf("Error: RLE requires valid input size.\n");
537 return NULL;
538 }
539
540 // Return the codec
541 // We will use ImageInfo to store width, height, and alpha type. The Skia
542 // color types do not match with the many possible bmp input color types,
543 // so we will ignore this field and depend on other parameters for input
544 // information.
545 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
546 kUnknown_SkColorType, alphaType);
547 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
548 inputFormat, masks.detach(), colorTable,
549 rowOrder, remainingBytes));
550 }
551
552 /*
553 *
554 * Creates an instance of the decoder
555 * Called only by NewFromStream
556 *
557 */
558 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
559 uint16_t bitsPerPixel, BitmapInputFormat inputFormat,
560 SkMasks* masks, SkPMColor* colorTable,
561 RowOrder rowOrder,
562 const uint32_t remainingBytes)
563 : INHERITED(info, stream)
564 , fBitsPerPixel(bitsPerPixel)
565 , fInputFormat(inputFormat)
566 , fMasks(masks)
567 , fColorTable(colorTable)
568 , fRowOrder(rowOrder)
569 , fRemainingBytes(remainingBytes)
570 {}
571
572 /*
573 *
574 * Initiates the bitmap decode
575 *
576 */
577 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
578 void* dst, size_t dstRowBytes,
579 SkPMColor*, int*) {
580 if (!this->rewindIfNeeded()) {
581 return kCouldNotRewind;
582 }
583 if (dstInfo.dimensions() != this->getOriginalInfo().dimensions()) {
584 SkDebugf("Error: scaling not supported.\n");
585 return kInvalidScale;
586 }
587 if (!conversion_possible(dstInfo, this->getOriginalInfo())) {
588 SkDebugf("Error: cannot convert input type to output type.\n");
589 return kInvalidConversion;
590 }
591
592 switch (fInputFormat) {
593 case kBitMask_BitmapInputFormat:
594 return decodeMask(dstInfo, dst, dstRowBytes);
595 case kRLE_BitmapInputFormat:
596 return decodeRLE(dstInfo, dst, dstRowBytes);
597 case kStandard_BitmapInputFormat:
598 return decode(dstInfo, dst, dstRowBytes);
599 default:
600 SkASSERT(false);
601 return kInvalidInput;
602 }
603 }
604
605 /*
606 *
607 * Performs the bitmap decoding for bit masks input format
608 *
609 */
610 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
611 void* dst, uint32_t dstRowBytes) {
612 // Set constant values
613 const int width = dstInfo.width();
614 const int height = dstInfo.height();
615 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
616
617 // Allocate space for a row buffer and a source for the swizzler
618 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
619
620 // Get the destination start row and delta
621 SkPMColor* dstRow;
622 int32_t delta;
623 if (kTopDown_RowOrder == fRowOrder) {
624 dstRow = (SkPMColor*) dst;
625 delta = dstRowBytes;
626 } else {
627 dstRow = (SkPMColor*) SkTAddOffset<void>(dst, (height-1) * dstRowBytes);
628 delta = -dstRowBytes;
629 }
630
631 // Create the swizzler
632 SkMaskSwizzler* swizzler = SkMaskSwizzler::CreateMaskSwizzler(
633 dstInfo, fMasks, fBitsPerPixel);
634
635 // Iterate over rows of the image
636 bool transparent = true;
637 for (int y = 0; y < height; y++) {
638 // Read a row of the input
639 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
640 SkDebugf("Warning: incomplete input stream.\n");
641 return kIncompleteInput;
642 }
643
644 // Decode the row in destination format
645 SkSwizzler::ResultAlpha r = swizzler->next(dstRow, srcBuffer.get());
646 transparent &= (SkSwizzler::kTransparent_ResultAlpha == r);
647
648 // Move to the next row
649 dstRow = SkTAddOffset<SkPMColor>(dstRow, delta);
650 }
651
652 // Many fully transparent bmp images are intended to be opaque. Here, we
653 // correct for this possibility.
654 dstRow = (SkPMColor*) dst;
655 if (transparent) {
656 for (int y = 0; y < height; y++) {
657 for (int x = 0; x < width; x++) {
658 dstRow[x] |= 0xFF000000;
659 }
660 dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes);
661 }
662 }
663
664 // Finished decoding the entire image
665 return kSuccess;
666 }
667
668 /*
669 *
670 * Set an RLE pixel using the color table
671 *
672 */
673 void SkBmpCodec::setRLEPixel(SkPMColor* dst, uint32_t dstRowBytes, int height,
674 uint32_t x, uint32_t y, uint8_t index) {
675 if (kBottomUp_RowOrder == fRowOrder) {
676 y = height - y - 1;
677 }
678 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, y * dstRowBytes);
679 dstRow[x] = fColorTable.get()[index];
680 }
681
682 /*
683 *
684 * Performs the bitmap decoding for RLE input format
685 * RLE decoding is performed all at once, rather than a one row at a time
686 *
687 */
688 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
689 void* dst, uint32_t dstRowBytes) {
690 // Set RLE flags
691 static const uint8_t RLE_ESCAPE = 0;
692 static const uint8_t RLE_EOL = 0;
693 static const uint8_t RLE_EOF = 1;
694 static const uint8_t RLE_DELTA = 2;
695
696 // Set constant values
697 const int width = dstInfo.width();
698 const int height = dstInfo.height();
699
700 // Input buffer parameters
701 uint32_t currByte = 0;
702 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRemainingBytes));
703 uint32_t totalBytes = stream()->read(buffer.get(), fRemainingBytes);
704 if (totalBytes < fRemainingBytes) {
705 SkDebugf("Warning: incomplete RLE file.\n");
706 } else if (totalBytes <= 0) {
707 SkDebugf("Error: could not read RLE image data.\n");
708 return kInvalidInput;
709 }
710
711 // Destination parameters
712 int x = 0;
713 int y = 0;
714 // If the code skips pixels, remaining pixels are transparent or black
715 // TODO: Skip this if memory was already zeroed.
716 memset(dst, 0, dstRowBytes * height);
717 SkPMColor* dstPtr = (SkPMColor*) dst;
718
719 while (true) {
720 // Every entry takes at least two bytes
721 if (totalBytes - currByte < 2) {
722 SkDebugf("Warning: incomplete RLE input.\n");
723 return kIncompleteInput;
724 }
725
726 // Read the next two bytes. These bytes have different meanings
727 // depending on their values. In the first interpretation, the first
728 // byte is an escape flag and the second byte indicates what special
729 // task to perform.
730 const uint8_t flag = buffer.get()[currByte++];
731 const uint8_t task = buffer.get()[currByte++];
732
733 // If we have reached a row that is beyond the image size, and the RLE
734 // code does not indicate end of file, abort and signal a warning.
735 if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) {
736 SkDebugf("Warning: invalid RLE input.\n");
737 return kIncompleteInput;
738 }
739
740 // Perform decoding
741 if (RLE_ESCAPE == flag) {
742 switch (task) {
743 case RLE_EOL:
744 x = 0;
745 y++;
746 break;
747 case RLE_EOF:
748 return kSuccess;
749 case RLE_DELTA: {
750 // Two bytes are needed to specify delta
751 if (totalBytes - currByte < 2) {
752 SkDebugf("Warning: incomplete RLE input\n");
753 return kIncompleteInput;
754 }
755 // Modify x and y
756 const uint8_t dx = buffer.get()[currByte++];
757 const uint8_t dy = buffer.get()[currByte++];
758 x += dx;
759 y += dy;
760 if (x > width || y > height) {
761 SkDebugf("Warning: invalid RLE input.\n");
762 return kIncompleteInput;
763 }
764 break;
765 }
766 default: {
767 // If task does not match any of the above signals, it
768 // indicates that we have a sequence of non-RLE pixels.
769 // Furthermore, the value of task is equal to the number
770 // of pixels to interpret.
771 uint8_t numPixels = task;
772 const size_t rowBytes = compute_row_bytes(numPixels,
773 fBitsPerPixel);
774 // Abort if setting numPixels moves us off the edge of the
775 // image. Also abort if there are not enough bytes
776 // remaining in the stream to set numPixels.
777 if (x + numPixels > width ||
778 totalBytes - currByte < SkAlign2(rowBytes)) {
779 SkDebugf("Warning: invalid RLE input.\n");
780 return kIncompleteInput;
781 }
782 // Set count number of pixels
783 while (numPixels > 0) {
784 switch(fBitsPerPixel) {
785 case 4: {
786 uint8_t val = buffer.get()[currByte++];
scroggo 2015/03/11 21:14:25 Do we need to do a check to make sure currByte is
msarett 2015/03/12 14:06:47 I agree that this is confusing. Hopefully adding
787 setRLEPixel(dstPtr, dstRowBytes, height, x++, y,
788 val >> 4);
789 numPixels--;
790 if (numPixels != 0) {
791 setRLEPixel(dstPtr, dstRowBytes, height,
792 x++, y, val & 0xF);
793 numPixels--;
794 }
795 break;
796 }
797 case 8:
798 setRLEPixel(dstPtr, dstRowBytes, height, x++, y,
799 buffer.get()[currByte++]);
800 numPixels--;
801 break;
802 case 24: {
803 uint8_t blue = buffer.get()[currByte++];
804 uint8_t green = buffer.get()[currByte++];
805 uint8_t red = buffer.get()[currByte++];
806 SkPMColor color = SkPackARGB32NoCheck(
807 0xFF, red, green, blue);
808 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(
809 dstPtr, y * dstRowBytes);
scroggo 2015/03/11 21:14:26 y is unchanged in the loop, correct? Can we do thi
msarett 2015/03/12 14:06:46 Yes you are correct!
810 dstRow[x++] = color;
811 numPixels--;
812 }
813 default:
814 SkASSERT(false);
815 return kInvalidInput;
816 }
817 }
818 // Skip a byte if necessary to maintain alignment
819 if (!SkIsAlign2(rowBytes)) {
820 currByte++;
821 }
822 break;
823 }
824 }
825 } else {
826 // If the first byte read is not a flag, it indicates the number of
827 // pixels to set in RLE mode.
828 const uint8_t numPixels = flag;
829 const int endX = SkTMin<int>(x + numPixels, width);
830
831 if (24 == fBitsPerPixel) {
832 // In RLE24, the second byte read is part of the pixel color.
833 // There are two more required bytes to finish encoding the
834 // color.
835 if (totalBytes - currByte < 2) {
836 SkDebugf("Warning: incomplete RLE input\n");
837 return kIncompleteInput;
838 }
839
840 // Fill the pixels up to endX with the specified color
841 uint8_t blue = task;
842 uint8_t green = buffer.get()[currByte++];
843 uint8_t red = buffer.get()[currByte++];
844 SkPMColor color = SkPackARGB32NoCheck(0xFF, red, green, blue);
845 SkPMColor* dstRow =
846 SkTAddOffset<SkPMColor>(dstPtr, y * dstRowBytes);
847 while (x < endX) {
848 dstRow[x++] = color;
849 }
850 } else {
851 // In RLE8 or RLE4, the second byte read gives the index in the
852 // color table to look up the pixel color.
853 // RLE8 has one color index that gets repeated
854 // RLE4 has two color indexes in the upper and lower 4 bits of
855 // the bytes, which are alternated
856 uint8_t indices[2] = { task, task };
857 if (4 == fBitsPerPixel) {
858 indices[0] >>= 4;
859 indices[1] &= 0xf;
860 }
861
862 // Set the indicated number of pixels
863 for (int which = 0; x < endX; x++) {
864 setRLEPixel(dstPtr, dstRowBytes, height, x, y,
865 indices[which]);
866 which = !which;
867 }
868 }
869 }
870 }
871 }
872
873 /*
874 *
875 * Performs the bitmap decoding for standard input format
876 *
877 */
878 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
879 void* dst, uint32_t dstRowBytes) {
880 // Set constant values
881 const int width = dstInfo.width();
882 const int height = dstInfo.height();
883 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
884 const uint32_t alphaMask = fMasks->getAlphaMask();
885
886 // Get swizzler configuration
887 SkSwizzler::SrcConfig config;
888 switch (fBitsPerPixel) {
scroggo 2015/03/11 21:14:25 It's ironic that here we use fBitsPerPixel to dete
msarett 2015/03/12 14:06:46 Yeah I completely agree with you, it doesn't make
scroggo 2015/03/12 15:19:57 I'd lean towards going all one direction or the ot
889 case 1:
890 config = SkSwizzler::kIndex1;
891 break;
892 case 2:
893 config = SkSwizzler::kIndex2;
894 break;
895 case 4:
896 config = SkSwizzler::kIndex4;
897 break;
898 case 8:
899 config = SkSwizzler::kIndex;
900 break;
901 case 24:
902 config = SkSwizzler::kBGR;
903 break;
904 case 32:
905 if (alphaMask == 0) {
906 config = SkSwizzler::kBGRX;
907 } else {
908 config = SkSwizzler::kBGRA;
909 }
910 break;
911 default:
912 SkASSERT(false);
913 return kInvalidInput;
914 }
915
916 // Create swizzler
917 SkSwizzler* swizzler = SkSwizzler::CreateSwizzler(config, fColorTable.get(),
918 dstInfo, dst, dstRowBytes, false);
919
920 // Allocate space for a row buffer and a source for the swizzler
921 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
922
923 // Iterate over rows of the image
924 bool transparent = true;
925 for (int y = 0; y < height; y++) {
926 // Read a row of the input
927 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
928 SkDebugf("Warning: incomplete input stream.\n");
929 return kIncompleteInput;
930 }
931
932 // Decode the row in destination format
933 uint32_t row;
934 if (kTopDown_RowOrder == fRowOrder) {
935 row = y;
936 } else {
937 row = height - 1 - y;
938 }
939 SkSwizzler::ResultAlpha r = swizzler->next(srcBuffer.get(), row);
940 transparent &= (SkSwizzler::kTransparent_ResultAlpha == r);
scroggo 2015/03/11 21:14:25 Maybe the parenthetical bit should be a helper fun
msarett 2015/03/12 14:06:47 Agreed, I will add a helper function to the Swizzl
941 }
942
943 // Now we adjust the output image with some additional behavior that
944 // SkSwizzler does not support. Firstly, all bmp images that contain
945 // alpha are masked by the alpha mask. Secondly, many fully transparent
946 // bmp images are intended to be opaque. Here, we make those corrections.
947 SkPMColor* dstRow = (SkPMColor*) dst;
948 if (alphaMask != 0) {
949 for (int y = 0; y < height; y++) {
950 for (int x = 0; x < width; x++) {
951 if (transparent) {
952 dstRow[x] |= 0xFF000000;
953 } else {
954 dstRow[x] &= alphaMask;
955 }
956 dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes);
957 }
958 }
959 }
960
961 // Finished decoding the entire image
962 return kSuccess;
963 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698