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

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

Issue 1258863008: Split SkBmpCodec into three separate classes (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: SkBmpCodec is a parent class of the bmp codecs 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
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkBmpCodec.h" 8 #include "SkBmpCodec.h"
9 #include "SkBmpMaskCodec.h"
10 #include "SkBmpRLECodec.h"
11 #include "SkBmpStandardCodec.h"
9 #include "SkCodecPriv.h" 12 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 13 #include "SkColorPriv.h"
11 #include "SkStream.h" 14 #include "SkStream.h"
12 15
13 /* 16 /*
14 * 17 *
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 18 * Defines the version and type of the second bitmap header
61 * 19 *
62 */ 20 */
63 enum BitmapHeaderType { 21 enum BmpHeaderType {
64 kInfoV1_BitmapHeaderType, 22 kInfoV1_BmpHeaderType,
65 kInfoV2_BitmapHeaderType, 23 kInfoV2_BmpHeaderType,
66 kInfoV3_BitmapHeaderType, 24 kInfoV3_BmpHeaderType,
67 kInfoV4_BitmapHeaderType, 25 kInfoV4_BmpHeaderType,
68 kInfoV5_BitmapHeaderType, 26 kInfoV5_BmpHeaderType,
69 kOS2V1_BitmapHeaderType, 27 kOS2V1_BmpHeaderType,
70 kOS2VX_BitmapHeaderType, 28 kOS2VX_BmpHeaderType,
71 kUnknown_BitmapHeaderType 29 kUnknown_BmpHeaderType
72 }; 30 };
73 31
74 /* 32 /*
75 * 33 *
76 * Possible bitmap compression types 34 * Possible bitmap compression types
77 * 35 *
78 */ 36 */
79 enum BitmapCompressionMethod { 37 enum BmpCompressionMethod {
80 kNone_BitmapCompressionMethod = 0, 38 kNone_BmpCompressionMethod = 0,
81 k8BitRLE_BitmapCompressionMethod = 1, 39 k8BitRLE_BmpCompressionMethod = 1,
82 k4BitRLE_BitmapCompressionMethod = 2, 40 k4BitRLE_BmpCompressionMethod = 2,
83 kBitMasks_BitmapCompressionMethod = 3, 41 kBitMasks_BmpCompressionMethod = 3,
84 kJpeg_BitmapCompressionMethod = 4, 42 kJpeg_BmpCompressionMethod = 4,
85 kPng_BitmapCompressionMethod = 5, 43 kPng_BmpCompressionMethod = 5,
86 kAlphaBitMasks_BitmapCompressionMethod = 6, 44 kAlphaBitMasks_BmpCompressionMethod = 6,
87 kCMYK_BitmapCompressionMethod = 11, 45 kCMYK_BmpCompressionMethod = 11,
88 kCMYK8BitRLE_BitmapCompressionMethod = 12, 46 kCMYK8BitRLE_BmpCompressionMethod = 12,
89 kCMYK4BitRLE_BitmapCompressionMethod = 13 47 kCMYK4BitRLE_BmpCompressionMethod = 13
90 }; 48 };
91 49
92 /* 50 /*
93 * 51 *
94 * Checks the start of the stream to see if the image is a bitmap 52 * Checks the start of the stream to see if the image is a bitmap
95 * 53 *
96 */ 54 */
97 bool SkBmpCodec::IsBmp(SkStream* stream) { 55 bool SkBmpCodec::IsBmp(SkStream* stream) {
98 // TODO: Support "IC", "PT", "CI", "CP", "BA" 56 // TODO: Support "IC", "PT", "CI", "CP", "BA"
99 const char bmpSig[] = { 'B', 'M' }; 57 const char bmpSig[] = { 'B', 'M' };
100 char buffer[sizeof(bmpSig)]; 58 char buffer[sizeof(bmpSig)];
101 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) && 59 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) &&
102 !memcmp(buffer, bmpSig, sizeof(bmpSig)); 60 !memcmp(buffer, bmpSig, sizeof(bmpSig));
103 } 61 }
104 62
105 /* 63 /*
106 *
107 * Assumes IsBmp was called and returned true 64 * Assumes IsBmp was called and returned true
108 * Creates a bmp decoder 65 * Creates a bmp decoder
109 * Reads enough of the stream to determine the image format 66 * Reads enough of the stream to determine the image format
110 *
111 */ 67 */
112 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) { 68 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
113 return SkBmpCodec::NewFromStream(stream, false); 69 return SkBmpCodec::NewFromStream(stream, false);
114 } 70 }
115 71
116 /* 72 /*
117 *
118 * Creates a bmp decoder for a bmp embedded in ico 73 * Creates a bmp decoder for a bmp embedded in ico
119 * Reads enough of the stream to determine the image format 74 * Reads enough of the stream to determine the image format
120 *
121 */ 75 */
122 SkCodec* SkBmpCodec::NewFromIco(SkStream* stream) { 76 SkCodec* SkBmpCodec::NewFromIco(SkStream* stream) {
123 return SkBmpCodec::NewFromStream(stream, true); 77 return SkBmpCodec::NewFromStream(stream, true);
124 } 78 }
125 79
126 /* 80 /*
127 *
128 * Read enough of the stream to initialize the SkBmpCodec. Returns a bool 81 * Read enough of the stream to initialize the SkBmpCodec. Returns a bool
129 * representing success or failure. If it returned true, and codecOut was 82 * representing success or failure. If it returned true, and codecOut was
130 * not NULL, it will be set to a new SkBmpCodec. 83 * not NULL, it will be set to a new SkBmpCodec.
131 * Does *not* take ownership of the passed in SkStream. 84 * Does *not* take ownership of the passed in SkStream.
132 *
133 */ 85 */
134 bool SkBmpCodec::ReadHeader(SkStream* stream, bool isIco, SkCodec** codecOut) { 86 bool SkBmpCodec::ReadHeader(SkStream* stream, bool isIco, SkCodec** codecOut) {
135 // Header size constants 87 // Header size constants
136 static const uint32_t kBmpHeaderBytes = 14; 88 static const uint32_t kBmpHeaderBytes = 14;
137 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4; 89 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
138 static const uint32_t kBmpOS2V1Bytes = 12; 90 static const uint32_t kBmpOS2V1Bytes = 12;
139 static const uint32_t kBmpOS2V2Bytes = 64; 91 static const uint32_t kBmpOS2V2Bytes = 64;
140 static const uint32_t kBmpInfoBaseBytes = 16; 92 static const uint32_t kBmpInfoBaseBytes = 16;
141 static const uint32_t kBmpInfoV1Bytes = 40; 93 static const uint32_t kBmpInfoV1Bytes = 40;
142 static const uint32_t kBmpInfoV2Bytes = 52; 94 static const uint32_t kBmpInfoV2Bytes = 52;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 SkNEW_ARRAY(uint8_t, infoBytesRemaining)); 165 SkNEW_ARRAY(uint8_t, infoBytesRemaining));
214 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) { 166 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
215 SkCodecPrintf("Error: unable to read second bitmap header.\n"); 167 SkCodecPrintf("Error: unable to read second bitmap header.\n");
216 return false; 168 return false;
217 } 169 }
218 170
219 // The number of bits used per pixel in the pixel data 171 // The number of bits used per pixel in the pixel data
220 uint16_t bitsPerPixel; 172 uint16_t bitsPerPixel;
221 173
222 // The compression method for the pixel data 174 // The compression method for the pixel data
223 uint32_t compression = kNone_BitmapCompressionMethod; 175 uint32_t compression = kNone_BmpCompressionMethod;
224 176
225 // Number of colors in the color table, defaults to 0 or max (see below) 177 // Number of colors in the color table, defaults to 0 or max (see below)
226 uint32_t numColors = 0; 178 uint32_t numColors = 0;
227 179
228 // Bytes per color in the color table, early versions use 3, most use 4 180 // Bytes per color in the color table, early versions use 3, most use 4
229 uint32_t bytesPerColor; 181 uint32_t bytesPerColor;
230 182
231 // The image width and height 183 // The image width and height
232 int width, height; 184 int width, height;
233 185
234 // Determine image information depending on second header format 186 // Determine image information depending on second header format
235 BitmapHeaderType headerType; 187 BmpHeaderType headerType;
236 if (infoBytes >= kBmpInfoBaseBytes) { 188 if (infoBytes >= kBmpInfoBaseBytes) {
237 // Check the version of the header 189 // Check the version of the header
238 switch (infoBytes) { 190 switch (infoBytes) {
239 case kBmpInfoV1Bytes: 191 case kBmpInfoV1Bytes:
240 headerType = kInfoV1_BitmapHeaderType; 192 headerType = kInfoV1_BmpHeaderType;
241 break; 193 break;
242 case kBmpInfoV2Bytes: 194 case kBmpInfoV2Bytes:
243 headerType = kInfoV2_BitmapHeaderType; 195 headerType = kInfoV2_BmpHeaderType;
244 break; 196 break;
245 case kBmpInfoV3Bytes: 197 case kBmpInfoV3Bytes:
246 headerType = kInfoV3_BitmapHeaderType; 198 headerType = kInfoV3_BmpHeaderType;
247 break; 199 break;
248 case kBmpInfoV4Bytes: 200 case kBmpInfoV4Bytes:
249 headerType = kInfoV4_BitmapHeaderType; 201 headerType = kInfoV4_BmpHeaderType;
250 break; 202 break;
251 case kBmpInfoV5Bytes: 203 case kBmpInfoV5Bytes:
252 headerType = kInfoV5_BitmapHeaderType; 204 headerType = kInfoV5_BmpHeaderType;
253 break; 205 break;
254 case 16: 206 case 16:
255 case 20: 207 case 20:
256 case 24: 208 case 24:
257 case 28: 209 case 28:
258 case 32: 210 case 32:
259 case 36: 211 case 36:
260 case 42: 212 case 42:
261 case 46: 213 case 46:
262 case 48: 214 case 48:
263 case 60: 215 case 60:
264 case kBmpOS2V2Bytes: 216 case kBmpOS2V2Bytes:
265 headerType = kOS2VX_BitmapHeaderType; 217 headerType = kOS2VX_BmpHeaderType;
266 break; 218 break;
267 default: 219 default:
268 // We do not signal an error here because there is the 220 // We do not signal an error here because there is the
269 // possibility of new or undocumented bmp header types. Most 221 // possibility of new or undocumented bmp header types. Most
270 // of the newer versions of bmp headers are similar to and 222 // 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 223 // build off of the older versions, so we may still be able to
272 // decode the bmp. 224 // decode the bmp.
273 SkCodecPrintf("Warning: unknown bmp header format.\n"); 225 SkCodecPrintf("Warning: unknown bmp header format.\n");
274 headerType = kUnknown_BitmapHeaderType; 226 headerType = kUnknown_BmpHeaderType;
275 break; 227 break;
276 } 228 }
277 // We check the size of the header before entering the if statement. 229 // 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 230 // We should not reach this point unless the size is large enough for
279 // these required fields. 231 // these required fields.
280 SkASSERT(infoBytesRemaining >= 12); 232 SkASSERT(infoBytesRemaining >= 12);
281 width = get_int(iBuffer.get(), 0); 233 width = get_int(iBuffer.get(), 0);
282 height = get_int(iBuffer.get(), 4); 234 height = get_int(iBuffer.get(), 4);
283 bitsPerPixel = get_short(iBuffer.get(), 10); 235 bitsPerPixel = get_short(iBuffer.get(), 10);
284 236
285 // Some versions do not have these fields, so we check before 237 // Some versions do not have these fields, so we check before
286 // overwriting the default value. 238 // overwriting the default value.
287 if (infoBytesRemaining >= 16) { 239 if (infoBytesRemaining >= 16) {
288 compression = get_int(iBuffer.get(), 12); 240 compression = get_int(iBuffer.get(), 12);
289 if (infoBytesRemaining >= 32) { 241 if (infoBytesRemaining >= 32) {
290 numColors = get_int(iBuffer.get(), 28); 242 numColors = get_int(iBuffer.get(), 28);
291 } 243 }
292 } 244 }
293 245
294 // All of the headers that reach this point, store color table entries 246 // All of the headers that reach this point, store color table entries
295 // using 4 bytes per pixel. 247 // using 4 bytes per pixel.
296 bytesPerColor = 4; 248 bytesPerColor = 4;
297 } else if (infoBytes >= kBmpOS2V1Bytes) { 249 } else if (infoBytes >= kBmpOS2V1Bytes) {
298 // The OS2V1 is treated separately because it has a unique format 250 // The OS2V1 is treated separately because it has a unique format
299 headerType = kOS2V1_BitmapHeaderType; 251 headerType = kOS2V1_BmpHeaderType;
300 width = (int) get_short(iBuffer.get(), 0); 252 width = (int) get_short(iBuffer.get(), 0);
301 height = (int) get_short(iBuffer.get(), 2); 253 height = (int) get_short(iBuffer.get(), 2);
302 bitsPerPixel = get_short(iBuffer.get(), 6); 254 bitsPerPixel = get_short(iBuffer.get(), 6);
303 bytesPerColor = 3; 255 bytesPerColor = 3;
304 } else { 256 } else {
305 // There are no valid bmp headers 257 // There are no valid bmp headers
306 SkCodecPrintf("Error: second bitmap header size is invalid.\n"); 258 SkCodecPrintf("Error: second bitmap header size is invalid.\n");
307 return false; 259 return false;
308 } 260 }
309 261
(...skipping 14 matching lines...) Expand all
324 SkCodecPrintf("Error: invalid bitmap dimensions.\n"); 276 SkCodecPrintf("Error: invalid bitmap dimensions.\n");
325 return false; 277 return false;
326 } 278 }
327 279
328 // Create mask struct 280 // Create mask struct
329 SkMasks::InputMasks inputMasks; 281 SkMasks::InputMasks inputMasks;
330 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks)); 282 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
331 283
332 // Determine the input compression format and set bit masks if necessary 284 // Determine the input compression format and set bit masks if necessary
333 uint32_t maskBytes = 0; 285 uint32_t maskBytes = 0;
334 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat; 286 BmpInputFormat inputFormat = kUnknown_BmpInputFormat;
335 switch (compression) { 287 switch (compression) {
336 case kNone_BitmapCompressionMethod: 288 case kNone_BmpCompressionMethod:
337 inputFormat = kStandard_BitmapInputFormat; 289 inputFormat = kStandard_BmpInputFormat;
338 break; 290 break;
339 case k8BitRLE_BitmapCompressionMethod: 291 case k8BitRLE_BmpCompressionMethod:
340 if (bitsPerPixel != 8) { 292 if (bitsPerPixel != 8) {
341 SkCodecPrintf("Warning: correcting invalid bitmap format.\n"); 293 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
342 bitsPerPixel = 8; 294 bitsPerPixel = 8;
343 } 295 }
344 inputFormat = kRLE_BitmapInputFormat; 296 inputFormat = kRLE_BmpInputFormat;
345 break; 297 break;
346 case k4BitRLE_BitmapCompressionMethod: 298 case k4BitRLE_BmpCompressionMethod:
347 if (bitsPerPixel != 4) { 299 if (bitsPerPixel != 4) {
348 SkCodecPrintf("Warning: correcting invalid bitmap format.\n"); 300 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
349 bitsPerPixel = 4; 301 bitsPerPixel = 4;
350 } 302 }
351 inputFormat = kRLE_BitmapInputFormat; 303 inputFormat = kRLE_BmpInputFormat;
352 break; 304 break;
353 case kAlphaBitMasks_BitmapCompressionMethod: 305 case kAlphaBitMasks_BmpCompressionMethod:
354 case kBitMasks_BitmapCompressionMethod: 306 case kBitMasks_BmpCompressionMethod:
355 // Load the masks 307 // Load the masks
356 inputFormat = kBitMask_BitmapInputFormat; 308 inputFormat = kBitMask_BmpInputFormat;
357 switch (headerType) { 309 switch (headerType) {
358 case kInfoV1_BitmapHeaderType: { 310 case kInfoV1_BmpHeaderType: {
359 // The V1 header stores the bit masks after the header 311 // The V1 header stores the bit masks after the header
360 SkAutoTDeleteArray<uint8_t> mBuffer( 312 SkAutoTDeleteArray<uint8_t> mBuffer(
361 SkNEW_ARRAY(uint8_t, kBmpMaskBytes)); 313 SkNEW_ARRAY(uint8_t, kBmpMaskBytes));
362 if (stream->read(mBuffer.get(), kBmpMaskBytes) != 314 if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
363 kBmpMaskBytes) { 315 kBmpMaskBytes) {
364 SkCodecPrintf("Error: unable to read bit inputMasks.\n") ; 316 SkCodecPrintf("Error: unable to read bit inputMasks.\n") ;
365 return false; 317 return false;
366 } 318 }
367 maskBytes = kBmpMaskBytes; 319 maskBytes = kBmpMaskBytes;
368 inputMasks.red = get_int(mBuffer.get(), 0); 320 inputMasks.red = get_int(mBuffer.get(), 0);
369 inputMasks.green = get_int(mBuffer.get(), 4); 321 inputMasks.green = get_int(mBuffer.get(), 4);
370 inputMasks.blue = get_int(mBuffer.get(), 8); 322 inputMasks.blue = get_int(mBuffer.get(), 8);
371 break; 323 break;
372 } 324 }
373 case kInfoV2_BitmapHeaderType: 325 case kInfoV2_BmpHeaderType:
374 case kInfoV3_BitmapHeaderType: 326 case kInfoV3_BmpHeaderType:
375 case kInfoV4_BitmapHeaderType: 327 case kInfoV4_BmpHeaderType:
376 case kInfoV5_BitmapHeaderType: 328 case kInfoV5_BmpHeaderType:
377 // Header types are matched based on size. If the header 329 // Header types are matched based on size. If the header
378 // is V2+, we are guaranteed to be able to read at least 330 // is V2+, we are guaranteed to be able to read at least
379 // this size. 331 // this size.
380 SkASSERT(infoBytesRemaining >= 48); 332 SkASSERT(infoBytesRemaining >= 48);
381 inputMasks.red = get_int(iBuffer.get(), 36); 333 inputMasks.red = get_int(iBuffer.get(), 36);
382 inputMasks.green = get_int(iBuffer.get(), 40); 334 inputMasks.green = get_int(iBuffer.get(), 40);
383 inputMasks.blue = get_int(iBuffer.get(), 44); 335 inputMasks.blue = get_int(iBuffer.get(), 44);
384 break; 336 break;
385 case kOS2VX_BitmapHeaderType: 337 case kOS2VX_BmpHeaderType:
386 // TODO: Decide if we intend to support this. 338 // TODO: Decide if we intend to support this.
387 // It is unsupported in the previous version and 339 // It is unsupported in the previous version and
388 // in chromium. I have not come across a test case 340 // in chromium. I have not come across a test case
389 // that uses this format. 341 // that uses this format.
390 SkCodecPrintf("Error: huffman format unsupported.\n"); 342 SkCodecPrintf("Error: huffman format unsupported.\n");
391 return false; 343 return false;
392 default: 344 default:
393 SkCodecPrintf("Error: invalid bmp bit masks header.\n"); 345 SkCodecPrintf("Error: invalid bmp bit masks header.\n");
394 return false; 346 return false;
395 } 347 }
396 break; 348 break;
397 case kJpeg_BitmapCompressionMethod: 349 case kJpeg_BmpCompressionMethod:
398 if (24 == bitsPerPixel) { 350 if (24 == bitsPerPixel) {
399 inputFormat = kRLE_BitmapInputFormat; 351 inputFormat = kRLE_BmpInputFormat;
400 break; 352 break;
401 } 353 }
402 // Fall through 354 // Fall through
403 case kPng_BitmapCompressionMethod: 355 case kPng_BmpCompressionMethod:
404 // TODO: Decide if we intend to support this. 356 // TODO: Decide if we intend to support this.
405 // It is unsupported in the previous version and 357 // It is unsupported in the previous version and
406 // in chromium. I think it is used mostly for printers. 358 // in chromium. I think it is used mostly for printers.
407 SkCodecPrintf("Error: compression format not supported.\n"); 359 SkCodecPrintf("Error: compression format not supported.\n");
408 return false; 360 return false;
409 case kCMYK_BitmapCompressionMethod: 361 case kCMYK_BmpCompressionMethod:
410 case kCMYK8BitRLE_BitmapCompressionMethod: 362 case kCMYK8BitRLE_BmpCompressionMethod:
411 case kCMYK4BitRLE_BitmapCompressionMethod: 363 case kCMYK4BitRLE_BmpCompressionMethod:
412 // TODO: Same as above. 364 // TODO: Same as above.
413 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n"); 365 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n");
414 return false; 366 return false;
415 default: 367 default:
416 SkCodecPrintf("Error: invalid format for bitmap decoding.\n"); 368 SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
417 return false; 369 return false;
418 } 370 }
419 371
420 // Most versions of bmps should be rendered as opaque. Either they do 372 // 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 373 // 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 374 // 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 375 // 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 376 // 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 377 // 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 378 // V4+, we will use the alpha channel, and fix the image later if it turns
427 // out to be fully transparent. 379 // out to be fully transparent.
428 // As an exception, V3 bmp-in-ico may use an alpha mask. 380 // As an exception, V3 bmp-in-ico may use an alpha mask.
429 SkAlphaType alphaType = kOpaque_SkAlphaType; 381 SkAlphaType alphaType = kOpaque_SkAlphaType;
430 if ((kInfoV3_BitmapHeaderType == headerType && isIco) || 382 if ((kInfoV3_BmpHeaderType == headerType && isIco) ||
431 kInfoV4_BitmapHeaderType == headerType || 383 kInfoV4_BmpHeaderType == headerType ||
432 kInfoV5_BitmapHeaderType == headerType) { 384 kInfoV5_BmpHeaderType == headerType) {
433 // Header types are matched based on size. If the header is 385 // 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. 386 // V3+, we are guaranteed to be able to read at least this size.
435 SkASSERT(infoBytesRemaining > 52); 387 SkASSERT(infoBytesRemaining > 52);
436 inputMasks.alpha = get_int(iBuffer.get(), 48); 388 inputMasks.alpha = get_int(iBuffer.get(), 48);
437 if (inputMasks.alpha != 0) { 389 if (inputMasks.alpha != 0) {
438 alphaType = kUnpremul_SkAlphaType; 390 alphaType = kUnpremul_SkAlphaType;
439 } 391 }
440 } 392 }
441 iBuffer.free(); 393 iBuffer.free();
442 394
443 // Additionally, 32 bit bmp-in-icos use the alpha channel. 395 // Additionally, 32 bit bmp-in-icos use the alpha channel.
444 // And, RLE inputs may skip pixels, leaving them as transparent. This 396 // 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. 397 // is uncommon, but we cannot be certain that an RLE bmp will be opaque.
446 if ((isIco && 32 == bitsPerPixel) || (kRLE_BitmapInputFormat == inputFormat) ) { 398 if ((isIco && 32 == bitsPerPixel) || (kRLE_BmpInputFormat == inputFormat)) {
447 alphaType = kUnpremul_SkAlphaType; 399 alphaType = kUnpremul_SkAlphaType;
448 } 400 }
449 401
450 // Check for valid bits per pixel. 402 // Check for valid bits per pixel.
451 // At the same time, use this information to choose a suggested color type 403 // At the same time, use this information to choose a suggested color type
452 // and to set default masks. 404 // and to set default masks.
453 SkColorType colorType = kN32_SkColorType; 405 SkColorType colorType = kN32_SkColorType;
454 switch (bitsPerPixel) { 406 switch (bitsPerPixel) {
455 // In addition to more standard pixel compression formats, bmp supports 407 // In addition to more standard pixel compression formats, bmp supports
456 // the use of bit masks to determine pixel components. The standard 408 // the use of bit masks to determine pixel components. The standard
457 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB), 409 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
458 // which does not map well to any Skia color formats. For this reason, 410 // 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. 411 // we will always enable mask mode with 16 bits per pixel.
460 case 16: 412 case 16:
461 if (kBitMask_BitmapInputFormat != inputFormat) { 413 if (kBitMask_BmpInputFormat != inputFormat) {
462 inputMasks.red = 0x7C00; 414 inputMasks.red = 0x7C00;
463 inputMasks.green = 0x03E0; 415 inputMasks.green = 0x03E0;
464 inputMasks.blue = 0x001F; 416 inputMasks.blue = 0x001F;
465 inputFormat = kBitMask_BitmapInputFormat; 417 inputFormat = kBitMask_BmpInputFormat;
466 } 418 }
467 break; 419 break;
468 // We want to decode to kIndex_8 for input formats that are already 420 // We want to decode to kIndex_8 for input formats that are already
469 // designed in index format. 421 // designed in index format.
470 case 1: 422 case 1:
471 case 2: 423 case 2:
472 case 4: 424 case 4:
473 case 8: 425 case 8:
474 // However, we cannot in RLE format since we may need to leave some 426 // However, we cannot in RLE format since we may need to leave some
475 // pixels as transparent. Similarly, we also cannot for ICO images 427 // pixels as transparent. Similarly, we also cannot for ICO images
476 // since we may need to apply a transparent mask. 428 // since we may need to apply a transparent mask.
477 if (kRLE_BitmapInputFormat != inputFormat && !isIco) { 429 if (kRLE_BmpInputFormat != inputFormat && !isIco) {
478 colorType = kIndex_8_SkColorType; 430 colorType = kIndex_8_SkColorType;
479 } 431 }
480 case 24: 432 case 24:
481 case 32: 433 case 32:
482 break; 434 break;
483 default: 435 default:
484 SkCodecPrintf("Error: invalid input value for bits per pixel.\n"); 436 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
485 return false; 437 return false;
486 } 438 }
487 439
488 // Check that input bit masks are valid and create the masks object 440 // Check that input bit masks are valid and create the masks object
489 SkAutoTDelete<SkMasks> 441 SkAutoTDelete<SkMasks>
490 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel)); 442 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
491 if (NULL == masks) { 443 if (NULL == masks) {
492 SkCodecPrintf("Error: invalid input masks.\n"); 444 SkCodecPrintf("Error: invalid input masks.\n");
493 return false; 445 return false;
494 } 446 }
495 447
496 // Check for a valid number of total bytes when in RLE mode 448 // Check for a valid number of total bytes when in RLE mode
497 if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) { 449 if (totalBytes <= offset && kRLE_BmpInputFormat == inputFormat) {
498 SkCodecPrintf("Error: RLE requires valid input size.\n"); 450 SkCodecPrintf("Error: RLE requires valid input size.\n");
499 return false; 451 return false;
500 } 452 }
501 const size_t RLEBytes = totalBytes - offset; 453 const size_t RLEBytes = totalBytes - offset;
502 454
503 // Calculate the number of bytes read so far 455 // Calculate the number of bytes read so far
504 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; 456 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
505 if (!isIco && offset < bytesRead) { 457 if (!isIco && offset < bytesRead) {
506 SkCodecPrintf("Error: pixel data offset less than header size.\n"); 458 SkCodecPrintf("Error: pixel data offset less than header size.\n");
507 return false; 459 return false;
508 } 460 }
509 461
510 if (codecOut) { 462 if (codecOut) {
511 // Return the codec 463 // Set the image info
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, 464 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
515 colorType, alphaType); 465 colorType, alphaType);
516 *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, 466
517 inputFormat, masks.detach(), 467 // Return the codec
518 numColors, bytesPerColor, 468 switch (inputFormat) {
519 offset - bytesRead, rowOrder, 469 case kStandard_BmpInputFormat:
520 RLEBytes, isIco)); 470 *codecOut = SkNEW_ARGS(SkBmpStandardCodec, (imageInfo, stream,
471 bitsPerPixel, numColors, bytesPerColor,
472 offset - bytesRead, rowOrder, isIco));
473 return true;
474 case kBitMask_BmpInputFormat:
475 // Skip to the start of the pixel array.
476 // We can do this here because there is no color table to read
477 // in bit mask mode.
478 if (stream->skip(offset - bytesRead) != offset - bytesRead) {
479 SkCodecPrintf("Error: unable to skip to image data.\n");
480 return false;
481 }
482
483 *codecOut = SkNEW_ARGS(SkBmpMaskCodec, (imageInfo, stream,
484 bitsPerPixel, masks.detach(), rowOrder));
485 return true;
486 case kRLE_BmpInputFormat:
487 *codecOut = SkNEW_ARGS(SkBmpRLECodec, (
488 imageInfo, stream, bitsPerPixel, numColors,
489 bytesPerColor, offset - bytesRead, rowOrder, RLEBytes));
490 return true;
491 default:
492 SkASSERT(false);
493 return false;
494 }
521 } 495 }
522 return true;
523 } 496 }
524 497
525 /* 498 /*
526 *
527 * Creates a bmp decoder 499 * Creates a bmp decoder
528 * Reads enough of the stream to determine the image format 500 * Reads enough of the stream to determine the image format
529 *
530 */ 501 */
531 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) { 502 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) {
532 SkAutoTDelete<SkStream> streamDeleter(stream); 503 SkAutoTDelete<SkStream> streamDeleter(stream);
533 SkCodec* codec = NULL; 504 SkCodec* codec = NULL;
534 if (ReadHeader(stream, isIco, &codec)) { 505 if (ReadHeader(stream, isIco, &codec)) {
535 // codec has taken ownership of stream, so we do not need to 506 // codec has taken ownership of stream, so we do not need to
536 // delete it. 507 // delete it.
537 SkASSERT(codec); 508 SkASSERT(codec);
538 streamDeleter.detach(); 509 streamDeleter.detach();
539 return codec; 510 return codec;
540 } 511 }
541 return NULL; 512 return NULL;
542 } 513 }
543 514
544 /*
545 *
546 * Creates an instance of the decoder
547 * Called only by NewFromStream
548 *
549 */
550 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, 515 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
551 uint16_t bitsPerPixel, BitmapInputFormat inputFormat, 516 uint16_t bitsPerPixel, RowOrder rowOrder)
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) 517 : INHERITED(info, stream)
556 , fBitsPerPixel(bitsPerPixel) 518 , fBitsPerPixel(bitsPerPixel)
557 , fInputFormat(inputFormat)
558 , fMasks(masks)
559 , fColorTable(NULL)
560 , fNumColors(numColors)
561 , fBytesPerColor(bytesPerColor)
562 , fOffset(offset)
563 , fRowOrder(rowOrder) 519 , fRowOrder(rowOrder)
564 , fRLEBytes(RLEBytes)
565 , fIsIco(isIco)
566
567 {} 520 {}
568 521
569 /* 522 /*
570 * 523 * Correct an invalid bmp decode, where the encoded image is fully transparent,
571 * Initiates the bitmap decode 524 * but it is probably intended to be opaque.
572 *
573 */ 525 */
574 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, 526 SkCodec::Result SkBmpCodec::FixTransparentDecode(void* dst, size_t dstRowBytes,
575 void* dst, size_t dstRowBytes, 527 SkPMColor* colorPtr, int* colorCountPtr, SkStream* stream) {
576 const Options& opts, 528 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream));
577 SkPMColor* inputColorPtr, 529 return codec->getPixels(codec->getInfo().makeAlphaType(kOpaque_SkAlphaType),
578 int* inputColorCount) { 530 dst, dstRowBytes, NULL, colorPtr, colorCountPtr);
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 } 531 }
624 532
625 /* 533 /*
626 * 534 * Rewinds the image stream if necessary
627 * Process the color table for the bmp input
628 *
629 */ 535 */
630 bool SkBmpCodec::createColorTable(SkAlphaType alphaType, int* numColors) { 536 bool SkBmpCodec::handleRewind(bool isIco) {
631 // Allocate memory for color table 537 SkCodec::RewindState rewindState = this->rewindIfNeeded();
632 uint32_t colorBytes = 0; 538 if (rewindState == kCouldNotRewind_RewindState) {
633 uint32_t maxColors = 0; 539 return false;
634 SkPMColor colorTable[256]; 540 } else if (rewindState == kRewound_RewindState) {
635 if (fBitsPerPixel <= 8) { 541 if (!SkBmpCodec::ReadHeader(this->stream(), isIco, NULL)) {
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; 542 return false;
723 } 543 }
724 } 544 }
725
726 // Return true on success
727 return true; 545 return true;
728 } 546 }
729 547
730 /* 548 /*
731 *
732 * Get the destination row to start filling from 549 * Get the destination row to start filling from
733 * Used to fill the remainder of the image on incomplete input 550 * Used to fill the remainder of the image on incomplete input for bmps
scroggo 2015/08/04 16:16:46 Maybe explain why this is necessary? (And maybe th
msarett 2015/08/04 23:14:44 Yes that's correct, adding a comment.
734 *
735 */ 551 */
736 static inline void* get_dst_start_row(void* dst, size_t dstRowBytes, int32_t y, 552 void* SkBmpCodec::getDstStartRow(void* dst, size_t dstRowBytes, int32_t y) const {
737 SkBmpCodec::RowOrder rowOrder) { 553 return (kTopDown_RowOrder == fRowOrder) ? SkTAddOffset<void*>(dst, y * dstRo wBytes) : dst;
738 return (SkBmpCodec::kTopDown_RowOrder == rowOrder) ?
739 SkTAddOffset<void*>(dst, y * dstRowBytes) : dst;
740 } 554 }
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

Powered by Google App Engine
This is Rietveld 408576698