1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkBmpCodec.h" 9 #include "SkBmpMaskCodec.h" 10 #include "SkBmpRLECodec.h" 11 #include "SkBmpStandardCodec.h" 12 #include "SkCodecPriv.h" 13 #include "SkColorPriv.h" 14 #include "SkStream.h" 15 16 /* 17 * Defines the version and type of the second bitmap header 18 */ 19 enum BmpHeaderType { 20 kInfoV1_BmpHeaderType, 21 kInfoV2_BmpHeaderType, 22 kInfoV3_BmpHeaderType, 23 kInfoV4_BmpHeaderType, 24 kInfoV5_BmpHeaderType, 25 kOS2V1_BmpHeaderType, 26 kOS2VX_BmpHeaderType, 27 kUnknown_BmpHeaderType 28 }; 29 30 /* 31 * Possible bitmap compression types 32 */ 33 enum BmpCompressionMethod { 34 kNone_BmpCompressionMethod = 0, 35 k8BitRLE_BmpCompressionMethod = 1, 36 k4BitRLE_BmpCompressionMethod = 2, 37 kBitMasks_BmpCompressionMethod = 3, 38 kJpeg_BmpCompressionMethod = 4, 39 kPng_BmpCompressionMethod = 5, 40 kAlphaBitMasks_BmpCompressionMethod = 6, 41 kCMYK_BmpCompressionMethod = 11, 42 kCMYK8BitRLE_BmpCompressionMethod = 12, 43 kCMYK4BitRLE_BmpCompressionMethod = 13 44 }; 45 46 /* 47 * Used to define the input format of the bmp 48 */ 49 enum BmpInputFormat { 50 kStandard_BmpInputFormat, 51 kRLE_BmpInputFormat, 52 kBitMask_BmpInputFormat, 53 kUnknown_BmpInputFormat 54 }; 55 56 /* 57 * Checks the start of the stream to see if the image is a bitmap 58 */ 59 bool SkBmpCodec::IsBmp(const void* buffer, size_t bytesRead) { 60 // TODO: Support "IC", "PT", "CI", "CP", "BA" 61 const char bmpSig[] = { 'B', 'M' }; 62 return bytesRead >= sizeof(bmpSig) && !memcmp(buffer, bmpSig, sizeof(bmpSig)); 63 } 64 65 /* 66 * Assumes IsBmp was called and returned true 67 * Creates a bmp decoder 68 * Reads enough of the stream to determine the image format 69 */ 70 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, Result* result) { 71 return SkBmpCodec::NewFromStream(stream, result, false); 72 } 73 74 /* 75 * Creates a bmp decoder for a bmp embedded in ico 76 * Reads enough of the stream to determine the image format 77 */ 78 SkCodec* SkBmpCodec::NewFromIco(SkStream* stream, Result* result) { 79 return SkBmpCodec::NewFromStream(stream, result, true); 80 } 81 82 // Header size constants 83 static const uint32_t kBmpHeaderBytes = 14; 84 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4; 85 static const uint32_t kBmpOS2V1Bytes = 12; 86 static const uint32_t kBmpOS2V2Bytes = 64; 87 static const uint32_t kBmpInfoBaseBytes = 16; 88 static const uint32_t kBmpInfoV1Bytes = 40; 89 static const uint32_t kBmpInfoV2Bytes = 52; 90 static const uint32_t kBmpInfoV3Bytes = 56; 91 static const uint32_t kBmpInfoV4Bytes = 108; 92 static const uint32_t kBmpInfoV5Bytes = 124; 93 static const uint32_t kBmpMaskBytes = 12; 94 95 static BmpHeaderType get_header_type(size_t infoBytes) { 96 if (infoBytes >= kBmpInfoBaseBytes) { 97 // Check the version of the header 98 switch (infoBytes) { 99 case kBmpInfoV1Bytes: 100 return kInfoV1_BmpHeaderType; 101 case kBmpInfoV2Bytes: 102 return kInfoV2_BmpHeaderType; 103 case kBmpInfoV3Bytes: 104 return kInfoV3_BmpHeaderType; 105 case kBmpInfoV4Bytes: 106 return kInfoV4_BmpHeaderType; 107 case kBmpInfoV5Bytes: 108 return kInfoV5_BmpHeaderType; 109 case 16: 110 case 20: 111 case 24: 112 case 28: 113 case 32: 114 case 36: 115 case 42: 116 case 46: 117 case 48: 118 case 60: 119 case kBmpOS2V2Bytes: 120 return kOS2VX_BmpHeaderType; 121 default: 122 SkCodecPrintf("Error: unknown bmp header format.\n"); 123 return kUnknown_BmpHeaderType; 124 } 125 } if (infoBytes >= kBmpOS2V1Bytes) { 126 // The OS2V1 is treated separately because it has a unique format 127 return kOS2V1_BmpHeaderType; 128 } else { 129 // There are no valid bmp headers 130 SkCodecPrintf("Error: second bitmap header size is invalid.\n"); 131 return kUnknown_BmpHeaderType; 132 } 133 } 134 135 SkCodec::Result SkBmpCodec::ReadHeader(SkStream* stream, bool inIco, 136 std::unique_ptr<SkCodec>* codecOut) { 137 // The total bytes in the bmp file 138 // We only need to use this value for RLE decoding, so we will only 139 // check that it is valid in the RLE case. 140 uint32_t totalBytes; 141 // The offset from the start of the file where the pixel data begins 142 uint32_t offset; 143 // The size of the second (info) header in bytes 144 uint32_t infoBytes; 145 146 // Bmps embedded in Icos skip the first Bmp header 147 if (!inIco) { 148 // Read the first header and the size of the second header 149 uint8_t hBuffer[kBmpHeaderBytesPlusFour]; 150 if (stream->read(hBuffer, kBmpHeaderBytesPlusFour) != 151 kBmpHeaderBytesPlusFour) { 152 SkCodecPrintf("Error: unable to read first bitmap header.\n"); 153 return kIncompleteInput; 154 } 155 156 totalBytes = get_int(hBuffer, 2); 157 offset = get_int(hBuffer, 10); 158 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) { 159 SkCodecPrintf("Error: invalid starting location for pixel data\n"); 160 return kInvalidInput; 161 } 162 163 // The size of the second (info) header in bytes 164 // The size is the first field of the second header, so we have already 165 // read the first four infoBytes. 166 infoBytes = get_int(hBuffer, 14); 167 if (infoBytes < kBmpOS2V1Bytes) { 168 SkCodecPrintf("Error: invalid second header size.\n"); 169 return kInvalidInput; 170 } 171 } else { 172 // This value is only used by RLE compression. Bmp in Ico files do not 173 // use RLE. If the compression field is incorrectly signaled as RLE, 174 // we will catch this and signal an error below. 175 totalBytes = 0; 176 177 // Bmps in Ico cannot specify an offset. We will always assume that 178 // pixel data begins immediately after the color table. This value 179 // will be corrected below. 180 offset = 0; 181 182 // Read the size of the second header 183 uint8_t hBuffer[4]; 184 if (stream->read(hBuffer, 4) != 4) { 185 SkCodecPrintf("Error: unable to read size of second bitmap header.\n"); 186 return kIncompleteInput; 187 } 188 infoBytes = get_int(hBuffer, 0); 189 if (infoBytes < kBmpOS2V1Bytes) { 190 SkCodecPrintf("Error: invalid second header size.\n"); 191 return kInvalidInput; 192 } 193 } 194 195 // Determine image information depending on second header format 196 const BmpHeaderType headerType = get_header_type(infoBytes); 197 if (kUnknown_BmpHeaderType == headerType) { 198 return kInvalidInput; 199 } 200 201 // We already read the first four bytes of the info header to get the size 202 const uint32_t infoBytesRemaining = infoBytes - 4; 203 204 // Read the second header 205 std::unique_ptr<uint8_t[]> iBuffer(new uint8_t[infoBytesRemaining]); 206 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) { 207 SkCodecPrintf("Error: unable to read second bitmap header.\n"); 208 return kIncompleteInput; 209 } 210 211 // The number of bits used per pixel in the pixel data 212 uint16_t bitsPerPixel; 213 214 // The compression method for the pixel data 215 uint32_t compression = kNone_BmpCompressionMethod; 216 217 // Number of colors in the color table, defaults to 0 or max (see below) 218 uint32_t numColors = 0; 219 220 // Bytes per color in the color table, early versions use 3, most use 4 221 uint32_t bytesPerColor; 222 223 // The image width and height 224 int width, height; 225 226 switch (headerType) { 227 case kInfoV1_BmpHeaderType: 228 case kInfoV2_BmpHeaderType: 229 case kInfoV3_BmpHeaderType: 230 case kInfoV4_BmpHeaderType: 231 case kInfoV5_BmpHeaderType: 232 case kOS2VX_BmpHeaderType: 233 // We check the size of the header before entering the if statement. 234 // We should not reach this point unless the size is large enough for 235 // these required fields. 236 SkASSERT(infoBytesRemaining >= 12); 237 width = get_int(iBuffer.get(), 0); 238 height = get_int(iBuffer.get(), 4); 239 bitsPerPixel = get_short(iBuffer.get(), 10); 240 241 // Some versions do not have these fields, so we check before 242 // overwriting the default value. 243 if (infoBytesRemaining >= 16) { 244 compression = get_int(iBuffer.get(), 12); 245 if (infoBytesRemaining >= 32) { 246 numColors = get_int(iBuffer.get(), 28); 247 } 248 } 249 250 // All of the headers that reach this point, store color table entries 251 // using 4 bytes per pixel. 252 bytesPerColor = 4; 253 break; 254 case kOS2V1_BmpHeaderType: 255 // The OS2V1 is treated separately because it has a unique format 256 width = (int) get_short(iBuffer.get(), 0); 257 height = (int) get_short(iBuffer.get(), 2); 258 bitsPerPixel = get_short(iBuffer.get(), 6); 259 bytesPerColor = 3; 260 break; 261 case kUnknown_BmpHeaderType: 262 // We'll exit above in this case. 263 SkASSERT(false); 264 return kInvalidInput; 265 } 266 267 // Check for valid dimensions from header 268 SkCodec::SkScanlineOrder rowOrder = SkCodec::kBottomUp_SkScanlineOrder; 269 if (height < 0) { 270 height = -height; 271 rowOrder = SkCodec::kTopDown_SkScanlineOrder; 272 } 273 // The height field for bmp in ico is double the actual height because they 274 // contain an XOR mask followed by an AND mask 275 if (inIco) { 276 height /= 2; 277 } 278 279 // Arbitrary maximum. Matches Chromium. 280 constexpr int kMaxDim = 1 << 16; 281 if (width <= 0 || height <= 0 || width >= kMaxDim || height >= kMaxDim) { 282 SkCodecPrintf("Error: invalid bitmap dimensions.\n"); 283 return kInvalidInput; 284 } 285 286 // Create mask struct 287 SkMasks::InputMasks inputMasks; 288 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks)); 289 290 // Determine the input compression format and set bit masks if necessary 291 uint32_t maskBytes = 0; 292 BmpInputFormat inputFormat = kUnknown_BmpInputFormat; 293 switch (compression) { 294 case kNone_BmpCompressionMethod: 295 inputFormat = kStandard_BmpInputFormat; 296 297 // In addition to more standard pixel compression formats, bmp supports 298 // the use of bit masks to determine pixel components. The standard 299 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB), 300 // which does not map well to any Skia color formats. For this reason, 301 // we will always enable mask mode with 16 bits per pixel. 302 if (16 == bitsPerPixel) { 303 inputMasks.red = 0x7C00; 304 inputMasks.green = 0x03E0; 305 inputMasks.blue = 0x001F; 306 inputFormat = kBitMask_BmpInputFormat; 307 } 308 break; 309 case k8BitRLE_BmpCompressionMethod: 310 if (bitsPerPixel != 8) { 311 SkCodecPrintf("Warning: correcting invalid bitmap format.\n"); 312 bitsPerPixel = 8; 313 } 314 inputFormat = kRLE_BmpInputFormat; 315 break; 316 case k4BitRLE_BmpCompressionMethod: 317 if (bitsPerPixel != 4) { 318 SkCodecPrintf("Warning: correcting invalid bitmap format.\n"); 319 bitsPerPixel = 4; 320 } 321 inputFormat = kRLE_BmpInputFormat; 322 break; 323 case kAlphaBitMasks_BmpCompressionMethod: 324 case kBitMasks_BmpCompressionMethod: 325 // Load the masks 326 inputFormat = kBitMask_BmpInputFormat; 327 switch (headerType) { 328 case kInfoV1_BmpHeaderType: { 329 // The V1 header stores the bit masks after the header 330 uint8_t buffer[kBmpMaskBytes]; 331 if (stream->read(buffer, kBmpMaskBytes) != kBmpMaskBytes) { 332 SkCodecPrintf("Error: unable to read bit inputMasks.\n"); 333 return kIncompleteInput; 334 } 335 maskBytes = kBmpMaskBytes; 336 inputMasks.red = get_int(buffer, 0); 337 inputMasks.green = get_int(buffer, 4); 338 inputMasks.blue = get_int(buffer, 8); 339 break; 340 } 341 case kInfoV2_BmpHeaderType: 342 case kInfoV3_BmpHeaderType: 343 case kInfoV4_BmpHeaderType: 344 case kInfoV5_BmpHeaderType: 345 // Header types are matched based on size. If the header 346 // is V2+, we are guaranteed to be able to read at least 347 // this size. 348 SkASSERT(infoBytesRemaining >= 48); 349 inputMasks.red = get_int(iBuffer.get(), 36); 350 inputMasks.green = get_int(iBuffer.get(), 40); 351 inputMasks.blue = get_int(iBuffer.get(), 44); 352 353 if (kInfoV2_BmpHeaderType == headerType || 354 (kInfoV3_BmpHeaderType == headerType && !inIco)) { 355 break; 356 } 357 358 // V3+ bmp files introduce an alpha mask and allow the creator of the image 359 // to use the alpha channels. However, many of these images leave the 360 // alpha channel blank and expect to be rendered as opaque. This is the 361 // case for almost all V3 images, so we ignore the alpha mask. For V4+ 362 // images in kMask mode, we will use the alpha mask. Additionally, V3 363 // bmp-in-ico expect us to use the alpha mask. 364 // 365 // skbug.com/4116: We should perhaps also apply the alpha mask in kStandard 366 // mode. We just haven't seen any images that expect this 367 // behavior. 368 // 369 // Header types are matched based on size. If the header is 370 // V3+, we are guaranteed to be able to read at least this size. 371 SkASSERT(infoBytesRemaining > 52); 372 inputMasks.alpha = get_int(iBuffer.get(), 48); 373 break; 374 case kOS2VX_BmpHeaderType: 375 // TODO: Decide if we intend to support this. 376 // It is unsupported in the previous version and 377 // in chromium. I have not come across a test case 378 // that uses this format. 379 SkCodecPrintf("Error: huffman format unsupported.\n"); 380 return kUnimplemented; 381 default: 382 SkCodecPrintf("Error: invalid bmp bit masks header.\n"); 383 return kInvalidInput; 384 } 385 break; 386 case kJpeg_BmpCompressionMethod: 387 if (24 == bitsPerPixel) { 388 inputFormat = kRLE_BmpInputFormat; 389 break; 390 } 391 // Fall through 392 case kPng_BmpCompressionMethod: 393 // TODO: Decide if we intend to support this. 394 // It is unsupported in the previous version and 395 // in chromium. I think it is used mostly for printers. 396 SkCodecPrintf("Error: compression format not supported.\n"); 397 return kUnimplemented; 398 case kCMYK_BmpCompressionMethod: 399 case kCMYK8BitRLE_BmpCompressionMethod: 400 case kCMYK4BitRLE_BmpCompressionMethod: 401 // TODO: Same as above. 402 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n"); 403 return kUnimplemented; 404 default: 405 SkCodecPrintf("Error: invalid format for bitmap decoding.\n"); 406 return kInvalidInput; 407 } 408 iBuffer.reset(); 409 410 // Calculate the number of bytes read so far 411 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; 412 if (!inIco && offset < bytesRead) { 413 // TODO (msarett): Do we really want to fail if the offset in the header is invalid? 414 // Seems like we can just assume that the offset is zero and try to decode? 415 // Maybe we don't want to try to decode corrupt images? 416 SkCodecPrintf("Error: pixel data offset less than header size.\n"); 417 return kInvalidInput; 418 } 419 420 421 422 switch (inputFormat) { 423 case kStandard_BmpInputFormat: { 424 // BMPs are generally opaque, however BMPs-in-ICOs may contain 425 // a transparency mask after the image. Therefore, we mark the 426 // alpha as kBinary if the BMP is contained in an ICO. 427 // We use |isOpaque| to indicate if the BMP itself is opaque. 428 SkEncodedInfo::Alpha alpha = inIco ? SkEncodedInfo::kBinary_Alpha : 429 SkEncodedInfo::kOpaque_Alpha; 430 bool isOpaque = true; 431 432 SkEncodedInfo::Color color; 433 uint8_t bitsPerComponent; 434 switch (bitsPerPixel) { 435 // Palette formats 436 case 1: 437 case 2: 438 case 4: 439 case 8: 440 // In the case of ICO, kBGRA is actually the closest match, 441 // since we will need to apply a transparency mask. 442 if (inIco) { 443 color = SkEncodedInfo::kBGRA_Color; 444 bitsPerComponent = 8; 445 } else { 446 color = SkEncodedInfo::kPalette_Color; 447 bitsPerComponent = (uint8_t) bitsPerPixel; 448 } 449 break; 450 case 24: 451 // In the case of ICO, kBGRA is actually the closest match, 452 // since we will need to apply a transparency mask. 453 color = inIco ? SkEncodedInfo::kBGRA_Color : SkEncodedInfo::kBGR_Color; 454 bitsPerComponent = 8; 455 break; 456 case 32: 457 // 32-bit BMP-in-ICOs actually use the alpha channel in place of a 458 // transparency mask. 459 if (inIco) { 460 isOpaque = false; 461 alpha = SkEncodedInfo::kUnpremul_Alpha; 462 color = SkEncodedInfo::kBGRA_Color; 463 } else { 464 color = SkEncodedInfo::kBGRX_Color; 465 } 466 bitsPerComponent = 8; 467 break; 468 default: 469 SkCodecPrintf("Error: invalid input value for bits per pixel.\n"); 470 return kInvalidInput; 471 } 472 473 if (codecOut) { 474 // We require streams to have a memory base for Bmp-in-Ico decodes. 475 SkASSERT(!inIco || nullptr != stream->getMemoryBase()); 476 477 // Set the image info and create a codec. 478 const SkEncodedInfo info = SkEncodedInfo::Make(color, alpha, bitsPerComponent); 479 codecOut->reset(new SkBmpStandardCodec(width, height, info, stream, bitsPerPixel, 480 numColors, bytesPerColor, offset - bytesRead, 481 rowOrder, isOpaque, inIco)); 482 return static_cast<SkBmpStandardCodec*>(codecOut->get())->didCreateSrcBuffer() 483 ? kSuccess : kInvalidInput; 484 } 485 return kSuccess; 486 } 487 488 case kBitMask_BmpInputFormat: { 489 // Bmp-in-Ico must be standard mode 490 if (inIco) { 491 SkCodecPrintf("Error: Icos may not use bit mask format.\n"); 492 return kInvalidInput; 493 } 494 495 switch (bitsPerPixel) { 496 case 16: 497 case 24: 498 case 32: 499 break; 500 default: 501 SkCodecPrintf("Error: invalid input value for bits per pixel.\n"); 502 return kInvalidInput; 503 } 504 505 // Skip to the start of the pixel array. 506 // We can do this here because there is no color table to read 507 // in bit mask mode. 508 if (stream->skip(offset - bytesRead) != offset - bytesRead) { 509 SkCodecPrintf("Error: unable to skip to image data.\n"); 510 return kIncompleteInput; 511 } 512 513 if (codecOut) { 514 // Check that input bit masks are valid and create the masks object 515 std::unique_ptr<SkMasks> masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel)); 516 if (nullptr == masks) { 517 SkCodecPrintf("Error: invalid input masks.\n"); 518 return kInvalidInput; 519 } 520 521 // Masked bmps are not a great fit for SkEncodedInfo, since they have 522 // arbitrary component orderings and bits per component. Here we choose 523 // somewhat reasonable values - it's ok that we don't match exactly 524 // because SkBmpMaskCodec has its own mask swizzler anyway. 525 SkEncodedInfo::Color color; 526 SkEncodedInfo::Alpha alpha; 527 if (masks->getAlphaMask()) { 528 color = SkEncodedInfo::kBGRA_Color; 529 alpha = SkEncodedInfo::kUnpremul_Alpha; 530 } else { 531 color = SkEncodedInfo::kBGR_Color; 532 alpha = SkEncodedInfo::kOpaque_Alpha; 533 } 534 const SkEncodedInfo info = SkEncodedInfo::Make(color, alpha, 8); 535 codecOut->reset(new SkBmpMaskCodec(width, height, info, stream, bitsPerPixel, 536 masks.release(), rowOrder)); 537 return static_cast<SkBmpMaskCodec*>(codecOut->get())->didCreateSrcBuffer() 538 ? kSuccess : kInvalidInput; 539 } 540 return kSuccess; 541 } 542 543 case kRLE_BmpInputFormat: { 544 // We should not reach this point without a valid value of bitsPerPixel. 545 SkASSERT(4 == bitsPerPixel || 8 == bitsPerPixel || 24 == bitsPerPixel); 546 547 // Check for a valid number of total bytes when in RLE mode 548 if (totalBytes <= offset) { 549 SkCodecPrintf("Error: RLE requires valid input size.\n"); 550 return kInvalidInput; 551 } 552 553 // Bmp-in-Ico must be standard mode 554 // When inIco is true, this line cannot be reached, since we 555 // require that RLE Bmps have a valid number of totalBytes, and 556 // Icos skip the header that contains totalBytes. 557 SkASSERT(!inIco); 558 559 if (codecOut) { 560 // RLE inputs may skip pixels, leaving them as transparent. This 561 // is uncommon, but we cannot be certain that an RLE bmp will be 562 // opaque or that we will be able to represent it with a palette. 563 // For that reason, we always indicate that we are kBGRA. 564 const SkEncodedInfo info = SkEncodedInfo::Make(SkEncodedInfo::kBGRA_Color, 565 SkEncodedInfo::kBinary_Alpha, 8); 566 codecOut->reset(new SkBmpRLECodec(width, height, info, stream, bitsPerPixel, 567 numColors, bytesPerColor, offset - bytesRead, 568 rowOrder)); 569 } 570 return kSuccess; 571 } 572 default: 573 SkASSERT(false); 574 return kInvalidInput; 575 } 576 } 577 578 /* 579 * Creates a bmp decoder 580 * Reads enough of the stream to determine the image format 581 */ 582 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, Result* result, bool inIco) { 583 std::unique_ptr<SkStream> streamDeleter(stream); 584 std::unique_ptr<SkCodec> codec; 585 *result = ReadHeader(stream, inIco, &codec); 586 if (codec) { 587 // codec has taken ownership of stream, so we do not need to 588 // delete it. 589 streamDeleter.release(); 590 } 591 return kSuccess == *result ? codec.release() : nullptr; 592 } 593 594 SkBmpCodec::SkBmpCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream, 595 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder) 596 : INHERITED(width, height, info, kXformSrcColorFormat, stream, SkColorSpace::MakeSRGB()) 597 , fBitsPerPixel(bitsPerPixel) 598 , fRowOrder(rowOrder) 599 , fSrcRowBytes(SkAlign4(compute_row_bytes(width, fBitsPerPixel))) 600 , fXformBuffer(nullptr) 601 {} 602 603 bool SkBmpCodec::onRewind() { 604 return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr) == kSuccess; 605 } 606 607 int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) const { 608 if (SkCodec::kTopDown_SkScanlineOrder == fRowOrder) { 609 return y; 610 } 611 SkASSERT(SkCodec::kBottomUp_SkScanlineOrder == fRowOrder); 612 return height - y - 1; 613 } 614 615 SkCodec::Result SkBmpCodec::prepareToDecode(const SkImageInfo& dstInfo, 616 const SkCodec::Options& options) { 617 if (!conversion_possible(dstInfo, this->getInfo()) || 618 !this->initializeColorXform(dstInfo, options.fPremulBehavior)) 619 { 620 return kInvalidConversion; 621 } 622 623 return this->onPrepareToDecode(dstInfo, options); 624 } 625 626 SkCodec::Result SkBmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, 627 const SkCodec::Options& options) { 628 return prepareToDecode(dstInfo, options); 629 } 630 631 int SkBmpCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { 632 // Create a new image info representing the portion of the image to decode 633 SkImageInfo rowInfo = this->dstInfo().makeWH(this->dstInfo().width(), count); 634 635 // Decode the requested rows 636 return this->decodeRows(rowInfo, dst, rowBytes, this->options()); 637 } 638 639 bool SkBmpCodec::skipRows(int count) { 640 const size_t bytesToSkip = count * fSrcRowBytes; 641 return this->stream()->skip(bytesToSkip) == bytesToSkip; 642 } 643 644 bool SkBmpCodec::onSkipScanlines(int count) { 645 return this->skipRows(count); 646 } 647