| 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 |