OLD | NEW |
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 "SkCodec_libbmp.h" | 8 #include "SkCodec_libbmp.h" |
9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 // The size of the second (info) header in bytes | 132 // The size of the second (info) header in bytes |
133 uint32_t infoBytes; | 133 uint32_t infoBytes; |
134 | 134 |
135 // Bmps embedded in Icos skip the first Bmp header | 135 // Bmps embedded in Icos skip the first Bmp header |
136 if (!isIco) { | 136 if (!isIco) { |
137 // Read the first header and the size of the second header | 137 // Read the first header and the size of the second header |
138 SkAutoTDeleteArray<uint8_t> hBuffer( | 138 SkAutoTDeleteArray<uint8_t> hBuffer( |
139 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour)); | 139 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour)); |
140 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) != | 140 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) != |
141 kBmpHeaderBytesPlusFour) { | 141 kBmpHeaderBytesPlusFour) { |
142 SkDebugf("Error: unable to read first bitmap header.\n"); | 142 SkCodecPrintf("Error: unable to read first bitmap header.\n"); |
143 return NULL; | 143 return NULL; |
144 } | 144 } |
145 | 145 |
146 totalBytes = get_int(hBuffer.get(), 2); | 146 totalBytes = get_int(hBuffer.get(), 2); |
147 offset = get_int(hBuffer.get(), 10); | 147 offset = get_int(hBuffer.get(), 10); |
148 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) { | 148 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) { |
149 SkDebugf("Error: invalid starting location for pixel data\n"); | 149 SkCodecPrintf("Error: invalid starting location for pixel data\n"); |
150 return NULL; | 150 return NULL; |
151 } | 151 } |
152 | 152 |
153 // The size of the second (info) header in bytes | 153 // The size of the second (info) header in bytes |
154 // The size is the first field of the second header, so we have already | 154 // The size is the first field of the second header, so we have already |
155 // read the first four infoBytes. | 155 // read the first four infoBytes. |
156 infoBytes = get_int(hBuffer.get(), 14); | 156 infoBytes = get_int(hBuffer.get(), 14); |
157 if (infoBytes < kBmpOS2V1Bytes) { | 157 if (infoBytes < kBmpOS2V1Bytes) { |
158 SkDebugf("Error: invalid second header size.\n"); | 158 SkCodecPrintf("Error: invalid second header size.\n"); |
159 return NULL; | 159 return NULL; |
160 } | 160 } |
161 } else { | 161 } else { |
162 // This value is only used by RLE compression. Bmp in Ico files do not | 162 // This value is only used by RLE compression. Bmp in Ico files do not |
163 // use RLE. If the compression field is incorrectly signaled as RLE, | 163 // use RLE. If the compression field is incorrectly signaled as RLE, |
164 // we will catch this and signal an error below. | 164 // we will catch this and signal an error below. |
165 totalBytes = 0; | 165 totalBytes = 0; |
166 | 166 |
167 // Bmps in Ico cannot specify an offset. We will always assume that | 167 // Bmps in Ico cannot specify an offset. We will always assume that |
168 // pixel data begins immediately after the color table. This value | 168 // pixel data begins immediately after the color table. This value |
169 // will be corrected below. | 169 // will be corrected below. |
170 offset = 0; | 170 offset = 0; |
171 | 171 |
172 // Read the size of the second header | 172 // Read the size of the second header |
173 SkAutoTDeleteArray<uint8_t> hBuffer( | 173 SkAutoTDeleteArray<uint8_t> hBuffer( |
174 SkNEW_ARRAY(uint8_t, 4)); | 174 SkNEW_ARRAY(uint8_t, 4)); |
175 if (stream->read(hBuffer.get(), 4) != 4) { | 175 if (stream->read(hBuffer.get(), 4) != 4) { |
176 SkDebugf("Error: unable to read size of second bitmap header.\n"); | 176 SkCodecPrintf("Error: unable to read size of second bitmap header.\n
"); |
177 return NULL; | 177 return NULL; |
178 } | 178 } |
179 infoBytes = get_int(hBuffer.get(), 0); | 179 infoBytes = get_int(hBuffer.get(), 0); |
180 if (infoBytes < kBmpOS2V1Bytes) { | 180 if (infoBytes < kBmpOS2V1Bytes) { |
181 SkDebugf("Error: invalid second header size.\n"); | 181 SkCodecPrintf("Error: invalid second header size.\n"); |
182 return NULL; | 182 return NULL; |
183 } | 183 } |
184 } | 184 } |
185 | 185 |
186 // We already read the first four bytes of the info header to get the size | 186 // We already read the first four bytes of the info header to get the size |
187 const uint32_t infoBytesRemaining = infoBytes - 4; | 187 const uint32_t infoBytesRemaining = infoBytes - 4; |
188 | 188 |
189 // Read the second header | 189 // Read the second header |
190 SkAutoTDeleteArray<uint8_t> iBuffer( | 190 SkAutoTDeleteArray<uint8_t> iBuffer( |
191 SkNEW_ARRAY(uint8_t, infoBytesRemaining)); | 191 SkNEW_ARRAY(uint8_t, infoBytesRemaining)); |
192 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) { | 192 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) { |
193 SkDebugf("Error: unable to read second bitmap header.\n"); | 193 SkCodecPrintf("Error: unable to read second bitmap header.\n"); |
194 return NULL; | 194 return NULL; |
195 } | 195 } |
196 | 196 |
197 // The number of bits used per pixel in the pixel data | 197 // The number of bits used per pixel in the pixel data |
198 uint16_t bitsPerPixel; | 198 uint16_t bitsPerPixel; |
199 | 199 |
200 // The compression method for the pixel data | 200 // The compression method for the pixel data |
201 uint32_t compression = kNone_BitmapCompressionMethod; | 201 uint32_t compression = kNone_BitmapCompressionMethod; |
202 | 202 |
203 // Number of colors in the color table, defaults to 0 or max (see below) | 203 // Number of colors in the color table, defaults to 0 or max (see below) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 case 60: | 241 case 60: |
242 case kBmpOS2V2Bytes: | 242 case kBmpOS2V2Bytes: |
243 headerType = kOS2VX_BitmapHeaderType; | 243 headerType = kOS2VX_BitmapHeaderType; |
244 break; | 244 break; |
245 default: | 245 default: |
246 // We do not signal an error here because there is the | 246 // We do not signal an error here because there is the |
247 // possibility of new or undocumented bmp header types. Most | 247 // possibility of new or undocumented bmp header types. Most |
248 // of the newer versions of bmp headers are similar to and | 248 // of the newer versions of bmp headers are similar to and |
249 // build off of the older versions, so we may still be able to | 249 // build off of the older versions, so we may still be able to |
250 // decode the bmp. | 250 // decode the bmp. |
251 SkDebugf("Warning: unknown bmp header format.\n"); | 251 SkCodecPrintf("Warning: unknown bmp header format.\n"); |
252 headerType = kUnknown_BitmapHeaderType; | 252 headerType = kUnknown_BitmapHeaderType; |
253 break; | 253 break; |
254 } | 254 } |
255 // We check the size of the header before entering the if statement. | 255 // We check the size of the header before entering the if statement. |
256 // We should not reach this point unless the size is large enough for | 256 // We should not reach this point unless the size is large enough for |
257 // these required fields. | 257 // these required fields. |
258 SkASSERT(infoBytesRemaining >= 12); | 258 SkASSERT(infoBytesRemaining >= 12); |
259 width = get_int(iBuffer.get(), 0); | 259 width = get_int(iBuffer.get(), 0); |
260 height = get_int(iBuffer.get(), 4); | 260 height = get_int(iBuffer.get(), 4); |
261 bitsPerPixel = get_short(iBuffer.get(), 10); | 261 bitsPerPixel = get_short(iBuffer.get(), 10); |
(...skipping 12 matching lines...) Expand all Loading... |
274 bytesPerColor = 4; | 274 bytesPerColor = 4; |
275 } else if (infoBytes >= kBmpOS2V1Bytes) { | 275 } else if (infoBytes >= kBmpOS2V1Bytes) { |
276 // The OS2V1 is treated separately because it has a unique format | 276 // The OS2V1 is treated separately because it has a unique format |
277 headerType = kOS2V1_BitmapHeaderType; | 277 headerType = kOS2V1_BitmapHeaderType; |
278 width = (int) get_short(iBuffer.get(), 0); | 278 width = (int) get_short(iBuffer.get(), 0); |
279 height = (int) get_short(iBuffer.get(), 2); | 279 height = (int) get_short(iBuffer.get(), 2); |
280 bitsPerPixel = get_short(iBuffer.get(), 6); | 280 bitsPerPixel = get_short(iBuffer.get(), 6); |
281 bytesPerColor = 3; | 281 bytesPerColor = 3; |
282 } else { | 282 } else { |
283 // There are no valid bmp headers | 283 // There are no valid bmp headers |
284 SkDebugf("Error: second bitmap header size is invalid.\n"); | 284 SkCodecPrintf("Error: second bitmap header size is invalid.\n"); |
285 return NULL; | 285 return NULL; |
286 } | 286 } |
287 | 287 |
288 // Check for valid dimensions from header | 288 // Check for valid dimensions from header |
289 RowOrder rowOrder = kBottomUp_RowOrder; | 289 RowOrder rowOrder = kBottomUp_RowOrder; |
290 if (height < 0) { | 290 if (height < 0) { |
291 height = -height; | 291 height = -height; |
292 rowOrder = kTopDown_RowOrder; | 292 rowOrder = kTopDown_RowOrder; |
293 } | 293 } |
294 // The height field for bmp in ico is double the actual height because they | 294 // The height field for bmp in ico is double the actual height because they |
295 // contain an XOR mask followed by an AND mask | 295 // contain an XOR mask followed by an AND mask |
296 if (isIco) { | 296 if (isIco) { |
297 height /= 2; | 297 height /= 2; |
298 } | 298 } |
299 static const int kBmpMaxDim = 1 << 16; | 299 static const int kBmpMaxDim = 1 << 16; |
300 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) { | 300 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) { |
301 // TODO: Decide if we want to support really large bmps. | 301 // TODO: Decide if we want to support really large bmps. |
302 SkDebugf("Error: invalid bitmap dimensions.\n"); | 302 SkCodecPrintf("Error: invalid bitmap dimensions.\n"); |
303 return NULL; | 303 return NULL; |
304 } | 304 } |
305 | 305 |
306 // Create mask struct | 306 // Create mask struct |
307 SkMasks::InputMasks inputMasks; | 307 SkMasks::InputMasks inputMasks; |
308 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks)); | 308 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks)); |
309 | 309 |
310 // Determine the input compression format and set bit masks if necessary | 310 // Determine the input compression format and set bit masks if necessary |
311 uint32_t maskBytes = 0; | 311 uint32_t maskBytes = 0; |
312 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat; | 312 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat; |
313 switch (compression) { | 313 switch (compression) { |
314 case kNone_BitmapCompressionMethod: | 314 case kNone_BitmapCompressionMethod: |
315 inputFormat = kStandard_BitmapInputFormat; | 315 inputFormat = kStandard_BitmapInputFormat; |
316 break; | 316 break; |
317 case k8BitRLE_BitmapCompressionMethod: | 317 case k8BitRLE_BitmapCompressionMethod: |
318 if (bitsPerPixel != 8) { | 318 if (bitsPerPixel != 8) { |
319 SkDebugf("Warning: correcting invalid bitmap format.\n"); | 319 SkCodecPrintf("Warning: correcting invalid bitmap format.\n"); |
320 bitsPerPixel = 8; | 320 bitsPerPixel = 8; |
321 } | 321 } |
322 inputFormat = kRLE_BitmapInputFormat; | 322 inputFormat = kRLE_BitmapInputFormat; |
323 break; | 323 break; |
324 case k4BitRLE_BitmapCompressionMethod: | 324 case k4BitRLE_BitmapCompressionMethod: |
325 if (bitsPerPixel != 4) { | 325 if (bitsPerPixel != 4) { |
326 SkDebugf("Warning: correcting invalid bitmap format.\n"); | 326 SkCodecPrintf("Warning: correcting invalid bitmap format.\n"); |
327 bitsPerPixel = 4; | 327 bitsPerPixel = 4; |
328 } | 328 } |
329 inputFormat = kRLE_BitmapInputFormat; | 329 inputFormat = kRLE_BitmapInputFormat; |
330 break; | 330 break; |
331 case kAlphaBitMasks_BitmapCompressionMethod: | 331 case kAlphaBitMasks_BitmapCompressionMethod: |
332 case kBitMasks_BitmapCompressionMethod: | 332 case kBitMasks_BitmapCompressionMethod: |
333 // Load the masks | 333 // Load the masks |
334 inputFormat = kBitMask_BitmapInputFormat; | 334 inputFormat = kBitMask_BitmapInputFormat; |
335 switch (headerType) { | 335 switch (headerType) { |
336 case kInfoV1_BitmapHeaderType: { | 336 case kInfoV1_BitmapHeaderType: { |
337 // The V1 header stores the bit masks after the header | 337 // The V1 header stores the bit masks after the header |
338 SkAutoTDeleteArray<uint8_t> mBuffer( | 338 SkAutoTDeleteArray<uint8_t> mBuffer( |
339 SkNEW_ARRAY(uint8_t, kBmpMaskBytes)); | 339 SkNEW_ARRAY(uint8_t, kBmpMaskBytes)); |
340 if (stream->read(mBuffer.get(), kBmpMaskBytes) != | 340 if (stream->read(mBuffer.get(), kBmpMaskBytes) != |
341 kBmpMaskBytes) { | 341 kBmpMaskBytes) { |
342 SkDebugf("Error: unable to read bit inputMasks.\n"); | 342 SkCodecPrintf("Error: unable to read bit inputMasks.\n")
; |
343 return NULL; | 343 return NULL; |
344 } | 344 } |
345 maskBytes = kBmpMaskBytes; | 345 maskBytes = kBmpMaskBytes; |
346 inputMasks.red = get_int(mBuffer.get(), 0); | 346 inputMasks.red = get_int(mBuffer.get(), 0); |
347 inputMasks.green = get_int(mBuffer.get(), 4); | 347 inputMasks.green = get_int(mBuffer.get(), 4); |
348 inputMasks.blue = get_int(mBuffer.get(), 8); | 348 inputMasks.blue = get_int(mBuffer.get(), 8); |
349 break; | 349 break; |
350 } | 350 } |
351 case kInfoV2_BitmapHeaderType: | 351 case kInfoV2_BitmapHeaderType: |
352 case kInfoV3_BitmapHeaderType: | 352 case kInfoV3_BitmapHeaderType: |
353 case kInfoV4_BitmapHeaderType: | 353 case kInfoV4_BitmapHeaderType: |
354 case kInfoV5_BitmapHeaderType: | 354 case kInfoV5_BitmapHeaderType: |
355 // Header types are matched based on size. If the header | 355 // Header types are matched based on size. If the header |
356 // is V2+, we are guaranteed to be able to read at least | 356 // is V2+, we are guaranteed to be able to read at least |
357 // this size. | 357 // this size. |
358 SkASSERT(infoBytesRemaining >= 48); | 358 SkASSERT(infoBytesRemaining >= 48); |
359 inputMasks.red = get_int(iBuffer.get(), 36); | 359 inputMasks.red = get_int(iBuffer.get(), 36); |
360 inputMasks.green = get_int(iBuffer.get(), 40); | 360 inputMasks.green = get_int(iBuffer.get(), 40); |
361 inputMasks.blue = get_int(iBuffer.get(), 44); | 361 inputMasks.blue = get_int(iBuffer.get(), 44); |
362 break; | 362 break; |
363 case kOS2VX_BitmapHeaderType: | 363 case kOS2VX_BitmapHeaderType: |
364 // TODO: Decide if we intend to support this. | 364 // TODO: Decide if we intend to support this. |
365 // It is unsupported in the previous version and | 365 // It is unsupported in the previous version and |
366 // in chromium. I have not come across a test case | 366 // in chromium. I have not come across a test case |
367 // that uses this format. | 367 // that uses this format. |
368 SkDebugf("Error: huffman format unsupported.\n"); | 368 SkCodecPrintf("Error: huffman format unsupported.\n"); |
369 return NULL; | 369 return NULL; |
370 default: | 370 default: |
371 SkDebugf("Error: invalid bmp bit masks header.\n"); | 371 SkCodecPrintf("Error: invalid bmp bit masks header.\n"); |
372 return NULL; | 372 return NULL; |
373 } | 373 } |
374 break; | 374 break; |
375 case kJpeg_BitmapCompressionMethod: | 375 case kJpeg_BitmapCompressionMethod: |
376 if (24 == bitsPerPixel) { | 376 if (24 == bitsPerPixel) { |
377 inputFormat = kRLE_BitmapInputFormat; | 377 inputFormat = kRLE_BitmapInputFormat; |
378 break; | 378 break; |
379 } | 379 } |
380 // Fall through | 380 // Fall through |
381 case kPng_BitmapCompressionMethod: | 381 case kPng_BitmapCompressionMethod: |
382 // TODO: Decide if we intend to support this. | 382 // TODO: Decide if we intend to support this. |
383 // It is unsupported in the previous version and | 383 // It is unsupported in the previous version and |
384 // in chromium. I think it is used mostly for printers. | 384 // in chromium. I think it is used mostly for printers. |
385 SkDebugf("Error: compression format not supported.\n"); | 385 SkCodecPrintf("Error: compression format not supported.\n"); |
386 return NULL; | 386 return NULL; |
387 case kCMYK_BitmapCompressionMethod: | 387 case kCMYK_BitmapCompressionMethod: |
388 case kCMYK8BitRLE_BitmapCompressionMethod: | 388 case kCMYK8BitRLE_BitmapCompressionMethod: |
389 case kCMYK4BitRLE_BitmapCompressionMethod: | 389 case kCMYK4BitRLE_BitmapCompressionMethod: |
390 // TODO: Same as above. | 390 // TODO: Same as above. |
391 SkDebugf("Error: CMYK not supported for bitmap decoding.\n"); | 391 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n"); |
392 return NULL; | 392 return NULL; |
393 default: | 393 default: |
394 SkDebugf("Error: invalid format for bitmap decoding.\n"); | 394 SkCodecPrintf("Error: invalid format for bitmap decoding.\n"); |
395 return NULL; | 395 return NULL; |
396 } | 396 } |
397 | 397 |
398 // Most versions of bmps should be rendered as opaque. Either they do | 398 // Most versions of bmps should be rendered as opaque. Either they do |
399 // not have an alpha channel, or they expect the alpha channel to be | 399 // not have an alpha channel, or they expect the alpha channel to be |
400 // ignored. V3+ bmp files introduce an alpha mask and allow the creator | 400 // ignored. V3+ bmp files introduce an alpha mask and allow the creator |
401 // of the image to use the alpha channels. However, many of these images | 401 // of the image to use the alpha channels. However, many of these images |
402 // leave the alpha channel blank and expect to be rendered as opaque. This | 402 // leave the alpha channel blank and expect to be rendered as opaque. This |
403 // is the case for almost all V3 images, so we render these as opaque. For | 403 // is the case for almost all V3 images, so we render these as opaque. For |
404 // V4+, we will use the alpha channel, and fix the image later if it turns | 404 // V4+, we will use the alpha channel, and fix the image later if it turns |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 } | 439 } |
440 break; | 440 break; |
441 case 1: | 441 case 1: |
442 case 2: | 442 case 2: |
443 case 4: | 443 case 4: |
444 case 8: | 444 case 8: |
445 case 24: | 445 case 24: |
446 case 32: | 446 case 32: |
447 break; | 447 break; |
448 default: | 448 default: |
449 SkDebugf("Error: invalid input value for bits per pixel.\n"); | 449 SkCodecPrintf("Error: invalid input value for bits per pixel.\n"); |
450 return NULL; | 450 return NULL; |
451 } | 451 } |
452 | 452 |
453 // Check that input bit masks are valid and create the masks object | 453 // Check that input bit masks are valid and create the masks object |
454 SkAutoTDelete<SkMasks> | 454 SkAutoTDelete<SkMasks> |
455 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel)); | 455 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel)); |
456 if (NULL == masks) { | 456 if (NULL == masks) { |
457 SkDebugf("Error: invalid input masks.\n"); | 457 SkCodecPrintf("Error: invalid input masks.\n"); |
458 return NULL; | 458 return NULL; |
459 } | 459 } |
460 | 460 |
461 // Check for a valid number of total bytes when in RLE mode | 461 // Check for a valid number of total bytes when in RLE mode |
462 if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) { | 462 if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) { |
463 SkDebugf("Error: RLE requires valid input size.\n"); | 463 SkCodecPrintf("Error: RLE requires valid input size.\n"); |
464 return NULL; | 464 return NULL; |
465 } | 465 } |
466 const size_t RLEBytes = totalBytes - offset; | 466 const size_t RLEBytes = totalBytes - offset; |
467 | 467 |
468 // Calculate the number of bytes read so far | 468 // Calculate the number of bytes read so far |
469 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; | 469 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; |
470 if (!isIco && offset < bytesRead) { | 470 if (!isIco && offset < bytesRead) { |
471 SkDebugf("Error: pixel data offset less than header size.\n"); | 471 SkCodecPrintf("Error: pixel data offset less than header size.\n"); |
472 return NULL; | 472 return NULL; |
473 } | 473 } |
474 | 474 |
475 // Return the codec | 475 // Return the codec |
476 // We will use ImageInfo to store width, height, and alpha type. We will | 476 // We will use ImageInfo to store width, height, and alpha type. We will |
477 // set color type to kN32_SkColorType because that should be the default | 477 // set color type to kN32_SkColorType because that should be the default |
478 // output. | 478 // output. |
479 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, | 479 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, |
480 kN32_SkColorType, alphaType); | 480 kN32_SkColorType, alphaType); |
481 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, | 481 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 */ | 516 */ |
517 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, | 517 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, |
518 void* dst, size_t dstRowBytes, | 518 void* dst, size_t dstRowBytes, |
519 const Options&, | 519 const Options&, |
520 SkPMColor*, int*) { | 520 SkPMColor*, int*) { |
521 // Check for proper input and output formats | 521 // Check for proper input and output formats |
522 if (!this->rewindIfNeeded()) { | 522 if (!this->rewindIfNeeded()) { |
523 return kCouldNotRewind; | 523 return kCouldNotRewind; |
524 } | 524 } |
525 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 525 if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
526 SkDebugf("Error: scaling not supported.\n"); | 526 SkCodecPrintf("Error: scaling not supported.\n"); |
527 return kInvalidScale; | 527 return kInvalidScale; |
528 } | 528 } |
529 if (!conversion_possible(dstInfo, this->getInfo())) { | 529 if (!conversion_possible(dstInfo, this->getInfo())) { |
530 SkDebugf("Error: cannot convert input type to output type.\n"); | 530 SkCodecPrintf("Error: cannot convert input type to output type.\n"); |
531 return kInvalidConversion; | 531 return kInvalidConversion; |
532 } | 532 } |
533 | 533 |
534 // Create the color table if necessary and prepare the stream for decode | 534 // Create the color table if necessary and prepare the stream for decode |
535 if (!createColorTable(dstInfo.alphaType())) { | 535 if (!createColorTable(dstInfo.alphaType())) { |
536 SkDebugf("Error: could not create color table.\n"); | 536 SkCodecPrintf("Error: could not create color table.\n"); |
537 return kInvalidInput; | 537 return kInvalidInput; |
538 } | 538 } |
539 | 539 |
540 // Perform the decode | 540 // Perform the decode |
541 switch (fInputFormat) { | 541 switch (fInputFormat) { |
542 case kBitMask_BitmapInputFormat: | 542 case kBitMask_BitmapInputFormat: |
543 return decodeMask(dstInfo, dst, dstRowBytes); | 543 return decodeMask(dstInfo, dst, dstRowBytes); |
544 case kRLE_BitmapInputFormat: | 544 case kRLE_BitmapInputFormat: |
545 return decodeRLE(dstInfo, dst, dstRowBytes); | 545 return decodeRLE(dstInfo, dst, dstRowBytes); |
546 case kStandard_BitmapInputFormat: | 546 case kStandard_BitmapInputFormat: |
(...skipping 19 matching lines...) Expand all Loading... |
566 // Also set fNumColors to maxColors when it is too large | 566 // Also set fNumColors to maxColors when it is too large |
567 maxColors = 1 << fBitsPerPixel; | 567 maxColors = 1 << fBitsPerPixel; |
568 if (fNumColors == 0 || fNumColors >= maxColors) { | 568 if (fNumColors == 0 || fNumColors >= maxColors) { |
569 fNumColors = maxColors; | 569 fNumColors = maxColors; |
570 } | 570 } |
571 | 571 |
572 // Read the color table from the stream | 572 // Read the color table from the stream |
573 colorBytes = fNumColors * fBytesPerColor; | 573 colorBytes = fNumColors * fBytesPerColor; |
574 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes)); | 574 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes)); |
575 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { | 575 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { |
576 SkDebugf("Error: unable to read color table.\n"); | 576 SkCodecPrintf("Error: unable to read color table.\n"); |
577 return false; | 577 return false; |
578 } | 578 } |
579 | 579 |
580 // Choose the proper packing function | 580 // Choose the proper packing function |
581 SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t); | 581 SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t); |
582 switch (alphaType) { | 582 switch (alphaType) { |
583 case kOpaque_SkAlphaType: | 583 case kOpaque_SkAlphaType: |
584 case kUnpremul_SkAlphaType: | 584 case kUnpremul_SkAlphaType: |
585 packARGB = &SkPackARGB32NoCheck; | 585 packARGB = &SkPackARGB32NoCheck; |
586 break; | 586 break; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 // Bmp-in-Ico files do not use an offset to indicate where the pixel data | 619 // Bmp-in-Ico files do not use an offset to indicate where the pixel data |
620 // begins. Pixel data always begins immediately after the color table. | 620 // begins. Pixel data always begins immediately after the color table. |
621 if (!fIsIco) { | 621 if (!fIsIco) { |
622 // Check that we have not read past the pixel array offset | 622 // Check that we have not read past the pixel array offset |
623 if(fOffset < colorBytes) { | 623 if(fOffset < colorBytes) { |
624 // This may occur on OS 2.1 and other old versions where the color | 624 // This may occur on OS 2.1 and other old versions where the color |
625 // table defaults to max size, and the bmp tries to use a smaller | 625 // table defaults to max size, and the bmp tries to use a smaller |
626 // color table. This is invalid, and our decision is to indicate | 626 // color table. This is invalid, and our decision is to indicate |
627 // an error, rather than try to guess the intended size of the | 627 // an error, rather than try to guess the intended size of the |
628 // color table. | 628 // color table. |
629 SkDebugf("Error: pixel data offset less than color table size.\n"); | 629 SkCodecPrintf("Error: pixel data offset less than color table size.\
n"); |
630 return false; | 630 return false; |
631 } | 631 } |
632 | 632 |
633 // After reading the color table, skip to the start of the pixel array | 633 // After reading the color table, skip to the start of the pixel array |
634 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { | 634 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { |
635 SkDebugf("Error: unable to skip to image data.\n"); | 635 SkCodecPrintf("Error: unable to skip to image data.\n"); |
636 return false; | 636 return false; |
637 } | 637 } |
638 } | 638 } |
639 | 639 |
640 // Set the color table and return true on success | 640 // Set the color table and return true on success |
641 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors))); | 641 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors))); |
642 return true; | 642 return true; |
643 } | 643 } |
644 | 644 |
645 /* | 645 /* |
(...skipping 16 matching lines...) Expand all Loading... |
662 // Create the swizzler | 662 // Create the swizzler |
663 SkAutoTDelete<SkMaskSwizzler> maskSwizzler( | 663 SkAutoTDelete<SkMaskSwizzler> maskSwizzler( |
664 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes, | 664 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes, |
665 fMasks, fBitsPerPixel)); | 665 fMasks, fBitsPerPixel)); |
666 | 666 |
667 // Iterate over rows of the image | 667 // Iterate over rows of the image |
668 bool transparent = true; | 668 bool transparent = true; |
669 for (int y = 0; y < height; y++) { | 669 for (int y = 0; y < height; y++) { |
670 // Read a row of the input | 670 // Read a row of the input |
671 if (stream()->read(srcRow, rowBytes) != rowBytes) { | 671 if (stream()->read(srcRow, rowBytes) != rowBytes) { |
672 SkDebugf("Warning: incomplete input stream.\n"); | 672 SkCodecPrintf("Warning: incomplete input stream.\n"); |
673 return kIncompleteInput; | 673 return kIncompleteInput; |
674 } | 674 } |
675 | 675 |
676 // Decode the row in destination format | 676 // Decode the row in destination format |
677 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; | 677 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; |
678 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row); | 678 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row); |
679 transparent &= SkSwizzler::IsTransparent(r); | 679 transparent &= SkSwizzler::IsTransparent(r); |
680 | 680 |
681 // Move to the next row | 681 // Move to the next row |
682 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes); | 682 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 | 800 |
801 // Set constant values | 801 // Set constant values |
802 const int width = dstInfo.width(); | 802 const int width = dstInfo.width(); |
803 const int height = dstInfo.height(); | 803 const int height = dstInfo.height(); |
804 | 804 |
805 // Input buffer parameters | 805 // Input buffer parameters |
806 uint32_t currByte = 0; | 806 uint32_t currByte = 0; |
807 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes)); | 807 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes)); |
808 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes); | 808 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes); |
809 if (totalBytes < fRLEBytes) { | 809 if (totalBytes < fRLEBytes) { |
810 SkDebugf("Warning: incomplete RLE file.\n"); | 810 SkCodecPrintf("Warning: incomplete RLE file.\n"); |
811 } else if (totalBytes <= 0) { | 811 } else if (totalBytes <= 0) { |
812 SkDebugf("Error: could not read RLE image data.\n"); | 812 SkCodecPrintf("Error: could not read RLE image data.\n"); |
813 return kInvalidInput; | 813 return kInvalidInput; |
814 } | 814 } |
815 | 815 |
816 // Destination parameters | 816 // Destination parameters |
817 int x = 0; | 817 int x = 0; |
818 int y = 0; | 818 int y = 0; |
819 // If the code skips pixels, remaining pixels are transparent or black | 819 // If the code skips pixels, remaining pixels are transparent or black |
820 // TODO: Skip this if memory was already zeroed. | 820 // TODO: Skip this if memory was already zeroed. |
821 memset(dst, 0, dstRowBytes * height); | 821 memset(dst, 0, dstRowBytes * height); |
822 SkPMColor* dstPtr = (SkPMColor*) dst; | 822 SkPMColor* dstPtr = (SkPMColor*) dst; |
823 | 823 |
824 while (true) { | 824 while (true) { |
825 // Every entry takes at least two bytes | 825 // Every entry takes at least two bytes |
826 if ((int) totalBytes - currByte < 2) { | 826 if ((int) totalBytes - currByte < 2) { |
827 SkDebugf("Warning: incomplete RLE input.\n"); | 827 SkCodecPrintf("Warning: incomplete RLE input.\n"); |
828 return kIncompleteInput; | 828 return kIncompleteInput; |
829 } | 829 } |
830 | 830 |
831 // Read the next two bytes. These bytes have different meanings | 831 // Read the next two bytes. These bytes have different meanings |
832 // depending on their values. In the first interpretation, the first | 832 // depending on their values. In the first interpretation, the first |
833 // byte is an escape flag and the second byte indicates what special | 833 // byte is an escape flag and the second byte indicates what special |
834 // task to perform. | 834 // task to perform. |
835 const uint8_t flag = buffer.get()[currByte++]; | 835 const uint8_t flag = buffer.get()[currByte++]; |
836 const uint8_t task = buffer.get()[currByte++]; | 836 const uint8_t task = buffer.get()[currByte++]; |
837 | 837 |
838 // If we have reached a row that is beyond the image size, and the RLE | 838 // If we have reached a row that is beyond the image size, and the RLE |
839 // code does not indicate end of file, abort and signal a warning. | 839 // code does not indicate end of file, abort and signal a warning. |
840 if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) { | 840 if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) { |
841 SkDebugf("Warning: invalid RLE input.\n"); | 841 SkCodecPrintf("Warning: invalid RLE input.\n"); |
842 return kIncompleteInput; | 842 return kIncompleteInput; |
843 } | 843 } |
844 | 844 |
845 // Perform decoding | 845 // Perform decoding |
846 if (RLE_ESCAPE == flag) { | 846 if (RLE_ESCAPE == flag) { |
847 switch (task) { | 847 switch (task) { |
848 case RLE_EOL: | 848 case RLE_EOL: |
849 x = 0; | 849 x = 0; |
850 y++; | 850 y++; |
851 break; | 851 break; |
852 case RLE_EOF: | 852 case RLE_EOF: |
853 return kSuccess; | 853 return kSuccess; |
854 case RLE_DELTA: { | 854 case RLE_DELTA: { |
855 // Two bytes are needed to specify delta | 855 // Two bytes are needed to specify delta |
856 if ((int) totalBytes - currByte < 2) { | 856 if ((int) totalBytes - currByte < 2) { |
857 SkDebugf("Warning: incomplete RLE input\n"); | 857 SkCodecPrintf("Warning: incomplete RLE input\n"); |
858 return kIncompleteInput; | 858 return kIncompleteInput; |
859 } | 859 } |
860 // Modify x and y | 860 // Modify x and y |
861 const uint8_t dx = buffer.get()[currByte++]; | 861 const uint8_t dx = buffer.get()[currByte++]; |
862 const uint8_t dy = buffer.get()[currByte++]; | 862 const uint8_t dy = buffer.get()[currByte++]; |
863 x += dx; | 863 x += dx; |
864 y += dy; | 864 y += dy; |
865 if (x > width || y > height) { | 865 if (x > width || y > height) { |
866 SkDebugf("Warning: invalid RLE input.\n"); | 866 SkCodecPrintf("Warning: invalid RLE input.\n"); |
867 return kIncompleteInput; | 867 return kIncompleteInput; |
868 } | 868 } |
869 break; | 869 break; |
870 } | 870 } |
871 default: { | 871 default: { |
872 // If task does not match any of the above signals, it | 872 // If task does not match any of the above signals, it |
873 // indicates that we have a sequence of non-RLE pixels. | 873 // indicates that we have a sequence of non-RLE pixels. |
874 // Furthermore, the value of task is equal to the number | 874 // Furthermore, the value of task is equal to the number |
875 // of pixels to interpret. | 875 // of pixels to interpret. |
876 uint8_t numPixels = task; | 876 uint8_t numPixels = task; |
877 const size_t rowBytes = compute_row_bytes(numPixels, | 877 const size_t rowBytes = compute_row_bytes(numPixels, |
878 fBitsPerPixel); | 878 fBitsPerPixel); |
879 // Abort if setting numPixels moves us off the edge of the | 879 // Abort if setting numPixels moves us off the edge of the |
880 // image. Also abort if there are not enough bytes | 880 // image. Also abort if there are not enough bytes |
881 // remaining in the stream to set numPixels. | 881 // remaining in the stream to set numPixels. |
882 if (x + numPixels > width || | 882 if (x + numPixels > width || |
883 (int) totalBytes - currByte < SkAlign2(rowBytes)) { | 883 (int) totalBytes - currByte < SkAlign2(rowBytes)) { |
884 SkDebugf("Warning: invalid RLE input.\n"); | 884 SkCodecPrintf("Warning: invalid RLE input.\n"); |
885 return kIncompleteInput; | 885 return kIncompleteInput; |
886 } | 886 } |
887 // Set numPixels number of pixels | 887 // Set numPixels number of pixels |
888 while (numPixels > 0) { | 888 while (numPixels > 0) { |
889 switch(fBitsPerPixel) { | 889 switch(fBitsPerPixel) { |
890 case 4: { | 890 case 4: { |
891 SkASSERT(currByte < totalBytes); | 891 SkASSERT(currByte < totalBytes); |
892 uint8_t val = buffer.get()[currByte++]; | 892 uint8_t val = buffer.get()[currByte++]; |
893 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++, | 893 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++, |
894 y, val >> 4); | 894 y, val >> 4); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
931 // If the first byte read is not a flag, it indicates the number of | 931 // If the first byte read is not a flag, it indicates the number of |
932 // pixels to set in RLE mode. | 932 // pixels to set in RLE mode. |
933 const uint8_t numPixels = flag; | 933 const uint8_t numPixels = flag; |
934 const int endX = SkTMin<int>(x + numPixels, width); | 934 const int endX = SkTMin<int>(x + numPixels, width); |
935 | 935 |
936 if (24 == fBitsPerPixel) { | 936 if (24 == fBitsPerPixel) { |
937 // In RLE24, the second byte read is part of the pixel color. | 937 // In RLE24, the second byte read is part of the pixel color. |
938 // There are two more required bytes to finish encoding the | 938 // There are two more required bytes to finish encoding the |
939 // color. | 939 // color. |
940 if ((int) totalBytes - currByte < 2) { | 940 if ((int) totalBytes - currByte < 2) { |
941 SkDebugf("Warning: incomplete RLE input\n"); | 941 SkCodecPrintf("Warning: incomplete RLE input\n"); |
942 return kIncompleteInput; | 942 return kIncompleteInput; |
943 } | 943 } |
944 | 944 |
945 // Fill the pixels up to endX with the specified color | 945 // Fill the pixels up to endX with the specified color |
946 uint8_t blue = task; | 946 uint8_t blue = task; |
947 uint8_t green = buffer.get()[currByte++]; | 947 uint8_t green = buffer.get()[currByte++]; |
948 uint8_t red = buffer.get()[currByte++]; | 948 uint8_t red = buffer.get()[currByte++]; |
949 while (x < endX) { | 949 while (x < endX) { |
950 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, x++, y, red, | 950 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, x++, y, red, |
951 green, blue); | 951 green, blue); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 SkImageGenerator::kNo_ZeroInitialized)); | 1021 SkImageGenerator::kNo_ZeroInitialized)); |
1022 | 1022 |
1023 // Allocate space for a row buffer and a source for the swizzler | 1023 // Allocate space for a row buffer and a source for the swizzler |
1024 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); | 1024 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); |
1025 | 1025 |
1026 // Iterate over rows of the image | 1026 // Iterate over rows of the image |
1027 // FIXME: bool transparent = true; | 1027 // FIXME: bool transparent = true; |
1028 for (int y = 0; y < height; y++) { | 1028 for (int y = 0; y < height; y++) { |
1029 // Read a row of the input | 1029 // Read a row of the input |
1030 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { | 1030 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { |
1031 SkDebugf("Warning: incomplete input stream.\n"); | 1031 SkCodecPrintf("Warning: incomplete input stream.\n"); |
1032 return kIncompleteInput; | 1032 return kIncompleteInput; |
1033 } | 1033 } |
1034 | 1034 |
1035 // Decode the row in destination format | 1035 // Decode the row in destination format |
1036 uint32_t row; | 1036 uint32_t row; |
1037 if (kTopDown_RowOrder == fRowOrder) { | 1037 if (kTopDown_RowOrder == fRowOrder) { |
1038 row = y; | 1038 row = y; |
1039 } else { | 1039 } else { |
1040 row = height - 1 - y; | 1040 row = height - 1 - y; |
1041 } | 1041 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1073 | 1073 |
1074 // Finally, apply the AND mask for bmp-in-ico images | 1074 // Finally, apply the AND mask for bmp-in-ico images |
1075 if (fIsIco) { | 1075 if (fIsIco) { |
1076 // The AND mask is always 1 bit per pixel | 1076 // The AND mask is always 1 bit per pixel |
1077 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); | 1077 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); |
1078 | 1078 |
1079 SkPMColor* dstPtr = (SkPMColor*) dst; | 1079 SkPMColor* dstPtr = (SkPMColor*) dst; |
1080 for (int y = 0; y < height; y++) { | 1080 for (int y = 0; y < height; y++) { |
1081 // The srcBuffer will at least be large enough | 1081 // The srcBuffer will at least be large enough |
1082 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { | 1082 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { |
1083 SkDebugf("Warning: incomplete AND mask for bmp-in-ico.\n"); | 1083 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n"); |
1084 return kIncompleteInput; | 1084 return kIncompleteInput; |
1085 } | 1085 } |
1086 | 1086 |
1087 int row; | 1087 int row; |
1088 if (kBottomUp_RowOrder == fRowOrder) { | 1088 if (kBottomUp_RowOrder == fRowOrder) { |
1089 row = height - y - 1; | 1089 row = height - y - 1; |
1090 } else { | 1090 } else { |
1091 row = y; | 1091 row = y; |
1092 } | 1092 } |
1093 | 1093 |
1094 SkPMColor* dstRow = | 1094 SkPMColor* dstRow = |
1095 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); | 1095 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); |
1096 | 1096 |
1097 for (int x = 0; x < width; x++) { | 1097 for (int x = 0; x < width; x++) { |
1098 int quotient; | 1098 int quotient; |
1099 int modulus; | 1099 int modulus; |
1100 SkTDivMod(x, 8, "ient, &modulus); | 1100 SkTDivMod(x, 8, "ient, &modulus); |
1101 uint32_t shift = 7 - modulus; | 1101 uint32_t shift = 7 - modulus; |
1102 uint32_t alphaBit = | 1102 uint32_t alphaBit = |
1103 (srcBuffer.get()[quotient] >> shift) & 0x1; | 1103 (srcBuffer.get()[quotient] >> shift) & 0x1; |
1104 dstRow[x] &= alphaBit - 1; | 1104 dstRow[x] &= alphaBit - 1; |
1105 } | 1105 } |
1106 } | 1106 } |
1107 } | 1107 } |
1108 | 1108 |
1109 // Finished decoding the entire image | 1109 // Finished decoding the entire image |
1110 return kSuccess; | 1110 return kSuccess; |
1111 } | 1111 } |
OLD | NEW |