OLD | NEW |
---|---|
(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 "SkColor.h" | |
10 #include "SkEndian.h" | |
11 #include "SkStream.h" | |
12 | |
13 /* | |
14 * | |
15 * Get a byte from the buffer | |
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 /* | |
53 * | |
54 * Used to convert 1-7 bit color components into 8-bit color components | |
55 * | |
56 */ | |
57 const static uint8_t n_bit_to_8_bit_lookup_table[] = { | |
58 // 1 bit | |
59 0, 255, | |
60 // 2 bits | |
61 0, 85, 170, 255, | |
62 // 3 bits | |
63 0, 36, 73, 109, 146, 182, 219, 255, | |
64 // 4 bits | |
65 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255, | |
66 // 5 bits | |
67 0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, | |
68 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255, | |
69 // 6 bits | |
70 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, | |
71 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, | |
72 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198, | |
73 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255, | |
74 // 7 bits | |
75 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, | |
76 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, | |
77 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, | |
78 112, 114, 116, 118, 120, 122, 124, 126, 129, 131, 133, 135, 137, 139, 141, | |
79 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, | |
80 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, | |
81 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, | |
82 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 | |
83 }; | |
84 | |
85 /* | |
86 * | |
87 * Convert an n bit component to an 8-bit component | |
88 * | |
89 */ | |
90 static uint8_t convert_n_to_8(uint32_t component, uint32_t n) { | |
91 if (0 == n) { | |
92 return 0; | |
93 } else if (8 > n) { | |
94 return n_bit_to_8_bit_lookup_table[(1 << n) - 2 + component]; | |
95 } else if (8 == n) { | |
scroggo
2015/03/06 18:56:13
I would change this to:
} else {
SkASSERT(8 ==
| |
96 return component; | |
97 } else { | |
98 SkASSERT(false); | |
99 return 0; | |
100 } | |
101 } | |
102 | |
103 /* | |
104 * | |
105 * Row procedure for masked color components with 16 bits per pixel | |
106 * | |
107 */ | |
108 static SkSwizzler::ResultAlpha swizzle_mask16_to_n32( | |
109 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, | |
110 const SkBmpCodec::BitMasks masks, | |
111 const SkBmpCodec::BitMaskShifts shifts, | |
112 const SkBmpCodec::BitMaskSizes sizes) { | |
113 | |
114 // Use the masks to decode to the destination | |
115 uint16_t* srcPtr = (uint16_t*) src; | |
116 SkColor* SK_RESTRICT dstPtr = (SkColor*) dstRow; | |
117 for (uint32_t i = 0; i < width; i++) { | |
118 uint16_t p = srcPtr[i]; | |
119 uint8_t red = convert_n_to_8( | |
120 (p & masks.redMask) >> shifts.redShift, sizes.redSize); | |
scroggo
2015/03/06 18:56:13
It looks like this same code is repeated a few tim
| |
121 uint8_t green = convert_n_to_8( | |
122 (p & masks.greenMask) >> shifts.greenShift, sizes.greenSize); | |
123 uint8_t blue = convert_n_to_8( | |
124 (p & masks.blueMask) >> shifts.blueShift, sizes.blueSize); | |
125 dstPtr[i] = SkColorSetARGBInline(0xFF, red, green, blue); | |
scroggo
2015/03/06 18:56:12
This doesn't do what we want. We want either premu
| |
126 } | |
127 return SkSwizzler::kOpaque_ResultAlpha; | |
128 } | |
129 | |
130 /* | |
131 * | |
132 * Row procedure for masked color components with 16 bits per pixel with alpha | |
133 * | |
134 */ | |
135 static SkSwizzler::ResultAlpha swizzle_mask16_alpha_to_n32( | |
136 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, | |
137 const SkBmpCodec::BitMasks masks, | |
138 const SkBmpCodec::BitMaskShifts shifts, | |
139 const SkBmpCodec::BitMaskSizes sizes) { | |
140 | |
141 // Use the masks to decode to the destination | |
142 uint16_t* srcPtr = (uint16_t*) src; | |
143 SkColor* SK_RESTRICT dstPtr = (SkColor*) dstRow; | |
144 uint8_t zAlpha = 0; | |
scroggo
2015/03/06 18:56:13
What does zAlpha mean? zeroAlpha?
| |
145 uint8_t mAlpha = 0xFF; | |
scroggo
2015/03/06 18:56:13
I think this is max alpha? Refrain from using mVar
| |
146 for (uint32_t i = 0; i < width; i++) { | |
147 uint16_t p = srcPtr[i]; | |
148 uint8_t red = convert_n_to_8( | |
149 (p & masks.redMask) >> shifts.redShift, sizes.redSize); | |
150 uint8_t green = convert_n_to_8( | |
151 (p & masks.greenMask) >> shifts.greenShift, sizes.greenSize); | |
152 uint8_t blue = convert_n_to_8( | |
153 (p & masks.blueMask) >> shifts.blueShift, sizes.blueSize); | |
154 uint8_t alpha = convert_n_to_8(( | |
155 p & masks.alphaMask) >> shifts.alphaShift, sizes.alphaSize); | |
156 zAlpha |= alpha; | |
157 mAlpha &= alpha; | |
158 dstPtr[i] = SkColorSetARGBInline(alpha, red, green, blue); | |
159 } | |
160 return (mAlpha == 0xFF) ? SkSwizzler::kOpaque_ResultAlpha : | |
scroggo
2015/03/06 18:56:13
Can you make a helper function for this? Something
| |
161 ((zAlpha == 0) ? SkSwizzler::kTransparent_ResultAlpha : | |
162 SkSwizzler::kNeither_ResultAlpha); | |
163 } | |
164 | |
165 /* | |
166 * | |
167 * Row procedure for masked color components with 24 bits per pixel | |
168 * | |
169 */ | |
170 static SkSwizzler::ResultAlpha swizzle_mask24_to_n32( | |
171 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, | |
172 const SkBmpCodec::BitMasks masks, | |
173 const SkBmpCodec::BitMaskShifts shifts, | |
174 const SkBmpCodec::BitMaskSizes sizes) { | |
175 | |
176 // Use the masks to decode to the destination | |
177 SkColor* SK_RESTRICT dstPtr = (SkColor*) dstRow; | |
178 for (uint32_t i = 0; i < 3*width; i += 3) { | |
179 uint32_t p = src[i] | (src[i + 1] << 8) | src[i + 2] << 16; | |
180 uint8_t red = convert_n_to_8( | |
181 (p & masks.redMask) >> shifts.redShift, sizes.redSize); | |
182 uint8_t green = convert_n_to_8( | |
183 (p & masks.greenMask) >> shifts.greenShift, sizes.greenSize); | |
184 uint8_t blue = convert_n_to_8( | |
185 (p & masks.blueMask) >> shifts.blueShift, sizes.blueSize); | |
186 dstPtr[i/3] = SkColorSetARGBInline(0xFF, red, green, blue); | |
187 } | |
188 return SkSwizzler::kOpaque_ResultAlpha; | |
189 } | |
190 | |
191 /* | |
192 * | |
193 * Row procedure for masked color components with 24 bits per pixel with alpha | |
194 * | |
195 */ | |
196 static SkSwizzler::ResultAlpha swizzle_mask24_alpha_to_n32( | |
197 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, | |
198 const SkBmpCodec::BitMasks masks, | |
199 const SkBmpCodec::BitMaskShifts shifts, | |
200 const SkBmpCodec::BitMaskSizes sizes) { | |
201 | |
202 // Use the masks to decode to the destination | |
203 SkColor* SK_RESTRICT dstPtr = (SkColor*) dstRow; | |
204 uint8_t zAlpha = 0; | |
205 uint8_t mAlpha = 0xFF; | |
206 for (uint32_t i = 0; i < 3*width; i += 3) { | |
207 uint32_t p = src[i] | (src[i + 1] << 8) | src[i + 2] << 16; | |
208 uint8_t red = convert_n_to_8( | |
209 (p & masks.redMask) >> shifts.redShift, sizes.redSize); | |
210 uint8_t green = convert_n_to_8( | |
211 (p & masks.greenMask) >> shifts.greenShift, sizes.greenSize); | |
212 uint8_t blue = convert_n_to_8( | |
213 (p & masks.blueMask) >> shifts.blueShift, sizes.blueSize); | |
214 uint8_t alpha = convert_n_to_8(( | |
215 p & masks.alphaMask) >> shifts.alphaShift, sizes.alphaSize); | |
216 zAlpha |= alpha; | |
217 mAlpha &= alpha; | |
218 dstPtr[i/3] = SkColorSetARGBInline(alpha, red, green, blue); | |
219 } | |
220 return (mAlpha == 0xFF) ? SkSwizzler::kOpaque_ResultAlpha : | |
221 ((zAlpha == 0) ? SkSwizzler::kTransparent_ResultAlpha : | |
222 SkSwizzler::kNeither_ResultAlpha); | |
223 } | |
224 | |
225 /* | |
226 * | |
227 * Row procedure for masked color components with 32 bits per pixel | |
228 * | |
229 */ | |
230 static SkSwizzler::ResultAlpha swizzle_mask32_to_n32( | |
231 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, | |
232 const SkBmpCodec::BitMasks masks, | |
233 const SkBmpCodec::BitMaskShifts shifts, | |
234 const SkBmpCodec::BitMaskSizes sizes) { | |
235 | |
236 // Use the masks to decode to the destination | |
237 uint32_t* srcPtr = (uint32_t*) src; | |
238 SkColor* SK_RESTRICT dstPtr = (SkColor*) dstRow; | |
239 for (uint32_t i = 0; i < width; i++) { | |
240 uint32_t p = srcPtr[i]; | |
241 uint8_t red = convert_n_to_8( | |
242 (p & masks.redMask) >> shifts.redShift, sizes.redSize); | |
243 uint8_t green = convert_n_to_8( | |
244 (p & masks.greenMask) >> shifts.greenShift, sizes.greenSize); | |
245 uint8_t blue = convert_n_to_8( | |
246 (p & masks.blueMask) >> shifts.blueShift, sizes.blueSize); | |
247 dstPtr[i] = SkColorSetARGBInline(0xFF, red, green, blue); | |
248 } | |
249 return SkSwizzler::kOpaque_ResultAlpha; | |
250 } | |
251 | |
252 /* | |
253 * | |
254 * Row procedure for masked color components with 32 bits per pixel | |
255 * | |
256 */ | |
257 static SkSwizzler::ResultAlpha swizzle_mask32_alpha_to_n32( | |
258 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, | |
259 const SkBmpCodec::BitMasks masks, | |
260 const SkBmpCodec::BitMaskShifts shifts, | |
261 const SkBmpCodec::BitMaskSizes sizes) { | |
262 | |
263 // Use the masks to decode to the destination | |
264 uint32_t* srcPtr = (uint32_t*) src; | |
265 SkColor* SK_RESTRICT dstPtr = (SkColor*) dstRow; | |
266 uint8_t zAlpha = 0; | |
267 uint8_t mAlpha = 0xFF; | |
268 for (uint32_t i = 0; i < width; i++) { | |
269 uint32_t p = srcPtr[i]; | |
270 uint8_t red = convert_n_to_8( | |
271 (p & masks.redMask) >> shifts.redShift, sizes.redSize); | |
272 uint8_t green = convert_n_to_8( | |
273 (p & masks.greenMask) >> shifts.greenShift, sizes.greenSize); | |
274 uint8_t blue = convert_n_to_8( | |
275 (p & masks.blueMask) >> shifts.blueShift, sizes.blueSize); | |
276 uint8_t alpha = convert_n_to_8(( | |
277 p & masks.alphaMask) >> shifts.alphaShift, sizes.alphaSize); | |
278 zAlpha |= alpha; | |
279 mAlpha &= alpha; | |
280 dstPtr[i] = SkColorSetARGBInline(alpha, red, green, blue); | |
281 } | |
282 return (mAlpha == 0xFF) ? SkSwizzler::kOpaque_ResultAlpha : | |
283 ((zAlpha == 0) ? SkSwizzler::kTransparent_ResultAlpha : | |
284 SkSwizzler::kNeither_ResultAlpha); | |
285 } | |
286 | |
287 /* | |
288 * | |
289 * Checks if the conversion between the input image and the requested output | |
290 * image has been implemented | |
291 * | |
292 */ | |
293 static bool conversion_possible(const SkImageInfo& dst, | |
294 const SkImageInfo& src) { | |
295 // TODO: Support all conversions | |
scroggo
2015/03/06 18:56:13
nit: we won't support *all* conversions, but perha
| |
296 if (kN32_SkColorType != dst.colorType()) { | |
297 return false; | |
298 } | |
299 if (kIgnore_SkAlphaType == dst.alphaType()) { | |
scroggo
2015/03/06 18:56:13
Can we also check for opaque vs non-opaque?
For P
| |
300 SkDebugf("Error: invalid dst alpha type."); | |
301 return false; | |
302 } | |
303 return true; | |
304 } | |
305 | |
306 /* | |
307 * | |
308 * Defines the version and type of the second bitmap header | |
309 * | |
310 */ | |
311 enum BitmapHeaderType { | |
312 kInfoV1_BitmapHeaderType, | |
313 kInfoV2_BitmapHeaderType, | |
314 kInfoV3_BitmapHeaderType, | |
315 kInfoV4_BitmapHeaderType, | |
316 kInfoV5_BitmapHeaderType, | |
317 kOS2V1_BitmapHeaderType, | |
318 kOS2VX_BitmapHeaderType, | |
319 kUnknown_BitmapHeaderType | |
320 }; | |
321 | |
322 /* | |
323 * | |
324 * Possible bitmap compression types | |
325 * | |
326 */ | |
327 enum BitmapCompressionMethod { | |
328 kNone_BitmapCompressionMethod = 0, | |
329 k8BitRLE_BitmapCompressionMethod = 1, | |
330 k4BitRLE_BitmapCompressionMethod = 2, | |
331 kBitMasks_BitmapCompressionMethod = 3, | |
332 kJpeg_BitmapCompressionMethod = 4, | |
333 kPng_BitmapCompressionMethod = 5, | |
334 kAlphaBitMasks_BitmapCompressionMethod = 6, | |
335 kCMYK_BitmapCompressionMethod = 11, | |
336 kCMYK8BitRLE_BitmapCompressionMethod = 12, | |
337 kCMYK4BitRLE_BitmapCompressionMethod = 13 | |
338 }; | |
339 | |
340 /* | |
341 * | |
342 * Checks the start of the stream to see if the image is a bitmap | |
343 * | |
344 */ | |
345 bool SkBmpCodec::IsBmp(SkStream* stream) { | |
346 // TODO: Support "IC", "PT", "CI", "CP", "BA" | |
347 // TODO: ICO files may contain a BMP and need to use this decoder | |
348 const char bmpSig[] = { 'B', 'M' }; | |
349 char buffer[sizeof(bmpSig)]; | |
350 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) && | |
351 !memcmp(buffer, bmpSig, sizeof(bmpSig)); | |
352 } | |
353 | |
354 /* | |
355 * | |
356 * Assumes IsBmp was called and returned true | |
357 * Creates a bitmap decoder | |
358 * Reads enough of the stream to determine the image format | |
359 * | |
360 */ | |
361 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) { | |
msarett
2015/03/05 23:13:17
This function is very long. There is not really r
scroggo
2015/03/05 23:32:35
I'm going to look at the whole of the code more in
| |
362 // Header size constants | |
363 static const uint32_t kBmpHeaderBytes = 14; | |
364 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4; | |
365 static const uint32_t kBmpOS2V1Bytes = 12; | |
366 static const uint32_t kBmpOS2V2Bytes = 64; | |
367 static const uint32_t kBmpInfoBaseBytes = 16; | |
368 static const uint32_t kBmpInfoV1Bytes = 40; | |
369 static const uint32_t kBmpInfoV2Bytes = 52; | |
370 static const uint32_t kBmpInfoV3Bytes = 56; | |
371 static const uint32_t kBmpInfoV4Bytes = 108; | |
372 static const uint32_t kBmpInfoV5Bytes = 124; | |
373 static const uint32_t kBmpMaskBytes = 12; | |
374 | |
375 // Read the first header and the size of the second header | |
376 SkAutoTDeleteArray<uint8_t> hBuffer( | |
377 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour)); | |
378 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) != | |
379 kBmpHeaderBytesPlusFour) { | |
380 SkDebugf("Error: unable to read first bitmap header.\n"); | |
381 return NULL; | |
382 } | |
383 | |
384 // The total bytes in the bmp file | |
385 // We only need to use this value for RLE decoding, so we will only check | |
386 // that it is valid in the RLE case. | |
387 const uint32_t totalBytes = get_int(hBuffer.get(), 2); | |
388 | |
389 // The offset from the start of the file where the pixel data begins | |
390 const uint32_t offset = get_int(hBuffer.get(), 10); | |
391 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) { | |
392 SkDebugf("Error: invalid starting location for pixel data\n"); | |
393 return NULL; | |
394 } | |
395 | |
396 // The size of the second (info) header in bytes | |
397 // The size is the first field of the second header, so we have already | |
398 // read the first four infoBytes. | |
399 const uint32_t infoBytes = get_int(hBuffer.get(), 14); | |
400 if (infoBytes < kBmpOS2V1Bytes) { | |
401 SkDebugf("Error: invalid second header size.\n"); | |
402 return NULL; | |
403 } | |
404 const uint32_t infoBytesRemaining = infoBytes - 4; | |
405 hBuffer.free(); | |
406 | |
407 // Read the second header | |
408 SkAutoTDeleteArray<uint8_t> iBuffer( | |
409 SkNEW_ARRAY(uint8_t, infoBytesRemaining)); | |
410 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) { | |
411 SkDebugf("Error: unable to read second bitmap header.\n"); | |
412 return NULL; | |
413 } | |
414 | |
415 // The number of bits used per pixel in the pixel data | |
416 uint16_t bitsPerPixel; | |
417 | |
418 // The compression method for the pixel data | |
419 uint32_t compression = kNone_BitmapCompressionMethod; | |
420 | |
421 // Number of colors in the color table, defaults to 0 or max (see below) | |
422 uint32_t numColors = 0; | |
423 | |
424 // Bytes per color in the color table, early versions use 3, most use 4 | |
425 uint32_t bytesPerColor; | |
426 | |
427 // The image width and height | |
428 int width, height; | |
429 | |
430 // Determine image information depending on second header format | |
431 BitmapHeaderType headerType; | |
432 if (infoBytes >= kBmpInfoBaseBytes) { | |
433 // Check the version of the header | |
434 switch (infoBytes) { | |
435 case kBmpInfoV1Bytes: | |
436 headerType = kInfoV1_BitmapHeaderType; | |
437 break; | |
438 case kBmpInfoV2Bytes: | |
439 headerType = kInfoV2_BitmapHeaderType; | |
440 break; | |
441 case kBmpInfoV3Bytes: | |
442 headerType = kInfoV3_BitmapHeaderType; | |
443 break; | |
444 case kBmpInfoV4Bytes: | |
445 headerType = kInfoV4_BitmapHeaderType; | |
446 break; | |
447 case kBmpInfoV5Bytes: | |
448 headerType = kInfoV5_BitmapHeaderType; | |
449 break; | |
450 case 16: | |
451 case 20: | |
452 case 24: | |
453 case 28: | |
454 case 32: | |
455 case 36: | |
456 case 42: | |
457 case 46: | |
458 case 48: | |
459 case 60: | |
460 case kBmpOS2V2Bytes: | |
461 headerType = kOS2VX_BitmapHeaderType; | |
462 break; | |
463 default: | |
464 // We do not signal an error here because there is the | |
465 // possibility of new or undocumented bmp header types. Most | |
466 // of the newer versions of bmp headers are similar to and | |
467 // build off of the older versions, so we may still be able to | |
468 // decode the bmp. | |
469 SkDebugf("Warning: unknown bmp header format.\n"); | |
470 headerType = kUnknown_BitmapHeaderType; | |
471 break; | |
472 } | |
473 // We check the size of the header before entering the if statement. | |
474 // We should not reach this point unless the size is large enough for | |
475 // these required fields. | |
476 SkASSERT(infoBytesRemaining >= 12); | |
477 width = get_int(iBuffer.get(), 0); | |
478 height = get_int(iBuffer.get(), 4); | |
479 //uint16_t planes = get_short(iBuffer, 8); | |
480 bitsPerPixel = get_short(iBuffer.get(), 10); | |
481 | |
482 // Some versions do not have this field, so we check before | |
483 // overwriting the default value. | |
484 if (infoBytesRemaining >= 16) { | |
485 compression = get_int(iBuffer.get(), 12); | |
486 } | |
487 | |
488 // Some versions do not have this field, so we check before | |
489 // overwriting the default value. | |
490 if (infoBytesRemaining >= 32) { | |
491 numColors = get_int(iBuffer.get(), 28); | |
492 } | |
493 | |
494 bytesPerColor = 4; | |
495 } else if (infoBytes >= kBmpOS2V1Bytes) { | |
496 // The OS2V1 is treated separately because it has a unique format | |
497 headerType = kOS2V1_BitmapHeaderType; | |
498 width = (int) get_short(iBuffer.get(), 0); | |
499 height = (int) get_short(iBuffer.get(), 2); | |
500 bitsPerPixel = get_short(iBuffer.get(), 6); | |
501 bytesPerColor = 3; | |
502 } else { | |
503 // There are no valid bmp headers | |
504 SkDebugf("Error: second bitmap header size is invalid.\n"); | |
505 return NULL; | |
506 } | |
507 | |
508 // Check for valid dimensions from header | |
509 RowOrder rowOrder = kBottomUp_RowOrder; | |
510 if (height < 0) { | |
511 height = -height; | |
512 rowOrder = kTopDown_RowOrder; | |
513 } | |
514 static const uint32_t kBmpMaxDim = 1 << 16; | |
515 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) { | |
516 // TODO: Decide if we want to support really large bmps. | |
517 SkDebugf("Error: invalid bitmap dimensions.\n"); | |
518 return NULL; | |
519 } | |
520 | |
521 // Create mask struct | |
522 BitMasks masks; | |
523 memset(&masks, 0, 4*sizeof(uint32_t)); | |
524 | |
525 // Determine the input compression format and set bit masks if necessary | |
526 uint32_t maskBytes = 0; | |
527 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat; | |
528 switch (compression) { | |
529 case kNone_BitmapCompressionMethod: | |
530 inputFormat = kStandard_BitmapInputFormat; | |
531 break; | |
532 case k8BitRLE_BitmapCompressionMethod: | |
533 if (bitsPerPixel != 8) { | |
534 SkDebugf("Warning: correcting invalid bitmap format.\n"); | |
535 bitsPerPixel = 8; | |
536 } | |
537 inputFormat = kRLE_BitmapInputFormat; | |
538 break; | |
539 case k4BitRLE_BitmapCompressionMethod: | |
540 if (bitsPerPixel != 4) { | |
541 SkDebugf("Warning: correcting invalid bitmap format.\n"); | |
542 bitsPerPixel = 4; | |
543 } | |
544 inputFormat = kRLE_BitmapInputFormat; | |
545 break; | |
546 case kAlphaBitMasks_BitmapCompressionMethod: | |
547 case kBitMasks_BitmapCompressionMethod: | |
548 // Load the masks | |
549 inputFormat = kBitMask_BitmapInputFormat; | |
550 switch (headerType) { | |
551 case kInfoV1_BitmapHeaderType: { | |
552 // The V1 header stores the bit masks after the header | |
553 SkAutoTDeleteArray<uint8_t> mBuffer( | |
554 SkNEW_ARRAY(uint8_t, kBmpMaskBytes)); | |
555 if (stream->read(mBuffer.get(), kBmpMaskBytes) != | |
556 kBmpMaskBytes) { | |
557 SkDebugf("Error: unable to read bit masks.\n"); | |
558 return NULL; | |
559 } | |
560 maskBytes = kBmpMaskBytes; | |
561 masks.redMask = get_int(mBuffer.get(), 0); | |
562 masks.greenMask = get_int(mBuffer.get(), 4); | |
563 masks.blueMask = get_int(mBuffer.get(), 8); | |
564 break; | |
565 } | |
566 case kInfoV2_BitmapHeaderType: | |
567 case kInfoV3_BitmapHeaderType: | |
568 case kInfoV4_BitmapHeaderType: | |
569 case kInfoV5_BitmapHeaderType: | |
570 // Header types are matched based on size. If the header | |
571 // is V2+, we are guaranteed to be able at least this size. | |
572 SkASSERT(infoBytesRemaining >= 48); | |
573 masks.redMask = get_int(iBuffer.get(), 36); | |
574 masks.greenMask = get_int(iBuffer.get(), 40); | |
575 masks.blueMask = get_int(iBuffer.get(), 44); | |
576 break; | |
577 case kOS2VX_BitmapHeaderType: | |
578 // TODO: Decide if we intend to support this. | |
579 // It is unsupported in the previous version and | |
580 // in chromium. I have not come across a test case | |
581 // that uses this format. | |
582 SkDebugf("Error: huffman format unsupported.\n"); | |
583 return NULL; | |
584 default: | |
585 SkDebugf("Error: invalid bmp bit masks header.\n"); | |
586 return NULL; | |
587 } | |
588 break; | |
589 case kJpeg_BitmapCompressionMethod: | |
590 if (24 == bitsPerPixel) { | |
591 inputFormat = kRLE_BitmapInputFormat; | |
592 break; | |
593 } | |
594 // Fall through | |
595 case kPng_BitmapCompressionMethod: | |
596 // TODO: Decide if we intend to support this. | |
597 // It is unsupported in the previous version and | |
598 // in chromium. I think it is used mostly for printers. | |
599 SkDebugf("Error: compression format not supported.\n"); | |
600 return NULL; | |
601 case kCMYK_BitmapCompressionMethod: | |
602 case kCMYK8BitRLE_BitmapCompressionMethod: | |
603 case kCMYK4BitRLE_BitmapCompressionMethod: | |
604 // TODO: Same as above. | |
605 SkDebugf("Error: CMYK not supported for bitmap decoding.\n"); | |
606 return NULL; | |
607 default: | |
608 SkDebugf("Error: invalid format for bitmap decoding.\n"); | |
609 return NULL; | |
610 } | |
611 | |
612 // Most versions of bmps should to be rendered as opaque. Either they do | |
scroggo
2015/03/06 18:56:13
should be*
| |
613 // not have an alpha channel, or they expect the alpha channel to be | |
614 // ignored. V4+ bmp files introduce an alpha mask and allow the creator | |
615 // of the image to use the alpha channels. However, many of these images | |
616 // leave the alpha channel blank and expect to be rendered as opaque. For | |
617 // this reason, we set the alpha type to kUnknown for V4+ bmps and figure | |
618 // out the alpha type during the decode. | |
619 SkAlphaType alphaType = kOpaque_SkAlphaType; | |
620 if (kInfoV4_BitmapHeaderType == headerType || | |
621 kInfoV5_BitmapHeaderType == headerType) { | |
622 // Header types are matched based on size. If the header is | |
623 // V4+, we are guaranteed to be able at least this size. | |
scroggo
2015/03/06 18:56:13
able... to read?
| |
624 SkASSERT(infoBytesRemaining > 52); | |
625 masks.alphaMask = get_int(iBuffer.get(), 48); | |
626 if (masks.alphaMask != 0) { | |
627 alphaType = kUnpremul_SkAlphaType; | |
628 } | |
629 } | |
630 iBuffer.free(); | |
631 | |
632 // Check for valid bits per pixel input | |
633 switch (bitsPerPixel) { | |
634 // In addition to more standard pixel compression formats, bmp supports | |
635 // the use of bit masks to determine pixel components. The standard | |
636 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB), | |
637 // which does not map well to any Skia color formats. For this reason, | |
638 // we will always enable mask mode with 16 bits per pixel. | |
639 case 16: | |
640 if (kBitMask_BitmapInputFormat != inputFormat) { | |
641 masks.redMask = 0x7C00; | |
642 masks.greenMask = 0x03E0; | |
643 masks.blueMask = 0x001F; | |
644 inputFormat = kBitMask_BitmapInputFormat; | |
645 } | |
646 break; | |
647 case 1: | |
648 case 2: | |
649 case 4: | |
650 case 8: | |
651 case 24: | |
652 case 32: | |
653 break; | |
654 default: | |
655 SkDebugf("Error: invalid input value for bits per pixel.\n"); | |
656 return NULL; | |
657 } | |
658 | |
659 // Process the color table | |
660 uint32_t colorBytes = 0; | |
661 SkColor* colorTable = NULL; | |
scroggo
2015/03/06 18:56:13
SkPMColor. Same down below.
| |
662 if (bitsPerPixel < 16) { | |
663 // Verify the number of colors for the color table | |
664 const int maxColors = 1 << bitsPerPixel; | |
665 // Zero is a default for maxColors | |
666 // Also set numColors to maxColors when input is too large | |
667 if (numColors <= 0 || numColors > maxColors) { | |
668 numColors = maxColors; | |
669 } | |
670 colorTable = SkNEW_ARRAY(SkColor, maxColors); | |
671 | |
672 // Construct the color table | |
673 colorBytes = numColors * bytesPerColor; | |
674 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes)); | |
675 if (stream->read(cBuffer.get(), colorBytes) != colorBytes) { | |
676 SkDebugf("Error: unable to read color table.\n"); | |
677 return NULL; | |
678 } | |
679 | |
680 // Fill in the color table | |
681 uint32_t i = 0; | |
682 for (; i < numColors; i++) { | |
683 uint8_t blue = get_byte(cBuffer.get(), i*bytesPerColor); | |
684 uint8_t green = get_byte(cBuffer.get(), i*bytesPerColor + 1); | |
685 uint8_t red = get_byte(cBuffer.get(), i*bytesPerColor + 2); | |
686 uint8_t alpha = 0xFF; | |
687 if (kOpaque_SkAlphaType != alphaType) { | |
688 alpha = (masks.alphaMask >> 24) & | |
689 get_byte(cBuffer.get(), i*bytesPerColor + 3); | |
690 } | |
691 colorTable[i] = SkColorSetARGBInline(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] = SkColorSetARGBInline(0xFF, 0, 0, 0); | |
699 } | |
700 } else { | |
701 // We will not use the color table if bitsPerPixel >= 16, but if there | |
702 // is a color table, we may need to skip the color table bytes. | |
703 // We will assume that the maximum color table size is the same as when | |
704 // there are 8 bits per pixel (the largest color table actually used). | |
705 // Color tables for greater than 8 bits per pixel are somewhat | |
706 // undocumented. It is indicated that they may exist to store a list | |
707 // of colors for optimization on devices with limited color display | |
708 // capacity. While we do not know for sure, we will guess that any | |
709 // value of numColors greater than this maximum is invalid. | |
710 if (numColors <= (1 << 8)) { | |
711 colorBytes = numColors * bytesPerColor; | |
712 if (stream->skip(colorBytes) != colorBytes) { | |
713 SkDebugf("Error: Could not skip color table bytes.\n"); | |
714 return NULL; | |
715 } | |
716 } | |
717 } | |
718 | |
719 // Ensure that the stream now points to the start of the pixel array | |
720 uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes + colorBytes; | |
721 | |
722 // Check that we have not read past the pixel array offset | |
723 if(bytesRead > offset) { | |
724 // This may occur on OS 2.1 and other old versions where the color | |
725 // table defaults to max size, and the bmp tries to use a smaller color | |
726 // table. This is invalid, and our decision is to indicate an error, | |
727 // rather than try to guess the intended size of the color table and | |
728 // rewind the stream to display the image. | |
729 SkDebugf("Error: pixel data offset less than header size.\n"); | |
730 return NULL; | |
731 } | |
732 | |
733 // Skip to the start of the pixel array | |
734 if (stream->skip(offset - bytesRead) != offset - bytesRead) { | |
735 SkDebugf("Error: unable to skip to image data.\n"); | |
736 return NULL; | |
737 } | |
738 | |
739 // Remaining bytes is only used for RLE | |
740 const int remainingBytes = totalBytes - offset; | |
741 if (remainingBytes <= 0 && kRLE_BitmapInputFormat == inputFormat) { | |
742 SkDebugf("Error: RLE requires valid input size.\n"); | |
743 return NULL; | |
744 } | |
745 | |
746 // Return the codec | |
747 // We will use ImageInfo to store width, height, and alpha type. The Skia | |
748 // color types do not match with the many possible bmp input color types, | |
749 // so we will ignore this field and depend on other parameters for input | |
750 // information. | |
751 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, | |
752 kUnknown_SkColorType, alphaType); | |
753 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, | |
754 inputFormat, masks, colorTable, rowOrder, | |
755 remainingBytes)); | |
756 } | |
757 | |
758 /* | |
759 * | |
760 * Creates an instance of the decoder | |
761 * Called only by NewFromStream | |
762 * | |
763 */ | |
764 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, | |
765 uint16_t bitsPerPixel, BitmapInputFormat inputFormat, | |
766 BitMasks masks, SkColor* colorTable, | |
767 RowOrder rowOrder, | |
768 const uint32_t remainingBytes) | |
769 : INHERITED(info, stream) | |
770 , fBitsPerPixel(bitsPerPixel) | |
771 , fInputFormat(inputFormat) | |
772 , fBitMasks(masks) | |
773 , fMaskShifts( { 0, 0, 0, 0 } ) | |
774 , fMaskSizes( { 0, 0, 0, 0 } ) | |
775 , fColorTable(colorTable) | |
776 , fRowOrder(rowOrder) | |
777 , fRemainingBytes(remainingBytes) | |
778 {} | |
779 | |
780 /* | |
781 * | |
782 * Initiates the bitmap decode | |
783 * | |
784 */ | |
785 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, | |
786 void* dst, size_t dstRowBytes, | |
787 SkColor*, int*) { | |
788 if (!this->couldRewindIfNeeded()) { | |
789 SkDebugf("Error: rewind should not be necessary.\n"); | |
scroggo
2015/03/06 18:56:13
This comment isn't necessary.
couldRewindIfNeeded
| |
790 return kCouldNotRewind; | |
791 } | |
792 if (dstInfo.dimensions() != this->getOriginalInfo().dimensions()) { | |
793 SkDebugf("Error: scaling not supported.\n"); | |
794 return kInvalidScale; | |
795 } | |
796 if (!conversion_possible(dstInfo, this->getOriginalInfo())) { | |
797 SkDebugf("Error: cannot convert input type to output type.\n"); | |
798 return kInvalidConversion; | |
799 } | |
800 | |
801 switch (fInputFormat) { | |
802 case kBitMask_BitmapInputFormat: | |
803 return decodeMask(dstInfo, dst, dstRowBytes); | |
804 case kRLE_BitmapInputFormat: | |
805 return decodeRLE(dstInfo, dst, dstRowBytes); | |
806 case kStandard_BitmapInputFormat: | |
807 return decode(dstInfo, dst, dstRowBytes); | |
808 default: | |
809 SkASSERT(false); | |
810 return kInvalidInput; | |
811 } | |
812 } | |
813 | |
814 /* | |
815 * | |
816 * For a continuous bit mask (ex: 0011100), retrieves the size of the mask and | |
817 * the number of bits to shift the mask | |
818 * | |
819 */ | |
820 void SkBmpCodec::processMasks() { | |
msarett
2015/03/05 23:13:17
I can make this function less repetitive (but hard
scroggo
2015/03/06 18:56:13
Hard to say... My initial thought was to let timin
| |
821 // Trim the masks to the allowed number of bits | |
822 if (fBitsPerPixel < 32) { | |
scroggo
2015/03/06 18:56:13
If you merged all the masks together, as suggested
| |
823 fBitMasks.redMask &= (1 << fBitsPerPixel) - 1; | |
824 fBitMasks.greenMask &= (1 << fBitsPerPixel) - 1; | |
825 fBitMasks.blueMask &= (1 << fBitsPerPixel) - 1; | |
826 fBitMasks.alphaMask &= (1 << fBitsPerPixel) - 1; | |
827 } | |
828 | |
829 // Get temporary versions of the inputs masks | |
830 uint32_t redMask = fBitMasks.redMask; | |
831 uint32_t greenMask = fBitMasks.greenMask; | |
832 uint32_t blueMask = fBitMasks.blueMask; | |
833 uint32_t alphaMask = fBitMasks.alphaMask; | |
834 | |
835 // Count trailing zeros on masks and the size of masks | |
836 if (redMask != 0) { | |
837 for (; (redMask & 1) == 0; redMask >>= 1) { | |
838 fMaskShifts.redShift++; | |
839 } | |
840 for (; redMask & 1; redMask >>= 1) { | |
841 fMaskSizes.redSize++; | |
842 } | |
843 // Truncate masks greater than 8 bits | |
844 if (fMaskSizes.redSize > 8) { | |
845 fMaskShifts.redShift += fMaskSizes.redSize - 8; | |
846 fMaskSizes.redSize = 8; | |
847 } | |
848 } | |
849 if (greenMask != 0) { | |
850 for (; (greenMask & 1) == 0; greenMask >>= 1) { | |
851 fMaskShifts.greenShift++; | |
852 } | |
853 for (; greenMask & 1; greenMask >>= 1) { | |
854 fMaskSizes.greenSize++; | |
855 } | |
856 // Truncate masks greater than 8 bits | |
857 if (fMaskSizes.greenSize > 8) { | |
858 fMaskShifts.greenShift += fMaskSizes.greenSize - 8; | |
859 fMaskSizes.greenSize = 8; | |
860 } | |
861 } | |
862 if (blueMask != 0) { | |
863 for (; (blueMask & 1) == 0; blueMask >>= 1) { | |
864 fMaskShifts.blueShift++; | |
865 } | |
866 for (; blueMask & 1; blueMask >>= 1) { | |
867 fMaskSizes.blueSize++; | |
868 } | |
869 // Truncate masks greater than 8 bits | |
870 if (fMaskSizes.blueSize > 8) { | |
871 fMaskShifts.blueShift += fMaskSizes.blueSize - 8; | |
872 fMaskSizes.blueSize = 8; | |
873 } | |
874 } | |
875 if (alphaMask != 0) { | |
876 for (; (alphaMask & 1) == 0; alphaMask >>= 1) { | |
877 fMaskShifts.alphaShift++; | |
878 } | |
879 for (; alphaMask & 1; alphaMask >>= 1) { | |
880 fMaskSizes.alphaSize++; | |
881 } | |
882 // Truncate masks greater than 8 bits | |
883 if (fMaskSizes.alphaSize > 8) { | |
884 fMaskShifts.alphaShift += fMaskSizes.alphaSize - 8; | |
885 fMaskSizes.alphaSize = 8; | |
886 } | |
887 } | |
888 return; | |
scroggo
2015/03/06 18:56:13
not needed.
| |
889 } | |
890 | |
891 /* | |
892 * | |
893 * Performs the bitmap decoding for bit masks input format | |
894 * | |
895 */ | |
896 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo, | |
897 void* dst, uint32_t dstRowBytes) { | |
898 // Set constant values | |
899 const int width = dstInfo.width(); | |
900 const int height = dstInfo.height(); | |
901 const uint32_t pixelsPerByte = 8 / fBitsPerPixel; | |
902 const uint32_t bytesPerPixel = fBitsPerPixel / 8; | |
scroggo
2015/03/06 18:56:13
what happens if fBitsPerPixel is not an even multi
msarett
2015/03/07 00:19:50
It would an error if it happened. We should proba
| |
903 const uint32_t unpaddedRowBytes = fBitsPerPixel < 16 ? | |
scroggo
2015/03/06 18:56:13
I think all you want here is the paddedRowBytes? A
| |
904 (width + pixelsPerByte - 1) / pixelsPerByte : width * bytesPerPixel; | |
905 const uint32_t paddedRowBytes = SkAlign4(unpaddedRowBytes); | |
906 const uint32_t alphaMask = fBitMasks.alphaMask; | |
907 | |
908 // Allocate space for a row buffer and a source for the swizzler | |
909 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, paddedRowBytes)); | |
910 | |
911 // Define the type of mask row procedures | |
912 typedef SkSwizzler::ResultAlpha (*RowProc)(void* SK_RESTRICT dstRow, | |
913 const uint8_t* SK_RESTRICT src, int width, | |
914 BitMasks masks, BitMaskShifts shifts, | |
915 BitMaskSizes sizes); | |
916 | |
917 // Choose the appropriate row procedure | |
918 RowProc proc = NULL; | |
919 switch (fBitsPerPixel) { | |
920 case 16: | |
921 if (alphaMask == 0) { | |
922 proc = &swizzle_mask16_to_n32; | |
923 } else { | |
924 proc = &swizzle_mask16_alpha_to_n32; | |
925 } | |
926 break; | |
927 case 24: | |
928 if (alphaMask == 0) { | |
929 proc = &swizzle_mask24_to_n32; | |
930 } else { | |
931 proc = &swizzle_mask24_alpha_to_n32; | |
932 } | |
933 break; | |
934 case 32: | |
935 if (alphaMask == 0) { | |
936 proc = &swizzle_mask32_to_n32; | |
937 } else { | |
938 proc = &swizzle_mask32_alpha_to_n32; | |
939 } | |
940 break; | |
941 default: | |
942 SkASSERT(false); | |
943 return kInvalidInput; | |
944 } | |
945 | |
946 // Obtain the size and location of the input bit masks | |
947 processMasks(); | |
948 | |
949 // Get the destination start row and delta | |
950 SkColor* dstRow; | |
951 int32_t delta; | |
952 if (kTopDown_RowOrder == fRowOrder) { | |
953 dstRow = (SkColor*) dst; | |
954 delta = dstRowBytes; | |
955 } else { | |
956 dstRow = (SkColor*) SkTAddOffset<void>(dst, (height - 1) * dstRowBytes); | |
957 delta = -dstRowBytes; | |
958 } | |
959 | |
960 // Iterate over rows of the image | |
961 bool transparent = true; | |
962 for (uint32_t y = 0; y < height; y++) { | |
963 // Read a row of the input | |
964 if (stream()->read(srcBuffer.get(), paddedRowBytes) != paddedRowBytes) { | |
965 SkDebugf("Warning: incomplete input stream.\n"); | |
966 return kIncompleteInput; | |
967 } | |
968 | |
969 // Decode the row in destination format | |
970 SkSwizzler::ResultAlpha r = proc(dstRow, srcBuffer.get(), width, | |
971 fBitMasks, fMaskShifts, fMaskSizes); | |
972 transparent &= SkSwizzler::kTransparent_ResultAlpha == r; | |
scroggo
2015/03/06 18:56:13
nit: parens around the == check
| |
973 | |
974 // Move to the next row | |
975 dstRow = SkTAddOffset<SkColor>(dstRow, delta); | |
976 } | |
977 | |
978 // Many fully transparent bmp images are intended to be opaque. Here, we | |
979 // correct for this possibility. | |
980 SkColor* dstPtr = (SkColor*) dst; | |
981 if (transparent) { | |
982 for (uint32_t y = 0; y < height; y++) { | |
983 for (uint32_t x = 0; x < width; x++) { | |
984 dstPtr[y * dstRowBytes + x] |= 0xFF000000; | |
985 } | |
986 } | |
987 } | |
988 | |
989 // Finished decoding the entire image | |
990 return kSuccess; | |
991 } | |
992 | |
993 /* | |
994 * | |
995 * Set an RLE pixel using the color table | |
996 * | |
997 */ | |
998 void SkBmpCodec::setRLEPixel(SkColor* dst, uint32_t dstRowBytes, int height, | |
999 uint32_t x, uint32_t y, uint8_t index) { | |
1000 if (kBottomUp_RowOrder == fRowOrder) { | |
1001 y = height - y - 1; | |
1002 } | |
1003 SkColor* dstRow = SkTAddOffset<SkColor>(dst, y * dstRowBytes); | |
1004 dstRow[x] = fColorTable.get()[index]; | |
1005 } | |
1006 | |
1007 /* | |
1008 * | |
1009 * Performs the bitmap decoding for RLE input format | |
1010 * RLE decoding is performed all at once, rather than a one row at a time | |
1011 * | |
1012 */ | |
1013 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo, | |
1014 void* dst, uint32_t dstRowBytes) { | |
1015 // Set RLE flags | |
1016 static const uint8_t RLE_ESCAPE = 0; | |
1017 static const uint8_t RLE_EOL = 0; | |
1018 static const uint8_t RLE_EOF = 1; | |
1019 static const uint8_t RLE_DELTA = 2; | |
1020 | |
1021 // Set constant values | |
1022 const int width = dstInfo.width(); | |
1023 const int height = dstInfo.height(); | |
1024 const uint32_t pixelsPerByte = 8 / fBitsPerPixel; | |
1025 const uint32_t bytesPerPixel = fBitsPerPixel / 8; | |
1026 | |
1027 // Input buffer parameters | |
1028 uint32_t currByte = 0; | |
1029 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRemainingBytes)); | |
1030 uint32_t totalBytes = stream()->read(buffer.get(), fRemainingBytes); | |
1031 if (totalBytes < fRemainingBytes) { | |
1032 SkDebugf("Warning: incomplete RLE file.\n"); | |
1033 } else if (totalBytes <= 0) { | |
1034 SkDebugf("Error: could not read RLE image data.\n"); | |
1035 return kInvalidInput; | |
1036 } | |
1037 | |
1038 // Destination parameters | |
1039 uint32_t x = 0; | |
1040 uint32_t y = 0; | |
1041 // If the code skips pixels, remaining pixels are transparent or black | |
1042 // TODO: Skip this if memory was already zeroed. | |
1043 memset(dst, 0, dstRowBytes * height); | |
1044 SkColor* dstPtr = (SkColor*) dst; | |
1045 | |
1046 while (true) { | |
1047 // Every entry takes at least two bytes | |
1048 if (totalBytes - currByte < 2) { | |
1049 SkDebugf("Warning: incomplete RLE input.\n"); | |
1050 return kIncompleteInput; | |
1051 } | |
1052 | |
1053 // Read the next two bytes. These bytes have different meanings | |
scroggo
2015/03/06 18:56:13
Thanks for the comments! It makes this code a lot
| |
1054 // depending on their values. In the first interpretation, the first | |
1055 // byte is an escape flag and the second byte indicates what special | |
1056 // task to perform. | |
1057 const uint8_t flag = buffer.get()[currByte++]; | |
1058 const uint8_t task = buffer.get()[currByte++]; | |
1059 | |
1060 // If we have reached a row that is beyond the image size, and the RLE | |
1061 // code does not indicate end of file, abort and signal a warning. | |
1062 if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) { | |
1063 SkDebugf("Warning: invalid RLE input.\n"); | |
1064 return kIncompleteInput; | |
1065 } | |
1066 | |
1067 // Perform decoding | |
1068 if (RLE_ESCAPE == flag) { | |
1069 switch (task) { | |
1070 case RLE_EOL: | |
1071 x = 0; | |
1072 y++; | |
1073 break; | |
1074 case RLE_EOF: | |
1075 return kSuccess; | |
1076 case RLE_DELTA: { | |
1077 // Two bytes are needed to specify delta | |
1078 if (totalBytes - currByte < 2) { | |
1079 SkDebugf("Warning: incomplete RLE input\n"); | |
1080 return kIncompleteInput; | |
1081 } | |
1082 // Modify x and y | |
1083 const uint8_t dx = buffer.get()[currByte++]; | |
1084 const uint8_t dy = buffer.get()[currByte++]; | |
1085 x += dx; | |
1086 y += dy; | |
1087 if (x > width || y > height) { | |
1088 SkDebugf("Warning: invalid RLE input.\n"); | |
1089 return kIncompleteInput; | |
1090 } | |
1091 break; | |
1092 } | |
1093 default: { | |
1094 // If task does not match any of the above signals, it | |
1095 // indicates that we have a sequence of non-RLE pixels. | |
1096 // Furthermore, the value of task is equal to the number | |
1097 // of pixels to interpret. | |
1098 uint8_t numPixels = task; | |
1099 const uint32_t unpaddedBytes = fBitsPerPixel < 16 ? | |
1100 (numPixels + pixelsPerByte - 1) / pixelsPerByte : | |
1101 numPixels * bytesPerPixel; | |
1102 const uint32_t paddedBytes = SkAlign2(unpaddedBytes); | |
1103 if (x + numPixels > width || | |
1104 totalBytes - currByte < paddedBytes) { | |
1105 SkDebugf("Warning: invalid RLE input.\n"); | |
1106 return kIncompleteInput; | |
1107 } | |
1108 // Set count number of pixels | |
1109 while (numPixels > 0) { | |
1110 switch(fBitsPerPixel) { | |
1111 case 4: { | |
1112 uint8_t val = buffer.get()[currByte++]; | |
1113 setRLEPixel(dstPtr, dstRowBytes, height, x++, y, | |
1114 val >> 4); | |
1115 numPixels--; | |
1116 if (numPixels != 0) { | |
1117 setRLEPixel(dstPtr, dstRowBytes, height, | |
1118 x++, y, val & 0xF); | |
1119 numPixels--; | |
1120 } | |
1121 break; | |
1122 } | |
1123 case 8: | |
1124 setRLEPixel(dstPtr, dstRowBytes, height, x++, y, | |
1125 buffer.get()[currByte++]); | |
1126 numPixels--; | |
1127 break; | |
1128 case 24: { | |
1129 uint8_t blue = buffer.get()[currByte++]; | |
1130 uint8_t green = buffer.get()[currByte++]; | |
1131 uint8_t red = buffer.get()[currByte++]; | |
1132 SkColor color = SkColorSetARGBInline( | |
1133 0xFF, red, green, blue); | |
1134 SkColor* dstRow = SkTAddOffset<SkColor>( | |
1135 dstPtr, y * dstRowBytes); | |
1136 dstRow[x++] = color; | |
1137 numPixels--; | |
1138 } | |
1139 default: | |
1140 SkASSERT(false); | |
1141 return kInvalidInput; | |
1142 } | |
1143 } | |
1144 // Skip a byte if necessary to maintain alignment | |
1145 if (unpaddedBytes & 1) { | |
1146 currByte++; | |
1147 } | |
1148 break; | |
1149 } | |
1150 } | |
1151 } else { | |
1152 // If the first byte read is not a flag, it indicates the number of | |
1153 // pixels to set in RLE mode. | |
1154 const uint8_t numPixels = flag; | |
1155 const uint32_t endX = SkTMin<uint32_t>(x + numPixels, | |
1156 (uint32_t) width); | |
1157 | |
1158 if (24 == fBitsPerPixel) { | |
1159 // In RLE24, the second byte read is part of the pixel color. | |
1160 // There are two more required bytes to finish encoding the | |
1161 // color. | |
1162 if (totalBytes - currByte < 2) { | |
1163 SkDebugf("Warning: incomplete RLE input\n"); | |
1164 return kIncompleteInput; | |
1165 } | |
1166 | |
1167 // Fill the pixels up to endX with the specified color | |
1168 uint8_t blue = task; | |
1169 uint8_t green = buffer.get()[currByte++]; | |
1170 uint8_t red = buffer.get()[currByte++]; | |
1171 SkColor color = SkColorSetARGBInline(0xFF, red, green, blue); | |
1172 SkColor* dstRow = | |
1173 SkTAddOffset<SkColor>(dstPtr, y * dstRowBytes); | |
1174 while (x < endX) { | |
1175 dstRow[x++] = color; | |
1176 } | |
1177 } else { | |
1178 // In RLE8 or RLE4, the second byte read gives the index in the | |
1179 // color table to look up the pixel color. | |
1180 // RLE8 has one color index that gets repeated | |
1181 // RLE4 has two color indexes in the upper and lower 4 bits of | |
1182 // the bytes, which are alternated | |
1183 uint8_t indices[2] = { task, task }; | |
1184 if (4 == fBitsPerPixel) { | |
1185 indices[0] >>= 4; | |
1186 indices[1] &= 0xf; | |
1187 } | |
1188 | |
1189 // Set the indicated number of pixels | |
1190 for (int which = 0; x < endX; x++) { | |
1191 setRLEPixel(dstPtr, dstRowBytes, height, x, y, | |
1192 indices[which]); | |
1193 which = !which; | |
1194 } | |
1195 } | |
1196 } | |
1197 } | |
1198 } | |
1199 | |
1200 /* | |
1201 * | |
1202 * Performs the bitmap decoding for standard input format | |
1203 * | |
1204 */ | |
1205 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, | |
1206 void* dst, uint32_t dstRowBytes) { | |
1207 // Set constant values | |
1208 const int width = dstInfo.width(); | |
1209 const int height = dstInfo.height(); | |
1210 const uint32_t pixelsPerByte = 8 / fBitsPerPixel; | |
1211 const uint32_t bytesPerPixel = fBitsPerPixel / 8; | |
1212 const uint32_t unpaddedRowBytes = fBitsPerPixel < 16 ? | |
1213 (width + pixelsPerByte - 1) / pixelsPerByte : width * bytesPerPixel; | |
1214 const uint32_t paddedRowBytes = SkAlign4(unpaddedRowBytes); | |
1215 const uint32_t alphaMask = fBitMasks.alphaMask; | |
1216 | |
1217 // Get the destination start row and delta | |
1218 SkColor* dstRow; | |
1219 int32_t delta; | |
1220 if (kTopDown_RowOrder == fRowOrder) { | |
1221 dstRow = (SkColor*) dst; | |
1222 delta = dstRowBytes; | |
1223 } else { | |
1224 dstRow = (SkColor*) SkTAddOffset<void>(dst, (height - 1) * dstRowBytes); | |
1225 delta = -dstRowBytes; | |
1226 } | |
1227 | |
1228 // Get swizzler configuration | |
1229 SkSwizzler::SrcConfig config; | |
1230 switch (fBitsPerPixel) { | |
1231 case 1: | |
1232 config = SkSwizzler::kIndex1; | |
1233 break; | |
1234 case 2: | |
1235 config = SkSwizzler::kIndex2; | |
1236 break; | |
1237 case 4: | |
1238 config = SkSwizzler::kIndex4; | |
1239 break; | |
1240 case 8: | |
1241 config = SkSwizzler::kIndex; | |
1242 break; | |
1243 case 24: | |
1244 config = SkSwizzler::kBGR; | |
1245 break; | |
1246 case 32: | |
1247 if (alphaMask == 0) { | |
1248 config = SkSwizzler::kBGRX; | |
1249 } else { | |
1250 config = SkSwizzler::kBGRA; | |
1251 } | |
1252 break; | |
1253 default: | |
1254 SkASSERT(false); | |
1255 return kInvalidInput; | |
1256 } | |
1257 | |
1258 // Create swizzler | |
1259 SkSwizzler* swizzler = SkSwizzler::CreateSwizzler(config, fColorTable.get(), | |
1260 dstInfo, dstRow, dstRowBytes, false); | |
1261 | |
1262 // Allocate space for a row buffer and a source for the swizzler | |
1263 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, paddedRowBytes)); | |
1264 | |
1265 // Iterate over rows of the image | |
1266 bool transparent = true; | |
1267 for (uint32_t y = 0; y < height; y++) { | |
1268 // Read a row of the input | |
1269 if (stream()->read(srcBuffer.get(), paddedRowBytes) != paddedRowBytes) { | |
1270 SkDebugf("Warning: incomplete input stream.\n"); | |
1271 return kIncompleteInput; | |
1272 } | |
1273 | |
1274 // Decode the row in destination format | |
1275 SkSwizzler::ResultAlpha r = swizzler->next(srcBuffer.get(), delta); | |
1276 transparent &= SkSwizzler::kTransparent_ResultAlpha == r; | |
1277 } | |
1278 | |
1279 // Now we adjust the output image with some additional behavior that | |
1280 // SkSwizzler does not support. Firstly, all bmp images that contain | |
1281 // alpha are masked by the alpha mask. Secondly, many fully transparent | |
1282 // bmp images are intended to be opaque. Here, we make those corrections. | |
1283 SkColor* dstPtr = (SkColor*) dst; | |
1284 if (alphaMask != 0) { | |
1285 for (uint32_t y = 0; y < height; y++) { | |
1286 for (uint32_t x = 0; x < width; x++) { | |
1287 if (transparent) { | |
1288 dstPtr[y * dstRowBytes + x] |= 0xFF000000; | |
1289 } else { | |
1290 dstPtr[y * dstRowBytes + x] &= alphaMask; | |
1291 } | |
1292 } | |
1293 } | |
1294 } | |
1295 | |
1296 // Finished decoding the entire image | |
1297 return kSuccess; | |
1298 } | |
OLD | NEW |