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

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

Issue 1254963006: Rename SkCodec_libbmp to SkBmpCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 4 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/SkCodec_libico.cpp » ('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 "SkCodecPriv.h"
10 #include "SkColorPriv.h"
11 #include "SkStream.h"
12
13 /*
14 *
15 * Checks if the conversion between the input image and the requested output
16 * image has been implemented
17 *
18 */
19 static bool conversion_possible(const SkImageInfo& dst,
20 const SkImageInfo& src) {
21 // Ensure that the profile type is unchanged
22 if (dst.profileType() != src.profileType()) {
23 return false;
24 }
25
26 // Check for supported alpha types
27 if (src.alphaType() != dst.alphaType()) {
28 if (kOpaque_SkAlphaType == src.alphaType()) {
29 // If the source is opaque, we must decode to opaque
30 return false;
31 }
32
33 // The source is not opaque
34 switch (dst.alphaType()) {
35 case kPremul_SkAlphaType:
36 case kUnpremul_SkAlphaType:
37 // The source is not opaque, so either of these is okay
38 break;
39 default:
40 // We cannot decode a non-opaque image to opaque (or unknown)
41 return false;
42 }
43 }
44
45 // Check for supported color types
46 switch (dst.colorType()) {
47 // Allow output to kN32 from any type of input
48 case kN32_SkColorType:
49 return true;
50 // Allow output to kIndex_8 from compatible inputs
51 case kIndex_8_SkColorType:
52 return kIndex_8_SkColorType == src.colorType();
53 default:
54 return false;
55 }
56 }
57
58 /*
59 *
60 * Defines the version and type of the second bitmap header
61 *
62 */
63 enum BitmapHeaderType {
64 kInfoV1_BitmapHeaderType,
65 kInfoV2_BitmapHeaderType,
66 kInfoV3_BitmapHeaderType,
67 kInfoV4_BitmapHeaderType,
68 kInfoV5_BitmapHeaderType,
69 kOS2V1_BitmapHeaderType,
70 kOS2VX_BitmapHeaderType,
71 kUnknown_BitmapHeaderType
72 };
73
74 /*
75 *
76 * Possible bitmap compression types
77 *
78 */
79 enum BitmapCompressionMethod {
80 kNone_BitmapCompressionMethod = 0,
81 k8BitRLE_BitmapCompressionMethod = 1,
82 k4BitRLE_BitmapCompressionMethod = 2,
83 kBitMasks_BitmapCompressionMethod = 3,
84 kJpeg_BitmapCompressionMethod = 4,
85 kPng_BitmapCompressionMethod = 5,
86 kAlphaBitMasks_BitmapCompressionMethod = 6,
87 kCMYK_BitmapCompressionMethod = 11,
88 kCMYK8BitRLE_BitmapCompressionMethod = 12,
89 kCMYK4BitRLE_BitmapCompressionMethod = 13
90 };
91
92 /*
93 *
94 * Checks the start of the stream to see if the image is a bitmap
95 *
96 */
97 bool SkBmpCodec::IsBmp(SkStream* stream) {
98 // TODO: Support "IC", "PT", "CI", "CP", "BA"
99 const char bmpSig[] = { 'B', 'M' };
100 char buffer[sizeof(bmpSig)];
101 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) &&
102 !memcmp(buffer, bmpSig, sizeof(bmpSig));
103 }
104
105 /*
106 *
107 * Assumes IsBmp was called and returned true
108 * Creates a bmp decoder
109 * Reads enough of the stream to determine the image format
110 *
111 */
112 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
113 return SkBmpCodec::NewFromStream(stream, false);
114 }
115
116 /*
117 *
118 * Creates a bmp decoder for a bmp embedded in ico
119 * Reads enough of the stream to determine the image format
120 *
121 */
122 SkCodec* SkBmpCodec::NewFromIco(SkStream* stream) {
123 return SkBmpCodec::NewFromStream(stream, true);
124 }
125
126 /*
127 *
128 * Read enough of the stream to initialize the SkBmpCodec. Returns a bool
129 * representing success or failure. If it returned true, and codecOut was
130 * not NULL, it will be set to a new SkBmpCodec.
131 * Does *not* take ownership of the passed in SkStream.
132 *
133 */
134 bool SkBmpCodec::ReadHeader(SkStream* stream, bool isIco, SkCodec** codecOut) {
135 // Header size constants
136 static const uint32_t kBmpHeaderBytes = 14;
137 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
138 static const uint32_t kBmpOS2V1Bytes = 12;
139 static const uint32_t kBmpOS2V2Bytes = 64;
140 static const uint32_t kBmpInfoBaseBytes = 16;
141 static const uint32_t kBmpInfoV1Bytes = 40;
142 static const uint32_t kBmpInfoV2Bytes = 52;
143 static const uint32_t kBmpInfoV3Bytes = 56;
144 static const uint32_t kBmpInfoV4Bytes = 108;
145 static const uint32_t kBmpInfoV5Bytes = 124;
146 static const uint32_t kBmpMaskBytes = 12;
147
148 // The total bytes in the bmp file
149 // We only need to use this value for RLE decoding, so we will only
150 // check that it is valid in the RLE case.
151 uint32_t totalBytes;
152 // The offset from the start of the file where the pixel data begins
153 uint32_t offset;
154 // The size of the second (info) header in bytes
155 uint32_t infoBytes;
156
157 // Bmps embedded in Icos skip the first Bmp header
158 if (!isIco) {
159 // Read the first header and the size of the second header
160 SkAutoTDeleteArray<uint8_t> hBuffer(
161 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour));
162 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
163 kBmpHeaderBytesPlusFour) {
164 SkCodecPrintf("Error: unable to read first bitmap header.\n");
165 return false;
166 }
167
168 totalBytes = get_int(hBuffer.get(), 2);
169 offset = get_int(hBuffer.get(), 10);
170 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
171 SkCodecPrintf("Error: invalid starting location for pixel data\n");
172 return false;
173 }
174
175 // The size of the second (info) header in bytes
176 // The size is the first field of the second header, so we have already
177 // read the first four infoBytes.
178 infoBytes = get_int(hBuffer.get(), 14);
179 if (infoBytes < kBmpOS2V1Bytes) {
180 SkCodecPrintf("Error: invalid second header size.\n");
181 return false;
182 }
183 } else {
184 // This value is only used by RLE compression. Bmp in Ico files do not
185 // use RLE. If the compression field is incorrectly signaled as RLE,
186 // we will catch this and signal an error below.
187 totalBytes = 0;
188
189 // Bmps in Ico cannot specify an offset. We will always assume that
190 // pixel data begins immediately after the color table. This value
191 // will be corrected below.
192 offset = 0;
193
194 // Read the size of the second header
195 SkAutoTDeleteArray<uint8_t> hBuffer(
196 SkNEW_ARRAY(uint8_t, 4));
197 if (stream->read(hBuffer.get(), 4) != 4) {
198 SkCodecPrintf("Error: unable to read size of second bitmap header.\n ");
199 return false;
200 }
201 infoBytes = get_int(hBuffer.get(), 0);
202 if (infoBytes < kBmpOS2V1Bytes) {
203 SkCodecPrintf("Error: invalid second header size.\n");
204 return false;
205 }
206 }
207
208 // We already read the first four bytes of the info header to get the size
209 const uint32_t infoBytesRemaining = infoBytes - 4;
210
211 // Read the second header
212 SkAutoTDeleteArray<uint8_t> iBuffer(
213 SkNEW_ARRAY(uint8_t, infoBytesRemaining));
214 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
215 SkCodecPrintf("Error: unable to read second bitmap header.\n");
216 return false;
217 }
218
219 // The number of bits used per pixel in the pixel data
220 uint16_t bitsPerPixel;
221
222 // The compression method for the pixel data
223 uint32_t compression = kNone_BitmapCompressionMethod;
224
225 // Number of colors in the color table, defaults to 0 or max (see below)
226 uint32_t numColors = 0;
227
228 // Bytes per color in the color table, early versions use 3, most use 4
229 uint32_t bytesPerColor;
230
231 // The image width and height
232 int width, height;
233
234 // Determine image information depending on second header format
235 BitmapHeaderType headerType;
236 if (infoBytes >= kBmpInfoBaseBytes) {
237 // Check the version of the header
238 switch (infoBytes) {
239 case kBmpInfoV1Bytes:
240 headerType = kInfoV1_BitmapHeaderType;
241 break;
242 case kBmpInfoV2Bytes:
243 headerType = kInfoV2_BitmapHeaderType;
244 break;
245 case kBmpInfoV3Bytes:
246 headerType = kInfoV3_BitmapHeaderType;
247 break;
248 case kBmpInfoV4Bytes:
249 headerType = kInfoV4_BitmapHeaderType;
250 break;
251 case kBmpInfoV5Bytes:
252 headerType = kInfoV5_BitmapHeaderType;
253 break;
254 case 16:
255 case 20:
256 case 24:
257 case 28:
258 case 32:
259 case 36:
260 case 42:
261 case 46:
262 case 48:
263 case 60:
264 case kBmpOS2V2Bytes:
265 headerType = kOS2VX_BitmapHeaderType;
266 break;
267 default:
268 // We do not signal an error here because there is the
269 // possibility of new or undocumented bmp header types. Most
270 // of the newer versions of bmp headers are similar to and
271 // build off of the older versions, so we may still be able to
272 // decode the bmp.
273 SkCodecPrintf("Warning: unknown bmp header format.\n");
274 headerType = kUnknown_BitmapHeaderType;
275 break;
276 }
277 // We check the size of the header before entering the if statement.
278 // We should not reach this point unless the size is large enough for
279 // these required fields.
280 SkASSERT(infoBytesRemaining >= 12);
281 width = get_int(iBuffer.get(), 0);
282 height = get_int(iBuffer.get(), 4);
283 bitsPerPixel = get_short(iBuffer.get(), 10);
284
285 // Some versions do not have these fields, so we check before
286 // overwriting the default value.
287 if (infoBytesRemaining >= 16) {
288 compression = get_int(iBuffer.get(), 12);
289 if (infoBytesRemaining >= 32) {
290 numColors = get_int(iBuffer.get(), 28);
291 }
292 }
293
294 // All of the headers that reach this point, store color table entries
295 // using 4 bytes per pixel.
296 bytesPerColor = 4;
297 } else if (infoBytes >= kBmpOS2V1Bytes) {
298 // The OS2V1 is treated separately because it has a unique format
299 headerType = kOS2V1_BitmapHeaderType;
300 width = (int) get_short(iBuffer.get(), 0);
301 height = (int) get_short(iBuffer.get(), 2);
302 bitsPerPixel = get_short(iBuffer.get(), 6);
303 bytesPerColor = 3;
304 } else {
305 // There are no valid bmp headers
306 SkCodecPrintf("Error: second bitmap header size is invalid.\n");
307 return false;
308 }
309
310 // Check for valid dimensions from header
311 RowOrder rowOrder = kBottomUp_RowOrder;
312 if (height < 0) {
313 height = -height;
314 rowOrder = kTopDown_RowOrder;
315 }
316 // The height field for bmp in ico is double the actual height because they
317 // contain an XOR mask followed by an AND mask
318 if (isIco) {
319 height /= 2;
320 }
321 if (width <= 0 || height <= 0) {
322 // TODO: Decide if we want to disable really large bmps as well.
323 // https://code.google.com/p/skia/issues/detail?id=3617
324 SkCodecPrintf("Error: invalid bitmap dimensions.\n");
325 return false;
326 }
327
328 // Create mask struct
329 SkMasks::InputMasks inputMasks;
330 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
331
332 // Determine the input compression format and set bit masks if necessary
333 uint32_t maskBytes = 0;
334 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat;
335 switch (compression) {
336 case kNone_BitmapCompressionMethod:
337 inputFormat = kStandard_BitmapInputFormat;
338 break;
339 case k8BitRLE_BitmapCompressionMethod:
340 if (bitsPerPixel != 8) {
341 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
342 bitsPerPixel = 8;
343 }
344 inputFormat = kRLE_BitmapInputFormat;
345 break;
346 case k4BitRLE_BitmapCompressionMethod:
347 if (bitsPerPixel != 4) {
348 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
349 bitsPerPixel = 4;
350 }
351 inputFormat = kRLE_BitmapInputFormat;
352 break;
353 case kAlphaBitMasks_BitmapCompressionMethod:
354 case kBitMasks_BitmapCompressionMethod:
355 // Load the masks
356 inputFormat = kBitMask_BitmapInputFormat;
357 switch (headerType) {
358 case kInfoV1_BitmapHeaderType: {
359 // The V1 header stores the bit masks after the header
360 SkAutoTDeleteArray<uint8_t> mBuffer(
361 SkNEW_ARRAY(uint8_t, kBmpMaskBytes));
362 if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
363 kBmpMaskBytes) {
364 SkCodecPrintf("Error: unable to read bit inputMasks.\n") ;
365 return false;
366 }
367 maskBytes = kBmpMaskBytes;
368 inputMasks.red = get_int(mBuffer.get(), 0);
369 inputMasks.green = get_int(mBuffer.get(), 4);
370 inputMasks.blue = get_int(mBuffer.get(), 8);
371 break;
372 }
373 case kInfoV2_BitmapHeaderType:
374 case kInfoV3_BitmapHeaderType:
375 case kInfoV4_BitmapHeaderType:
376 case kInfoV5_BitmapHeaderType:
377 // Header types are matched based on size. If the header
378 // is V2+, we are guaranteed to be able to read at least
379 // this size.
380 SkASSERT(infoBytesRemaining >= 48);
381 inputMasks.red = get_int(iBuffer.get(), 36);
382 inputMasks.green = get_int(iBuffer.get(), 40);
383 inputMasks.blue = get_int(iBuffer.get(), 44);
384 break;
385 case kOS2VX_BitmapHeaderType:
386 // TODO: Decide if we intend to support this.
387 // It is unsupported in the previous version and
388 // in chromium. I have not come across a test case
389 // that uses this format.
390 SkCodecPrintf("Error: huffman format unsupported.\n");
391 return false;
392 default:
393 SkCodecPrintf("Error: invalid bmp bit masks header.\n");
394 return false;
395 }
396 break;
397 case kJpeg_BitmapCompressionMethod:
398 if (24 == bitsPerPixel) {
399 inputFormat = kRLE_BitmapInputFormat;
400 break;
401 }
402 // Fall through
403 case kPng_BitmapCompressionMethod:
404 // TODO: Decide if we intend to support this.
405 // It is unsupported in the previous version and
406 // in chromium. I think it is used mostly for printers.
407 SkCodecPrintf("Error: compression format not supported.\n");
408 return false;
409 case kCMYK_BitmapCompressionMethod:
410 case kCMYK8BitRLE_BitmapCompressionMethod:
411 case kCMYK4BitRLE_BitmapCompressionMethod:
412 // TODO: Same as above.
413 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n");
414 return false;
415 default:
416 SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
417 return false;
418 }
419
420 // Most versions of bmps should be rendered as opaque. Either they do
421 // not have an alpha channel, or they expect the alpha channel to be
422 // ignored. V3+ bmp files introduce an alpha mask and allow the creator
423 // of the image to use the alpha channels. However, many of these images
424 // leave the alpha channel blank and expect to be rendered as opaque. This
425 // is the case for almost all V3 images, so we render these as opaque. For
426 // V4+, we will use the alpha channel, and fix the image later if it turns
427 // out to be fully transparent.
428 // As an exception, V3 bmp-in-ico may use an alpha mask.
429 SkAlphaType alphaType = kOpaque_SkAlphaType;
430 if ((kInfoV3_BitmapHeaderType == headerType && isIco) ||
431 kInfoV4_BitmapHeaderType == headerType ||
432 kInfoV5_BitmapHeaderType == headerType) {
433 // Header types are matched based on size. If the header is
434 // V3+, we are guaranteed to be able to read at least this size.
435 SkASSERT(infoBytesRemaining > 52);
436 inputMasks.alpha = get_int(iBuffer.get(), 48);
437 if (inputMasks.alpha != 0) {
438 alphaType = kUnpremul_SkAlphaType;
439 }
440 }
441 iBuffer.free();
442
443 // Additionally, 32 bit bmp-in-icos use the alpha channel.
444 // And, RLE inputs may skip pixels, leaving them as transparent. This
445 // is uncommon, but we cannot be certain that an RLE bmp will be opaque.
446 if ((isIco && 32 == bitsPerPixel) || (kRLE_BitmapInputFormat == inputFormat) ) {
447 alphaType = kUnpremul_SkAlphaType;
448 }
449
450 // Check for valid bits per pixel.
451 // At the same time, use this information to choose a suggested color type
452 // and to set default masks.
453 SkColorType colorType = kN32_SkColorType;
454 switch (bitsPerPixel) {
455 // In addition to more standard pixel compression formats, bmp supports
456 // the use of bit masks to determine pixel components. The standard
457 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
458 // which does not map well to any Skia color formats. For this reason,
459 // we will always enable mask mode with 16 bits per pixel.
460 case 16:
461 if (kBitMask_BitmapInputFormat != inputFormat) {
462 inputMasks.red = 0x7C00;
463 inputMasks.green = 0x03E0;
464 inputMasks.blue = 0x001F;
465 inputFormat = kBitMask_BitmapInputFormat;
466 }
467 break;
468 // We want to decode to kIndex_8 for input formats that are already
469 // designed in index format.
470 case 1:
471 case 2:
472 case 4:
473 case 8:
474 // However, we cannot in RLE format since we may need to leave some
475 // pixels as transparent. Similarly, we also cannot for ICO images
476 // since we may need to apply a transparent mask.
477 if (kRLE_BitmapInputFormat != inputFormat && !isIco) {
478 colorType = kIndex_8_SkColorType;
479 }
480 case 24:
481 case 32:
482 break;
483 default:
484 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
485 return false;
486 }
487
488 // Check that input bit masks are valid and create the masks object
489 SkAutoTDelete<SkMasks>
490 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
491 if (NULL == masks) {
492 SkCodecPrintf("Error: invalid input masks.\n");
493 return false;
494 }
495
496 // Check for a valid number of total bytes when in RLE mode
497 if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) {
498 SkCodecPrintf("Error: RLE requires valid input size.\n");
499 return false;
500 }
501 const size_t RLEBytes = totalBytes - offset;
502
503 // Calculate the number of bytes read so far
504 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
505 if (!isIco && offset < bytesRead) {
506 SkCodecPrintf("Error: pixel data offset less than header size.\n");
507 return false;
508 }
509
510 if (codecOut) {
511 // Return the codec
512 // We will use ImageInfo to store width, height, suggested color type, a nd
513 // suggested alpha type.
514 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
515 colorType, alphaType);
516 *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
517 inputFormat, masks.detach(),
518 numColors, bytesPerColor,
519 offset - bytesRead, rowOrder,
520 RLEBytes, isIco));
521 }
522 return true;
523 }
524
525 /*
526 *
527 * Creates a bmp decoder
528 * Reads enough of the stream to determine the image format
529 *
530 */
531 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) {
532 SkAutoTDelete<SkStream> streamDeleter(stream);
533 SkCodec* codec = NULL;
534 if (ReadHeader(stream, isIco, &codec)) {
535 // codec has taken ownership of stream, so we do not need to
536 // delete it.
537 SkASSERT(codec);
538 streamDeleter.detach();
539 return codec;
540 }
541 return NULL;
542 }
543
544 /*
545 *
546 * Creates an instance of the decoder
547 * Called only by NewFromStream
548 *
549 */
550 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
551 uint16_t bitsPerPixel, BitmapInputFormat inputFormat,
552 SkMasks* masks, uint32_t numColors,
553 uint32_t bytesPerColor, uint32_t offset,
554 RowOrder rowOrder, size_t RLEBytes, bool isIco)
555 : INHERITED(info, stream)
556 , fBitsPerPixel(bitsPerPixel)
557 , fInputFormat(inputFormat)
558 , fMasks(masks)
559 , fColorTable(NULL)
560 , fNumColors(numColors)
561 , fBytesPerColor(bytesPerColor)
562 , fOffset(offset)
563 , fRowOrder(rowOrder)
564 , fRLEBytes(RLEBytes)
565 , fIsIco(isIco)
566
567 {}
568
569 /*
570 *
571 * Initiates the bitmap decode
572 *
573 */
574 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
575 void* dst, size_t dstRowBytes,
576 const Options& opts,
577 SkPMColor* inputColorPtr,
578 int* inputColorCount) {
579 // Check for proper input and output formats
580 SkCodec::RewindState rewindState = this->rewindIfNeeded();
581 if (rewindState == kCouldNotRewind_RewindState) {
582 return kCouldNotRewind;
583 } else if (rewindState == kRewound_RewindState) {
584 if (!ReadHeader(this->stream(), fIsIco, NULL)) {
585 return kCouldNotRewind;
586 }
587 }
588 if (opts.fSubset) {
589 // Subsets are not supported.
590 return kUnimplemented;
591 }
592 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
593 SkCodecPrintf("Error: scaling not supported.\n");
594 return kInvalidScale;
595 }
596 if (!conversion_possible(dstInfo, this->getInfo())) {
597 SkCodecPrintf("Error: cannot convert input type to output type.\n");
598 return kInvalidConversion;
599 }
600
601 // Create the color table if necessary and prepare the stream for decode
602 // Note that if it is non-NULL, inputColorCount will be modified
603 if (!createColorTable(dstInfo.alphaType(), inputColorCount)) {
604 SkCodecPrintf("Error: could not create color table.\n");
605 return kInvalidInput;
606 }
607
608 // Copy the color table to the client if necessary
609 copy_color_table(dstInfo, fColorTable, inputColorPtr, inputColorCount);
610
611 // Perform the decode
612 switch (fInputFormat) {
613 case kBitMask_BitmapInputFormat:
614 return decodeMask(dstInfo, dst, dstRowBytes, opts);
615 case kRLE_BitmapInputFormat:
616 return decodeRLE(dstInfo, dst, dstRowBytes, opts);
617 case kStandard_BitmapInputFormat:
618 return decode(dstInfo, dst, dstRowBytes, opts);
619 default:
620 SkASSERT(false);
621 return kInvalidInput;
622 }
623 }
624
625 /*
626 *
627 * Process the color table for the bmp input
628 *
629 */
630 bool SkBmpCodec::createColorTable(SkAlphaType alphaType, int* numColors) {
631 // Allocate memory for color table
632 uint32_t colorBytes = 0;
633 uint32_t maxColors = 0;
634 SkPMColor colorTable[256];
635 if (fBitsPerPixel <= 8) {
636 // Zero is a default for maxColors
637 // Also set fNumColors to maxColors when it is too large
638 maxColors = 1 << fBitsPerPixel;
639 if (fNumColors == 0 || fNumColors >= maxColors) {
640 fNumColors = maxColors;
641 }
642
643 // Inform the caller of the number of colors
644 if (NULL != numColors) {
645 // We set the number of colors to maxColors in order to ensure
646 // safe memory accesses. Otherwise, an invalid pixel could
647 // access memory outside of our color table array.
648 *numColors = maxColors;
649 }
650
651 // Read the color table from the stream
652 colorBytes = fNumColors * fBytesPerColor;
653 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
654 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) {
655 SkCodecPrintf("Error: unable to read color table.\n");
656 return false;
657 }
658
659 // Choose the proper packing function
660 SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t);
661 switch (alphaType) {
662 case kOpaque_SkAlphaType:
663 case kUnpremul_SkAlphaType:
664 packARGB = &SkPackARGB32NoCheck;
665 break;
666 case kPremul_SkAlphaType:
667 packARGB = &SkPreMultiplyARGB;
668 break;
669 default:
670 // This should not be reached because conversion possible
671 // should fail if the alpha type is not one of the above
672 // values.
673 SkASSERT(false);
674 packARGB = NULL;
675 break;
676 }
677
678 // Fill in the color table
679 uint32_t i = 0;
680 for (; i < fNumColors; i++) {
681 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor);
682 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1);
683 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2);
684 uint8_t alpha;
685 if (kOpaque_SkAlphaType == alphaType || kRLE_BitmapInputFormat == fI nputFormat) {
686 alpha = 0xFF;
687 } else {
688 alpha = (fMasks->getAlphaMask() >> 24) &
689 get_byte(cBuffer.get(), i*fBytesPerColor + 3);
690 }
691 colorTable[i] = packARGB(alpha, red, green, blue);
692 }
693
694 // To avoid segmentation faults on bad pixel data, fill the end of the
695 // color table with black. This is the same the behavior as the
696 // chromium decoder.
697 for (; i < maxColors; i++) {
698 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
699 }
700
701 // Set the color table
702 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors)));
703 }
704
705 // Bmp-in-Ico files do not use an offset to indicate where the pixel data
706 // begins. Pixel data always begins immediately after the color table.
707 if (!fIsIco) {
708 // Check that we have not read past the pixel array offset
709 if(fOffset < colorBytes) {
710 // This may occur on OS 2.1 and other old versions where the color
711 // table defaults to max size, and the bmp tries to use a smaller
712 // color table. This is invalid, and our decision is to indicate
713 // an error, rather than try to guess the intended size of the
714 // color table.
715 SkCodecPrintf("Error: pixel data offset less than color table size.\ n");
716 return false;
717 }
718
719 // After reading the color table, skip to the start of the pixel array
720 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) {
721 SkCodecPrintf("Error: unable to skip to image data.\n");
722 return false;
723 }
724 }
725
726 // Return true on success
727 return true;
728 }
729
730 /*
731 *
732 * Get the destination row to start filling from
733 * Used to fill the remainder of the image on incomplete input
734 *
735 */
736 static inline void* get_dst_start_row(void* dst, size_t dstRowBytes, int32_t y,
737 SkBmpCodec::RowOrder rowOrder) {
738 return (SkBmpCodec::kTopDown_RowOrder == rowOrder) ?
739 SkTAddOffset<void*>(dst, y * dstRowBytes) : dst;
740 }
741
742 /*
743 *
744 * Performs the bitmap decoding for bit masks input format
745 *
746 */
747 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
748 void* dst, size_t dstRowBytes,
749 const Options& opts) {
750 // Set constant values
751 const int width = dstInfo.width();
752 const int height = dstInfo.height();
753 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
754
755 // Allocate a buffer large enough to hold the full image
756 SkAutoTDeleteArray<uint8_t>
757 srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes));
758 uint8_t* srcRow = srcBuffer.get();
759
760 // Create the swizzler
761 SkAutoTDelete<SkMaskSwizzler> maskSwizzler(
762 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, fMasks, fBitsPerPixel));
763
764 // Iterate over rows of the image
765 bool transparent = true;
766 for (int y = 0; y < height; y++) {
767 // Read a row of the input
768 if (stream()->read(srcRow, rowBytes) != rowBytes) {
769 SkCodecPrintf("Warning: incomplete input stream.\n");
770 // Fill the destination image on failure
771 SkPMColor fillColor = dstInfo.alphaType() == kOpaque_SkAlphaType ?
772 SK_ColorBLACK : SK_ColorTRANSPARENT;
773 if (kNo_ZeroInitialized == opts.fZeroInitialized || 0 != fillColor) {
774 void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrde r);
775 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, fillColor,
776 NULL);
777 }
778 return kIncompleteInput;
779 }
780
781 // Decode the row in destination format
782 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y;
783 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * row);
784 SkSwizzler::ResultAlpha r = maskSwizzler->swizzle(dstRow, srcRow);
785 transparent &= SkSwizzler::IsTransparent(r);
786
787 // Move to the next row
788 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
789 }
790
791 // Some fully transparent bmp images are intended to be opaque. Here, we
792 // correct for this possibility.
793 if (transparent) {
794 const SkImageInfo& opaqueInfo =
795 dstInfo.makeAlphaType(kOpaque_SkAlphaType);
796 SkAutoTDelete<SkMaskSwizzler> opaqueSwizzler(
797 SkMaskSwizzler::CreateMaskSwizzler(opaqueInfo, fMasks, fBitsPerP ixel));
798 srcRow = srcBuffer.get();
799 for (int y = 0; y < height; y++) {
800 // Decode the row in opaque format
801 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y;
802 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * row);
803 opaqueSwizzler->swizzle(dstRow, srcRow);
804
805 // Move to the next row
806 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
807 }
808 }
809
810 // Finished decoding the entire image
811 return kSuccess;
812 }
813
814 /*
815 *
816 * Set an RLE pixel using the color table
817 *
818 */
819 void SkBmpCodec::setRLEPixel(void* dst, size_t dstRowBytes,
820 const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
821 uint8_t index) {
822 // Set the row
823 int height = dstInfo.height();
824 int row;
825 if (kBottomUp_RowOrder == fRowOrder) {
826 row = height - y - 1;
827 } else {
828 row = y;
829 }
830
831 // Set the pixel based on destination color type
832 switch (dstInfo.colorType()) {
833 case kN32_SkColorType: {
834 SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst,
835 row * (int) dstRowBytes);
836 dstRow[x] = fColorTable->operator[](index);
837 break;
838 }
839 default:
840 // This case should not be reached. We should catch an invalid
841 // color type when we check that the conversion is possible.
842 SkASSERT(false);
843 break;
844 }
845 }
846
847 /*
848 *
849 * Set an RLE pixel from R, G, B values
850 *
851 */
852 void SkBmpCodec::setRLE24Pixel(void* dst, size_t dstRowBytes,
853 const SkImageInfo& dstInfo, uint32_t x,
854 uint32_t y, uint8_t red, uint8_t green,
855 uint8_t blue) {
856 // Set the row
857 int height = dstInfo.height();
858 int row;
859 if (kBottomUp_RowOrder == fRowOrder) {
860 row = height - y - 1;
861 } else {
862 row = y;
863 }
864
865 // Set the pixel based on destination color type
866 switch (dstInfo.colorType()) {
867 case kN32_SkColorType: {
868 SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst,
869 row * (int) dstRowBytes);
870 dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue);
871 break;
872 }
873 default:
874 // This case should not be reached. We should catch an invalid
875 // color type when we check that the conversion is possible.
876 SkASSERT(false);
877 break;
878 }
879 }
880
881 /*
882 *
883 * Performs the bitmap decoding for RLE input format
884 * RLE decoding is performed all at once, rather than a one row at a time
885 *
886 */
887 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
888 void* dst, size_t dstRowBytes,
889 const Options& opts) {
890 // Set RLE flags
891 static const uint8_t RLE_ESCAPE = 0;
892 static const uint8_t RLE_EOL = 0;
893 static const uint8_t RLE_EOF = 1;
894 static const uint8_t RLE_DELTA = 2;
895
896 // Set constant values
897 const int width = dstInfo.width();
898 const int height = dstInfo.height();
899
900 // Input buffer parameters
901 uint32_t currByte = 0;
902 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes));
903 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes);
904 if (totalBytes < fRLEBytes) {
905 SkCodecPrintf("Warning: incomplete RLE file.\n");
906 } else if (totalBytes <= 0) {
907 SkCodecPrintf("Error: could not read RLE image data.\n");
908 return kInvalidInput;
909 }
910
911 // Destination parameters
912 int x = 0;
913 int y = 0;
914
915 // Set the background as transparent. Then, if the RLE code skips pixels,
916 // the skipped pixels will be transparent.
917 // Because of the need for transparent pixels, kN32 is the only color
918 // type that makes sense for the destination format.
919 SkASSERT(kN32_SkColorType == dstInfo.colorType());
920 if (kNo_ZeroInitialized == opts.fZeroInitialized) {
921 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, SK_ColorTRANSPARENT, NULL);
922 }
923
924 while (true) {
925 // Every entry takes at least two bytes
926 if ((int) totalBytes - currByte < 2) {
927 SkCodecPrintf("Warning: incomplete RLE input.\n");
928 return kIncompleteInput;
929 }
930
931 // Read the next two bytes. These bytes have different meanings
932 // depending on their values. In the first interpretation, the first
933 // byte is an escape flag and the second byte indicates what special
934 // task to perform.
935 const uint8_t flag = buffer.get()[currByte++];
936 const uint8_t task = buffer.get()[currByte++];
937
938 // If we have reached a row that is beyond the image size, and the RLE
939 // code does not indicate end of file, abort and signal a warning.
940 if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) {
941 SkCodecPrintf("Warning: invalid RLE input.\n");
942 return kIncompleteInput;
943 }
944
945 // Perform decoding
946 if (RLE_ESCAPE == flag) {
947 switch (task) {
948 case RLE_EOL:
949 x = 0;
950 y++;
951 break;
952 case RLE_EOF:
953 return kSuccess;
954 case RLE_DELTA: {
955 // Two bytes are needed to specify delta
956 if ((int) totalBytes - currByte < 2) {
957 SkCodecPrintf("Warning: incomplete RLE input\n");
958 return kIncompleteInput;
959 }
960 // Modify x and y
961 const uint8_t dx = buffer.get()[currByte++];
962 const uint8_t dy = buffer.get()[currByte++];
963 x += dx;
964 y += dy;
965 if (x > width || y > height) {
966 SkCodecPrintf("Warning: invalid RLE input.\n");
967 return kIncompleteInput;
968 }
969 break;
970 }
971 default: {
972 // If task does not match any of the above signals, it
973 // indicates that we have a sequence of non-RLE pixels.
974 // Furthermore, the value of task is equal to the number
975 // of pixels to interpret.
976 uint8_t numPixels = task;
977 const size_t rowBytes = compute_row_bytes(numPixels,
978 fBitsPerPixel);
979 // Abort if setting numPixels moves us off the edge of the
980 // image. Also abort if there are not enough bytes
981 // remaining in the stream to set numPixels.
982 if (x + numPixels > width ||
983 (int) totalBytes - currByte < SkAlign2(rowBytes)) {
984 SkCodecPrintf("Warning: invalid RLE input.\n");
985 return kIncompleteInput;
986 }
987 // Set numPixels number of pixels
988 while (numPixels > 0) {
989 switch(fBitsPerPixel) {
990 case 4: {
991 SkASSERT(currByte < totalBytes);
992 uint8_t val = buffer.get()[currByte++];
993 setRLEPixel(dst, dstRowBytes, dstInfo, x++,
994 y, val >> 4);
995 numPixels--;
996 if (numPixels != 0) {
997 setRLEPixel(dst, dstRowBytes, dstInfo,
998 x++, y, val & 0xF);
999 numPixels--;
1000 }
1001 break;
1002 }
1003 case 8:
1004 SkASSERT(currByte < totalBytes);
1005 setRLEPixel(dst, dstRowBytes, dstInfo, x++,
1006 y, buffer.get()[currByte++]);
1007 numPixels--;
1008 break;
1009 case 24: {
1010 SkASSERT(currByte + 2 < totalBytes);
1011 uint8_t blue = buffer.get()[currByte++];
1012 uint8_t green = buffer.get()[currByte++];
1013 uint8_t red = buffer.get()[currByte++];
1014 setRLE24Pixel(dst, dstRowBytes, dstInfo,
1015 x++, y, red, green, blue);
1016 numPixels--;
1017 }
1018 default:
1019 SkASSERT(false);
1020 return kInvalidInput;
1021 }
1022 }
1023 // Skip a byte if necessary to maintain alignment
1024 if (!SkIsAlign2(rowBytes)) {
1025 currByte++;
1026 }
1027 break;
1028 }
1029 }
1030 } else {
1031 // If the first byte read is not a flag, it indicates the number of
1032 // pixels to set in RLE mode.
1033 const uint8_t numPixels = flag;
1034 const int endX = SkTMin<int>(x + numPixels, width);
1035
1036 if (24 == fBitsPerPixel) {
1037 // In RLE24, the second byte read is part of the pixel color.
1038 // There are two more required bytes to finish encoding the
1039 // color.
1040 if ((int) totalBytes - currByte < 2) {
1041 SkCodecPrintf("Warning: incomplete RLE input\n");
1042 return kIncompleteInput;
1043 }
1044
1045 // Fill the pixels up to endX with the specified color
1046 uint8_t blue = task;
1047 uint8_t green = buffer.get()[currByte++];
1048 uint8_t red = buffer.get()[currByte++];
1049 while (x < endX) {
1050 setRLE24Pixel(dst, dstRowBytes, dstInfo, x++, y, red,
1051 green, blue);
1052 }
1053 } else {
1054 // In RLE8 or RLE4, the second byte read gives the index in the
1055 // color table to look up the pixel color.
1056 // RLE8 has one color index that gets repeated
1057 // RLE4 has two color indexes in the upper and lower 4 bits of
1058 // the bytes, which are alternated
1059 uint8_t indices[2] = { task, task };
1060 if (4 == fBitsPerPixel) {
1061 indices[0] >>= 4;
1062 indices[1] &= 0xf;
1063 }
1064
1065 // Set the indicated number of pixels
1066 for (int which = 0; x < endX; x++) {
1067 setRLEPixel(dst, dstRowBytes, dstInfo, x, y,
1068 indices[which]);
1069 which = !which;
1070 }
1071 }
1072 }
1073 }
1074 }
1075
1076 /*
1077 *
1078 * Performs the bitmap decoding for standard input format
1079 *
1080 */
1081 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
1082 void* dst, size_t dstRowBytes,
1083 const Options& opts) {
1084 // Set constant values
1085 const int width = dstInfo.width();
1086 const int height = dstInfo.height();
1087 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
1088
1089 // Get swizzler configuration and choose the fill value for failures. We wi ll use
1090 // zero as the default palette index, black for opaque images, and transpare nt for
1091 // non-opaque images.
1092 SkSwizzler::SrcConfig config;
1093 uint32_t fillColorOrIndex;
1094 bool zeroFill = true;
1095 switch (fBitsPerPixel) {
1096 case 1:
1097 config = SkSwizzler::kIndex1;
1098 fillColorOrIndex = 0;
1099 break;
1100 case 2:
1101 config = SkSwizzler::kIndex2;
1102 fillColorOrIndex = 0;
1103 break;
1104 case 4:
1105 config = SkSwizzler::kIndex4;
1106 fillColorOrIndex = 0;
1107 break;
1108 case 8:
1109 config = SkSwizzler::kIndex;
1110 fillColorOrIndex = 0;
1111 break;
1112 case 24:
1113 config = SkSwizzler::kBGR;
1114 fillColorOrIndex = SK_ColorBLACK;
1115 zeroFill = false;
1116 break;
1117 case 32:
1118 if (kOpaque_SkAlphaType == dstInfo.alphaType()) {
1119 config = SkSwizzler::kBGRX;
1120 fillColorOrIndex = SK_ColorBLACK;
1121 zeroFill = false;
1122 } else {
1123 config = SkSwizzler::kBGRA;
1124 fillColorOrIndex = SK_ColorTRANSPARENT;
1125 }
1126 break;
1127 default:
1128 SkASSERT(false);
1129 return kInvalidInput;
1130 }
1131
1132 // Get a pointer to the color table if it exists
1133 const SkPMColor* colorPtr = NULL != fColorTable.get() ? fColorTable->readCol ors() : NULL;
1134
1135 // Create swizzler
1136 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config,
1137 colorPtr, dstInfo, kNo_ZeroInitialized));
1138
1139 // Allocate space for a row buffer and a source for the swizzler
1140 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
1141
1142 // Iterate over rows of the image
1143 // FIXME: bool transparent = true;
1144 for (int y = 0; y < height; y++) {
1145 // Read a row of the input
1146 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
1147 SkCodecPrintf("Warning: incomplete input stream.\n");
1148 // Fill the destination image on failure
1149 if (kNo_ZeroInitialized == opts.fZeroInitialized || !zeroFill) {
1150 void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrde r);
1151 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y,
1152 fillColorOrIndex, colorPtr);
1153 }
1154 return kIncompleteInput;
1155 }
1156
1157 // Decode the row in destination format
1158 uint32_t row;
1159 if (kTopDown_RowOrder == fRowOrder) {
1160 row = y;
1161 } else {
1162 row = height - 1 - y;
1163 }
1164
1165 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * row);
1166 swizzler->swizzle(dstRow, srcBuffer.get());
1167 // FIXME: SkSwizzler::ResultAlpha r =
1168 // swizzler->swizzle(dstRow, srcBuffer.get());
1169 // FIXME: transparent &= SkSwizzler::IsTransparent(r);
1170 }
1171
1172 // FIXME: This code exists to match the behavior in the chromium decoder
1173 // and to follow the bmp specification as it relates to alpha masks. It is
1174 // commented out because we have yet to discover a test image that provides
1175 // an alpha mask and uses this decode mode.
1176
1177 // Now we adjust the output image with some additional behavior that
1178 // SkSwizzler does not support. Firstly, all bmp images that contain
1179 // alpha are masked by the alpha mask. Secondly, many fully transparent
1180 // bmp images are intended to be opaque. Here, we make those corrections
1181 // in the kN32 case.
1182 /*
1183 SkPMColor* dstRow = (SkPMColor*) dst;
1184 if (SkSwizzler::kBGRA == config) {
1185 for (int y = 0; y < height; y++) {
1186 for (int x = 0; x < width; x++) {
1187 if (transparent) {
1188 dstRow[x] |= 0xFF000000;
1189 } else {
1190 dstRow[x] &= alphaMask;
1191 }
1192 dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes);
1193 }
1194 }
1195 }
1196 */
1197
1198 // Finally, apply the AND mask for bmp-in-ico images
1199 if (fIsIco) {
1200 // The AND mask is always 1 bit per pixel
1201 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1));
1202
1203 SkPMColor* dstPtr = (SkPMColor*) dst;
1204 for (int y = 0; y < height; y++) {
1205 // The srcBuffer will at least be large enough
1206 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
1207 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n");
1208 return kIncompleteInput;
1209 }
1210
1211 int row;
1212 if (kBottomUp_RowOrder == fRowOrder) {
1213 row = height - y - 1;
1214 } else {
1215 row = y;
1216 }
1217
1218 SkPMColor* dstRow =
1219 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes);
1220
1221 for (int x = 0; x < width; x++) {
1222 int quotient;
1223 int modulus;
1224 SkTDivMod(x, 8, &quotient, &modulus);
1225 uint32_t shift = 7 - modulus;
1226 uint32_t alphaBit =
1227 (srcBuffer.get()[quotient] >> shift) & 0x1;
1228 dstRow[x] &= alphaBit - 1;
1229 }
1230 }
1231 }
1232
1233 // Finished decoding the entire image
1234 return kSuccess;
1235 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkCodec_libico.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698