Home | History | Annotate | Download | only in codec
      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) {
     71     return SkBmpCodec::NewFromStream(stream, 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) {
     79     return SkBmpCodec::NewFromStream(stream, true);
     80 }
     81 
     82 /*
     83  * Read enough of the stream to initialize the SkBmpCodec. Returns a bool
     84  * representing success or failure. If it returned true, and codecOut was
     85  * not nullptr, it will be set to a new SkBmpCodec.
     86  * Does *not* take ownership of the passed in SkStream.
     87  */
     88 bool SkBmpCodec::ReadHeader(SkStream* stream, bool inIco, SkCodec** codecOut) {
     89     // Header size constants
     90     static const uint32_t kBmpHeaderBytes = 14;
     91     static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
     92     static const uint32_t kBmpOS2V1Bytes = 12;
     93     static const uint32_t kBmpOS2V2Bytes = 64;
     94     static const uint32_t kBmpInfoBaseBytes = 16;
     95     static const uint32_t kBmpInfoV1Bytes = 40;
     96     static const uint32_t kBmpInfoV2Bytes = 52;
     97     static const uint32_t kBmpInfoV3Bytes = 56;
     98     static const uint32_t kBmpInfoV4Bytes = 108;
     99     static const uint32_t kBmpInfoV5Bytes = 124;
    100     static const uint32_t kBmpMaskBytes = 12;
    101 
    102     // The total bytes in the bmp file
    103     // We only need to use this value for RLE decoding, so we will only
    104     // check that it is valid in the RLE case.
    105     uint32_t totalBytes;
    106     // The offset from the start of the file where the pixel data begins
    107     uint32_t offset;
    108     // The size of the second (info) header in bytes
    109     uint32_t infoBytes;
    110 
    111     // Bmps embedded in Icos skip the first Bmp header
    112     if (!inIco) {
    113         // Read the first header and the size of the second header
    114         SkAutoTDeleteArray<uint8_t> hBuffer(new uint8_t[kBmpHeaderBytesPlusFour]);
    115         if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
    116                 kBmpHeaderBytesPlusFour) {
    117             SkCodecPrintf("Error: unable to read first bitmap header.\n");
    118             return false;
    119         }
    120 
    121         totalBytes = get_int(hBuffer.get(), 2);
    122         offset = get_int(hBuffer.get(), 10);
    123         if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
    124             SkCodecPrintf("Error: invalid starting location for pixel data\n");
    125             return false;
    126         }
    127 
    128         // The size of the second (info) header in bytes
    129         // The size is the first field of the second header, so we have already
    130         // read the first four infoBytes.
    131         infoBytes = get_int(hBuffer.get(), 14);
    132         if (infoBytes < kBmpOS2V1Bytes) {
    133             SkCodecPrintf("Error: invalid second header size.\n");
    134             return false;
    135         }
    136     } else {
    137         // This value is only used by RLE compression.  Bmp in Ico files do not
    138         // use RLE.  If the compression field is incorrectly signaled as RLE,
    139         // we will catch this and signal an error below.
    140         totalBytes = 0;
    141 
    142         // Bmps in Ico cannot specify an offset.  We will always assume that
    143         // pixel data begins immediately after the color table.  This value
    144         // will be corrected below.
    145         offset = 0;
    146 
    147         // Read the size of the second header
    148         SkAutoTDeleteArray<uint8_t> hBuffer(new uint8_t[4]);
    149         if (stream->read(hBuffer.get(), 4) != 4) {
    150             SkCodecPrintf("Error: unable to read size of second bitmap header.\n");
    151             return false;
    152         }
    153         infoBytes = get_int(hBuffer.get(), 0);
    154         if (infoBytes < kBmpOS2V1Bytes) {
    155             SkCodecPrintf("Error: invalid second header size.\n");
    156             return false;
    157         }
    158     }
    159 
    160     // We already read the first four bytes of the info header to get the size
    161     const uint32_t infoBytesRemaining = infoBytes - 4;
    162 
    163     // Read the second header
    164     SkAutoTDeleteArray<uint8_t> iBuffer(new uint8_t[infoBytesRemaining]);
    165     if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
    166         SkCodecPrintf("Error: unable to read second bitmap header.\n");
    167         return false;
    168     }
    169 
    170     // The number of bits used per pixel in the pixel data
    171     uint16_t bitsPerPixel;
    172 
    173     // The compression method for the pixel data
    174     uint32_t compression = kNone_BmpCompressionMethod;
    175 
    176     // Number of colors in the color table, defaults to 0 or max (see below)
    177     uint32_t numColors = 0;
    178 
    179     // Bytes per color in the color table, early versions use 3, most use 4
    180     uint32_t bytesPerColor;
    181 
    182     // The image width and height
    183     int width, height;
    184 
    185     // Determine image information depending on second header format
    186     BmpHeaderType headerType;
    187     if (infoBytes >= kBmpInfoBaseBytes) {
    188         // Check the version of the header
    189         switch (infoBytes) {
    190             case kBmpInfoV1Bytes:
    191                 headerType = kInfoV1_BmpHeaderType;
    192                 break;
    193             case kBmpInfoV2Bytes:
    194                 headerType = kInfoV2_BmpHeaderType;
    195                 break;
    196             case kBmpInfoV3Bytes:
    197                 headerType = kInfoV3_BmpHeaderType;
    198                 break;
    199             case kBmpInfoV4Bytes:
    200                 headerType = kInfoV4_BmpHeaderType;
    201                 break;
    202             case kBmpInfoV5Bytes:
    203                 headerType = kInfoV5_BmpHeaderType;
    204                 break;
    205             case 16:
    206             case 20:
    207             case 24:
    208             case 28:
    209             case 32:
    210             case 36:
    211             case 42:
    212             case 46:
    213             case 48:
    214             case 60:
    215             case kBmpOS2V2Bytes:
    216                 headerType = kOS2VX_BmpHeaderType;
    217                 break;
    218             default:
    219                 // We do not signal an error here because there is the
    220                 // possibility of new or undocumented bmp header types.  Most
    221                 // of the newer versions of bmp headers are similar to and
    222                 // build off of the older versions, so we may still be able to
    223                 // decode the bmp.
    224                 SkCodecPrintf("Warning: unknown bmp header format.\n");
    225                 headerType = kUnknown_BmpHeaderType;
    226                 break;
    227         }
    228         // We check the size of the header before entering the if statement.
    229         // We should not reach this point unless the size is large enough for
    230         // these required fields.
    231         SkASSERT(infoBytesRemaining >= 12);
    232         width = get_int(iBuffer.get(), 0);
    233         height = get_int(iBuffer.get(), 4);
    234         bitsPerPixel = get_short(iBuffer.get(), 10);
    235 
    236         // Some versions do not have these fields, so we check before
    237         // overwriting the default value.
    238         if (infoBytesRemaining >= 16) {
    239             compression = get_int(iBuffer.get(), 12);
    240             if (infoBytesRemaining >= 32) {
    241                 numColors = get_int(iBuffer.get(), 28);
    242             }
    243         }
    244 
    245         // All of the headers that reach this point, store color table entries
    246         // using 4 bytes per pixel.
    247         bytesPerColor = 4;
    248     } else if (infoBytes >= kBmpOS2V1Bytes) {
    249         // The OS2V1 is treated separately because it has a unique format
    250         headerType = kOS2V1_BmpHeaderType;
    251         width = (int) get_short(iBuffer.get(), 0);
    252         height = (int) get_short(iBuffer.get(), 2);
    253         bitsPerPixel = get_short(iBuffer.get(), 6);
    254         bytesPerColor = 3;
    255     } else {
    256         // There are no valid bmp headers
    257         SkCodecPrintf("Error: second bitmap header size is invalid.\n");
    258         return false;
    259     }
    260 
    261     // Check for valid dimensions from header
    262     SkCodec::SkScanlineOrder rowOrder = SkCodec::kBottomUp_SkScanlineOrder;
    263     if (height < 0) {
    264         height = -height;
    265         rowOrder = SkCodec::kTopDown_SkScanlineOrder;
    266     }
    267     // The height field for bmp in ico is double the actual height because they
    268     // contain an XOR mask followed by an AND mask
    269     if (inIco) {
    270         height /= 2;
    271     }
    272     if (width <= 0 || height <= 0) {
    273         // TODO: Decide if we want to disable really large bmps as well.
    274         // https://code.google.com/p/skia/issues/detail?id=3617
    275         SkCodecPrintf("Error: invalid bitmap dimensions.\n");
    276         return false;
    277     }
    278 
    279     // Create mask struct
    280     SkMasks::InputMasks inputMasks;
    281     memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
    282 
    283     // Determine the input compression format and set bit masks if necessary
    284     uint32_t maskBytes = 0;
    285     BmpInputFormat inputFormat = kUnknown_BmpInputFormat;
    286     switch (compression) {
    287         case kNone_BmpCompressionMethod:
    288             inputFormat = kStandard_BmpInputFormat;
    289             break;
    290         case k8BitRLE_BmpCompressionMethod:
    291             if (bitsPerPixel != 8) {
    292                 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
    293                 bitsPerPixel = 8;
    294             }
    295             inputFormat = kRLE_BmpInputFormat;
    296             break;
    297         case k4BitRLE_BmpCompressionMethod:
    298             if (bitsPerPixel != 4) {
    299                 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
    300                 bitsPerPixel = 4;
    301             }
    302             inputFormat = kRLE_BmpInputFormat;
    303             break;
    304         case kAlphaBitMasks_BmpCompressionMethod:
    305         case kBitMasks_BmpCompressionMethod:
    306             // Load the masks
    307             inputFormat = kBitMask_BmpInputFormat;
    308             switch (headerType) {
    309                 case kInfoV1_BmpHeaderType: {
    310                     // The V1 header stores the bit masks after the header
    311                     SkAutoTDeleteArray<uint8_t> mBuffer(new uint8_t[kBmpMaskBytes]);
    312                     if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
    313                             kBmpMaskBytes) {
    314                         SkCodecPrintf("Error: unable to read bit inputMasks.\n");
    315                         return false;
    316                     }
    317                     maskBytes = kBmpMaskBytes;
    318                     inputMasks.red = get_int(mBuffer.get(), 0);
    319                     inputMasks.green = get_int(mBuffer.get(), 4);
    320                     inputMasks.blue = get_int(mBuffer.get(), 8);
    321                     break;
    322                 }
    323                 case kInfoV2_BmpHeaderType:
    324                 case kInfoV3_BmpHeaderType:
    325                 case kInfoV4_BmpHeaderType:
    326                 case kInfoV5_BmpHeaderType:
    327                     // Header types are matched based on size.  If the header
    328                     // is V2+, we are guaranteed to be able to read at least
    329                     // this size.
    330                     SkASSERT(infoBytesRemaining >= 48);
    331                     inputMasks.red = get_int(iBuffer.get(), 36);
    332                     inputMasks.green = get_int(iBuffer.get(), 40);
    333                     inputMasks.blue = get_int(iBuffer.get(), 44);
    334                     break;
    335                 case kOS2VX_BmpHeaderType:
    336                     // TODO: Decide if we intend to support this.
    337                     //       It is unsupported in the previous version and
    338                     //       in chromium.  I have not come across a test case
    339                     //       that uses this format.
    340                     SkCodecPrintf("Error: huffman format unsupported.\n");
    341                     return false;
    342                 default:
    343                    SkCodecPrintf("Error: invalid bmp bit masks header.\n");
    344                    return false;
    345             }
    346             break;
    347         case kJpeg_BmpCompressionMethod:
    348             if (24 == bitsPerPixel) {
    349                 inputFormat = kRLE_BmpInputFormat;
    350                 break;
    351             }
    352             // Fall through
    353         case kPng_BmpCompressionMethod:
    354             // TODO: Decide if we intend to support this.
    355             //       It is unsupported in the previous version and
    356             //       in chromium.  I think it is used mostly for printers.
    357             SkCodecPrintf("Error: compression format not supported.\n");
    358             return false;
    359         case kCMYK_BmpCompressionMethod:
    360         case kCMYK8BitRLE_BmpCompressionMethod:
    361         case kCMYK4BitRLE_BmpCompressionMethod:
    362             // TODO: Same as above.
    363             SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n");
    364             return false;
    365         default:
    366             SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
    367             return false;
    368     }
    369 
    370     // Most versions of bmps should be rendered as opaque.  Either they do
    371     // not have an alpha channel, or they expect the alpha channel to be
    372     // ignored.  V3+ bmp files introduce an alpha mask and allow the creator
    373     // of the image to use the alpha channels.  However, many of these images
    374     // leave the alpha channel blank and expect to be rendered as opaque.  This
    375     // is the case for almost all V3 images, so we render these as opaque.  For
    376     // V4+ images in kMask mode, we will use the alpha mask.
    377     //
    378     // skbug.com/4116: We should perhaps also apply the alpha mask in kStandard
    379     //                 mode.  We just haven't seen any images that expect this
    380     //                 behavior.
    381     //
    382     // Additionally, V3 bmp-in-ico may use the alpha mask.
    383     SkAlphaType alphaType = kOpaque_SkAlphaType;
    384     if ((kInfoV3_BmpHeaderType == headerType && inIco) ||
    385             kInfoV4_BmpHeaderType == headerType ||
    386             kInfoV5_BmpHeaderType == headerType) {
    387         // Header types are matched based on size.  If the header is
    388         // V3+, we are guaranteed to be able to read at least this size.
    389         SkASSERT(infoBytesRemaining > 52);
    390         inputMasks.alpha = get_int(iBuffer.get(), 48);
    391         if (inputMasks.alpha != 0) {
    392             alphaType = kUnpremul_SkAlphaType;
    393         }
    394     }
    395     iBuffer.free();
    396 
    397     // Additionally, 32 bit bmp-in-icos use the alpha channel.
    398     // FIXME (msarett): Don't all bmp-in-icos use the alpha channel?
    399     // And, RLE inputs may skip pixels, leaving them as transparent.  This
    400     // is uncommon, but we cannot be certain that an RLE bmp will be opaque.
    401     if ((inIco && 32 == bitsPerPixel) || (kRLE_BmpInputFormat == inputFormat)) {
    402         alphaType = kUnpremul_SkAlphaType;
    403     }
    404 
    405     // Check for valid bits per pixel.
    406     // At the same time, use this information to choose a suggested color type
    407     // and to set default masks.
    408     SkColorType colorType = kN32_SkColorType;
    409     switch (bitsPerPixel) {
    410         // In addition to more standard pixel compression formats, bmp supports
    411         // the use of bit masks to determine pixel components.  The standard
    412         // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
    413         // which does not map well to any Skia color formats.  For this reason,
    414         // we will always enable mask mode with 16 bits per pixel.
    415         case 16:
    416             if (kBitMask_BmpInputFormat != inputFormat) {
    417                 inputMasks.red = 0x7C00;
    418                 inputMasks.green = 0x03E0;
    419                 inputMasks.blue = 0x001F;
    420                 inputFormat = kBitMask_BmpInputFormat;
    421             }
    422             break;
    423         // We want to decode to kIndex_8 for input formats that are already
    424         // designed in index format.
    425         case 1:
    426         case 2:
    427         case 4:
    428         case 8:
    429             // However, we cannot in RLE format since we may need to leave some
    430             // pixels as transparent.  Similarly, we also cannot for ICO images
    431             // since we may need to apply a transparent mask.
    432             if (kRLE_BmpInputFormat != inputFormat && !inIco) {
    433                 colorType = kIndex_8_SkColorType;
    434             }
    435 
    436             // Mask bmps must have 16, 24, or 32 bits per pixel.
    437             if (kBitMask_BmpInputFormat == inputFormat) {
    438                 SkCodecPrintf("Error: invalid input value of bits per pixel for mask bmp.\n");
    439                 return false;
    440             }
    441         case 24:
    442         case 32:
    443             break;
    444         default:
    445             SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
    446             return false;
    447     }
    448 
    449     // Check that input bit masks are valid and create the masks object
    450     SkAutoTDelete<SkMasks>
    451             masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
    452     if (nullptr == masks) {
    453         SkCodecPrintf("Error: invalid input masks.\n");
    454         return false;
    455     }
    456 
    457     // Check for a valid number of total bytes when in RLE mode
    458     if (totalBytes <= offset && kRLE_BmpInputFormat == inputFormat) {
    459         SkCodecPrintf("Error: RLE requires valid input size.\n");
    460         return false;
    461     }
    462     const size_t RLEBytes = totalBytes - offset;
    463 
    464     // Calculate the number of bytes read so far
    465     const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
    466     if (!inIco && offset < bytesRead) {
    467         // TODO (msarett): Do we really want to fail if the offset in the header is invalid?
    468         //                 Seems like we can just assume that the offset is zero and try to decode?
    469         //                 Maybe we don't want to try to decode corrupt images?
    470         SkCodecPrintf("Error: pixel data offset less than header size.\n");
    471         return false;
    472     }
    473 
    474     // Skip to the start of the pixel array.
    475     // We can do this here because there is no color table to read
    476     // in bit mask mode.
    477     if (!inIco && kBitMask_BmpInputFormat == inputFormat) {
    478         if (stream->skip(offset - bytesRead) != offset - bytesRead) {
    479             SkCodecPrintf("Error: unable to skip to image data.\n");
    480             return false;
    481         }
    482     }
    483 
    484     if (codecOut) {
    485         // BMPs-in-ICOs contain an alpha mask after the image which means we
    486         // cannot guarantee that an image is opaque, even if the bmp thinks
    487         // it is.
    488         bool isOpaque = kOpaque_SkAlphaType == alphaType;
    489         if (inIco) {
    490             alphaType = kUnpremul_SkAlphaType;
    491         }
    492 
    493         // Set the image info
    494         const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
    495                 colorType, alphaType);
    496 
    497         // Return the codec
    498         switch (inputFormat) {
    499             case kStandard_BmpInputFormat:
    500                 // We require streams to have a memory base for Bmp-in-Ico decodes.
    501                 SkASSERT(!inIco || nullptr != stream->getMemoryBase());
    502                 *codecOut = new SkBmpStandardCodec(imageInfo, stream, bitsPerPixel, numColors,
    503                         bytesPerColor, offset - bytesRead, rowOrder, isOpaque, inIco);
    504                 return true;
    505             case kBitMask_BmpInputFormat:
    506                 // Bmp-in-Ico must be standard mode
    507                 if (inIco) {
    508                     SkCodecPrintf("Error: Icos may not use bit mask format.\n");
    509                     return false;
    510                 }
    511 
    512                 *codecOut = new SkBmpMaskCodec(imageInfo, stream, bitsPerPixel, masks.detach(),
    513                         rowOrder);
    514                 return true;
    515             case kRLE_BmpInputFormat:
    516                 // Bmp-in-Ico must be standard mode
    517                 // When inIco is true, this line cannot be reached, since we
    518                 // require that RLE Bmps have a valid number of totalBytes, and
    519                 // Icos skip the header that contains totalBytes.
    520                 SkASSERT(!inIco);
    521                 *codecOut = new SkBmpRLECodec(imageInfo, stream, bitsPerPixel, numColors,
    522                         bytesPerColor, offset - bytesRead, rowOrder, RLEBytes);
    523                 return true;
    524             default:
    525                 SkASSERT(false);
    526                 return false;
    527         }
    528     }
    529 
    530     return true;
    531 }
    532 
    533 /*
    534  * Creates a bmp decoder
    535  * Reads enough of the stream to determine the image format
    536  */
    537 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool inIco) {
    538     SkAutoTDelete<SkStream> streamDeleter(stream);
    539     SkCodec* codec = nullptr;
    540     if (ReadHeader(stream, inIco, &codec)) {
    541         // codec has taken ownership of stream, so we do not need to
    542         // delete it.
    543         SkASSERT(codec);
    544         streamDeleter.detach();
    545         return codec;
    546     }
    547     return nullptr;
    548 }
    549 
    550 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
    551         uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder)
    552     : INHERITED(info, stream)
    553     , fBitsPerPixel(bitsPerPixel)
    554     , fRowOrder(rowOrder)
    555     , fSrcRowBytes(SkAlign4(compute_row_bytes(info.width(), fBitsPerPixel)))
    556 {}
    557 
    558 bool SkBmpCodec::onRewind() {
    559     return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr);
    560 }
    561 
    562 int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) const {
    563     if (SkCodec::kTopDown_SkScanlineOrder == fRowOrder) {
    564         return y;
    565     }
    566     SkASSERT(SkCodec::kBottomUp_SkScanlineOrder == fRowOrder);
    567     return height - y - 1;
    568 }
    569 
    570 SkCodec::Result SkBmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
    571         const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) {
    572     if (!conversion_possible(dstInfo, this->getInfo())) {
    573         SkCodecPrintf("Error: cannot convert input type to output type.\n");
    574         return kInvalidConversion;
    575     }
    576 
    577     return prepareToDecode(dstInfo, options, inputColorPtr, inputColorCount);
    578 }
    579 
    580 int SkBmpCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
    581     // Create a new image info representing the portion of the image to decode
    582     SkImageInfo rowInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);
    583 
    584     // Decode the requested rows
    585     return this->decodeRows(rowInfo, dst, rowBytes, this->options());
    586 }
    587 
    588 bool SkBmpCodec::skipRows(int count) {
    589     const size_t bytesToSkip = count * fSrcRowBytes;
    590     return this->stream()->skip(bytesToSkip) == bytesToSkip;
    591 }
    592 
    593 bool SkBmpCodec::onSkipScanlines(int count) {
    594     return this->skipRows(count);
    595 }
    596