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 "SkBmpRLECodec.h"
      9 #include "SkCodecPriv.h"
     10 #include "SkColorData.h"
     11 #include "SkStream.h"
     12 
     13 /*
     14  * Creates an instance of the decoder
     15  * Called only by NewFromStream
     16  */
     17 SkBmpRLECodec::SkBmpRLECodec(int width, int height, const SkEncodedInfo& info,
     18                              std::unique_ptr<SkStream> stream,
     19                              uint16_t bitsPerPixel, uint32_t numColors,
     20                              uint32_t bytesPerColor, uint32_t offset,
     21                              SkCodec::SkScanlineOrder rowOrder)
     22     : INHERITED(width, height, info, std::move(stream), bitsPerPixel, rowOrder)
     23     , fColorTable(nullptr)
     24     , fNumColors(numColors)
     25     , fBytesPerColor(bytesPerColor)
     26     , fOffset(offset)
     27     , fBytesBuffered(0)
     28     , fCurrRLEByte(0)
     29     , fSampleX(1)
     30 {}
     31 
     32 /*
     33  * Initiates the bitmap decode
     34  */
     35 SkCodec::Result SkBmpRLECodec::onGetPixels(const SkImageInfo& dstInfo,
     36                                            void* dst, size_t dstRowBytes,
     37                                            const Options& opts,
     38                                            int* rowsDecoded) {
     39     if (opts.fSubset) {
     40         // Subsets are not supported.
     41         return kUnimplemented;
     42     }
     43 
     44     Result result = this->prepareToDecode(dstInfo, opts);
     45     if (kSuccess != result) {
     46         return result;
     47     }
     48 
     49     // Perform the decode
     50     int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts);
     51     if (rows != dstInfo.height()) {
     52         // We set rowsDecoded equal to the height because the background has already
     53         // been filled.  RLE encodings sometimes skip pixels, so we always start by
     54         // filling the background.
     55         *rowsDecoded = dstInfo.height();
     56         return kIncompleteInput;
     57     }
     58 
     59     return kSuccess;
     60 }
     61 
     62 /*
     63  * Process the color table for the bmp input
     64  */
     65  bool SkBmpRLECodec::createColorTable(SkColorType dstColorType) {
     66     // Allocate memory for color table
     67     uint32_t colorBytes = 0;
     68     SkPMColor colorTable[256];
     69     if (this->bitsPerPixel() <= 8) {
     70         // Inform the caller of the number of colors
     71         uint32_t maxColors = 1 << this->bitsPerPixel();
     72         // Don't bother reading more than maxColors.
     73         const uint32_t numColorsToRead =
     74             fNumColors == 0 ? maxColors : SkTMin(fNumColors, maxColors);
     75 
     76         // Read the color table from the stream
     77         colorBytes = numColorsToRead * fBytesPerColor;
     78         std::unique_ptr<uint8_t[]> cBuffer(new uint8_t[colorBytes]);
     79         if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) {
     80             SkCodecPrintf("Error: unable to read color table.\n");
     81             return false;
     82         }
     83 
     84         // Fill in the color table
     85         PackColorProc packARGB = choose_pack_color_proc(false, dstColorType);
     86         uint32_t i = 0;
     87         for (; i < numColorsToRead; i++) {
     88             uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor);
     89             uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1);
     90             uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2);
     91             colorTable[i] = packARGB(0xFF, red, green, blue);
     92         }
     93 
     94         // To avoid segmentation faults on bad pixel data, fill the end of the
     95         // color table with black.  This is the same the behavior as the
     96         // chromium decoder.
     97         for (; i < maxColors; i++) {
     98             colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
     99         }
    100 
    101         // Set the color table
    102         fColorTable.reset(new SkColorTable(colorTable, maxColors));
    103     }
    104 
    105     // Check that we have not read past the pixel array offset
    106     if(fOffset < colorBytes) {
    107         // This may occur on OS 2.1 and other old versions where the color
    108         // table defaults to max size, and the bmp tries to use a smaller
    109         // color table.  This is invalid, and our decision is to indicate
    110         // an error, rather than try to guess the intended size of the
    111         // color table.
    112         SkCodecPrintf("Error: pixel data offset less than color table size.\n");
    113         return false;
    114     }
    115 
    116     // After reading the color table, skip to the start of the pixel array
    117     if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) {
    118         SkCodecPrintf("Error: unable to skip to image data.\n");
    119         return false;
    120     }
    121 
    122     // Return true on success
    123     return true;
    124 }
    125 
    126 bool SkBmpRLECodec::initializeStreamBuffer() {
    127     fBytesBuffered = this->stream()->read(fStreamBuffer, kBufferSize);
    128     if (fBytesBuffered == 0) {
    129         SkCodecPrintf("Error: could not read RLE image data.\n");
    130         return false;
    131     }
    132     fCurrRLEByte = 0;
    133     return true;
    134 }
    135 
    136 /*
    137  * @return the number of bytes remaining in the stream buffer after
    138  *         attempting to read more bytes from the stream
    139  */
    140 size_t SkBmpRLECodec::checkForMoreData() {
    141     const size_t remainingBytes = fBytesBuffered - fCurrRLEByte;
    142     uint8_t* buffer = fStreamBuffer;
    143 
    144     // We will be reusing the same buffer, starting over from the beginning.
    145     // Move any remaining bytes to the start of the buffer.
    146     // We use memmove() instead of memcpy() because there is risk that the dst
    147     // and src memory will overlap in corrupt images.
    148     memmove(buffer, SkTAddOffset<uint8_t>(buffer, fCurrRLEByte), remainingBytes);
    149 
    150     // Adjust the buffer ptr to the start of the unfilled data.
    151     buffer += remainingBytes;
    152 
    153     // Try to read additional bytes from the stream.  There are fCurrRLEByte
    154     // bytes of additional space remaining in the buffer, assuming that we
    155     // have already copied remainingBytes to the start of the buffer.
    156     size_t additionalBytes = this->stream()->read(buffer, fCurrRLEByte);
    157 
    158     // Update counters and return the number of bytes we currently have
    159     // available.  We are at the start of the buffer again.
    160     fCurrRLEByte = 0;
    161     fBytesBuffered = remainingBytes + additionalBytes;
    162     return fBytesBuffered;
    163 }
    164 
    165 /*
    166  * Set an RLE pixel using the color table
    167  */
    168 void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes,
    169                              const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
    170                              uint8_t index) {
    171     if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) {
    172         // Set the row
    173         uint32_t row = this->getDstRow(y, dstInfo.height());
    174 
    175         // Set the pixel based on destination color type
    176         const int dstX = get_dst_coord(x, fSampleX);
    177         switch (dstInfo.colorType()) {
    178             case kRGBA_8888_SkColorType:
    179             case kBGRA_8888_SkColorType: {
    180                 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dstRowBytes);
    181                 dstRow[dstX] = fColorTable->operator[](index);
    182                 break;
    183             }
    184             case kRGB_565_SkColorType: {
    185                 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRowBytes);
    186                 dstRow[dstX] = SkPixel32ToPixel16(fColorTable->operator[](index));
    187                 break;
    188             }
    189             default:
    190                 // This case should not be reached.  We should catch an invalid
    191                 // color type when we check that the conversion is possible.
    192                 SkASSERT(false);
    193                 break;
    194         }
    195     }
    196 }
    197 
    198 /*
    199  * Set an RLE pixel from R, G, B values
    200  */
    201 void SkBmpRLECodec::setRGBPixel(void* dst, size_t dstRowBytes,
    202                                 const SkImageInfo& dstInfo, uint32_t x,
    203                                 uint32_t y, uint8_t red, uint8_t green,
    204                                 uint8_t blue) {
    205     if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) {
    206         // Set the row
    207         uint32_t row = this->getDstRow(y, dstInfo.height());
    208 
    209         // Set the pixel based on destination color type
    210         const int dstX = get_dst_coord(x, fSampleX);
    211         switch (dstInfo.colorType()) {
    212             case kRGBA_8888_SkColorType: {
    213                 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dstRowBytes);
    214                 dstRow[dstX] = SkPackARGB_as_RGBA(0xFF, red, green, blue);
    215                 break;
    216             }
    217             case kBGRA_8888_SkColorType: {
    218                 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dstRowBytes);
    219                 dstRow[dstX] = SkPackARGB_as_BGRA(0xFF, red, green, blue);
    220                 break;
    221             }
    222             case kRGB_565_SkColorType: {
    223                 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRowBytes);
    224                 dstRow[dstX] = SkPack888ToRGB16(red, green, blue);
    225                 break;
    226             }
    227             default:
    228                 // This case should not be reached.  We should catch an invalid
    229                 // color type when we check that the conversion is possible.
    230                 SkASSERT(false);
    231                 break;
    232         }
    233     }
    234 }
    235 
    236 SkCodec::Result SkBmpRLECodec::onPrepareToDecode(const SkImageInfo& dstInfo,
    237         const SkCodec::Options& options) {
    238     // FIXME: Support subsets for scanline decodes.
    239     if (options.fSubset) {
    240         // Subsets are not supported.
    241         return kUnimplemented;
    242     }
    243 
    244     // Reset fSampleX. If it needs to be a value other than 1, it will get modified by
    245     // the sampler.
    246     fSampleX = 1;
    247     fLinesToSkip = 0;
    248 
    249     SkColorType colorTableColorType = dstInfo.colorType();
    250     if (this->colorXform()) {
    251         // Just set a known colorType for the colorTable.  No need to actually transform
    252         // the colors in the colorTable.
    253         colorTableColorType = kBGRA_8888_SkColorType;
    254     }
    255 
    256     // Create the color table if necessary and prepare the stream for decode
    257     // Note that if it is non-NULL, inputColorCount will be modified
    258     if (!this->createColorTable(colorTableColorType)) {
    259         SkCodecPrintf("Error: could not create color table.\n");
    260         return SkCodec::kInvalidInput;
    261     }
    262 
    263     // Initialize a buffer for encoded RLE data
    264     if (!this->initializeStreamBuffer()) {
    265         SkCodecPrintf("Error: cannot initialize stream buffer.\n");
    266         return SkCodec::kInvalidInput;
    267     }
    268 
    269     return SkCodec::kSuccess;
    270 }
    271 
    272 /*
    273  * Performs the bitmap decoding for RLE input format
    274  * RLE decoding is performed all at once, rather than a one row at a time
    275  */
    276 int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowBytes,
    277         const Options& opts) {
    278     const int width = this->getInfo().width();
    279     int height = info.height();
    280 
    281     // Account for sampling.
    282     SkImageInfo dstInfo = info.makeWH(get_scaled_dimension(width, fSampleX), height);
    283 
    284     // Set the background as transparent.  Then, if the RLE code skips pixels,
    285     // the skipped pixels will be transparent.
    286     if (dst) {
    287         SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZeroInitialized);
    288     }
    289 
    290     // Adjust the height and the dst if the previous call to decodeRows() left us
    291     // with lines that need to be skipped.
    292     if (height > fLinesToSkip) {
    293         height -= fLinesToSkip;
    294         if (dst) {
    295             dst = SkTAddOffset<void>(dst, fLinesToSkip * dstRowBytes);
    296         }
    297         fLinesToSkip = 0;
    298 
    299         dstInfo = dstInfo.makeWH(dstInfo.width(), height);
    300     } else {
    301         fLinesToSkip -= height;
    302         return height;
    303     }
    304 
    305     void* decodeDst = dst;
    306     size_t decodeRowBytes = dstRowBytes;
    307     SkImageInfo decodeInfo = dstInfo;
    308     if (decodeDst) {
    309         if (this->colorXform()) {
    310             decodeInfo = decodeInfo.makeColorType(kXformSrcColorType);
    311             if (kRGBA_F16_SkColorType == dstInfo.colorType()) {
    312                 int count = height * dstInfo.width();
    313                 this->resetXformBuffer(count);
    314                 sk_bzero(this->xformBuffer(), count * sizeof(uint32_t));
    315                 decodeDst = this->xformBuffer();
    316                 decodeRowBytes = dstInfo.width() * sizeof(uint32_t);
    317             }
    318         }
    319     }
    320 
    321     int decodedHeight = this->decodeRLE(decodeInfo, decodeDst, decodeRowBytes);
    322     if (this->colorXform() && decodeDst) {
    323         for (int y = 0; y < decodedHeight; y++) {
    324             this->applyColorXform(dst, decodeDst, dstInfo.width());
    325             decodeDst = SkTAddOffset<void>(decodeDst, decodeRowBytes);
    326             dst = SkTAddOffset<void>(dst, dstRowBytes);
    327         }
    328     }
    329 
    330     return decodedHeight;
    331 }
    332 
    333 int SkBmpRLECodec::decodeRLE(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes) {
    334     // Use the original width to count the number of pixels in each row.
    335     const int width = this->getInfo().width();
    336 
    337     // This tells us the number of rows that we are meant to decode.
    338     const int height = dstInfo.height();
    339 
    340     // Set RLE flags
    341     constexpr uint8_t RLE_ESCAPE = 0;
    342     constexpr uint8_t RLE_EOL = 0;
    343     constexpr uint8_t RLE_EOF = 1;
    344     constexpr uint8_t RLE_DELTA = 2;
    345 
    346     // Destination parameters
    347     int x = 0;
    348     int y = 0;
    349 
    350     while (true) {
    351         // If we have reached a row that is beyond the requested height, we have
    352         // succeeded.
    353         if (y >= height) {
    354             // It would be better to check for the EOF marker before indicating
    355             // success, but we may be performing a scanline decode, which
    356             // would require us to stop before decoding the full height.
    357             return height;
    358         }
    359 
    360         // Every entry takes at least two bytes
    361         if ((int) fBytesBuffered - fCurrRLEByte < 2) {
    362             if (this->checkForMoreData() < 2) {
    363                 return y;
    364             }
    365         }
    366 
    367         // Read the next two bytes.  These bytes have different meanings
    368         // depending on their values.  In the first interpretation, the first
    369         // byte is an escape flag and the second byte indicates what special
    370         // task to perform.
    371         const uint8_t flag = fStreamBuffer[fCurrRLEByte++];
    372         const uint8_t task = fStreamBuffer[fCurrRLEByte++];
    373 
    374         // Perform decoding
    375         if (RLE_ESCAPE == flag) {
    376             switch (task) {
    377                 case RLE_EOL:
    378                     x = 0;
    379                     y++;
    380                     break;
    381                 case RLE_EOF:
    382                     return height;
    383                 case RLE_DELTA: {
    384                     // Two bytes are needed to specify delta
    385                     if ((int) fBytesBuffered - fCurrRLEByte < 2) {
    386                         if (this->checkForMoreData() < 2) {
    387                             return y;
    388                         }
    389                     }
    390                     // Modify x and y
    391                     const uint8_t dx = fStreamBuffer[fCurrRLEByte++];
    392                     const uint8_t dy = fStreamBuffer[fCurrRLEByte++];
    393                     x += dx;
    394                     y += dy;
    395                     if (x > width) {
    396                         SkCodecPrintf("Warning: invalid RLE input.\n");
    397                         return y - dy;
    398                     } else if (y > height) {
    399                         fLinesToSkip = y - height;
    400                         return height;
    401                     }
    402                     break;
    403                 }
    404                 default: {
    405                     // If task does not match any of the above signals, it
    406                     // indicates that we have a sequence of non-RLE pixels.
    407                     // Furthermore, the value of task is equal to the number
    408                     // of pixels to interpret.
    409                     uint8_t numPixels = task;
    410                     const size_t rowBytes = compute_row_bytes(numPixels,
    411                             this->bitsPerPixel());
    412                     // Abort if setting numPixels moves us off the edge of the
    413                     // image.
    414                     if (x + numPixels > width) {
    415                         SkCodecPrintf("Warning: invalid RLE input.\n");
    416                         return y;
    417                     }
    418 
    419                     // Also abort if there are not enough bytes
    420                     // remaining in the stream to set numPixels.
    421 
    422                     // At most, alignedRowBytes can be 255 (max uint8_t) *
    423                     // 3 (max bytes per pixel) + 1 (aligned) = 766. If
    424                     // fStreamBuffer was smaller than this,
    425                     // checkForMoreData would never succeed for some bmps.
    426                     static_assert(255 * 3 + 1 < kBufferSize,
    427                                   "kBufferSize needs to be larger!");
    428                     const size_t alignedRowBytes = SkAlign2(rowBytes);
    429                     if ((int) fBytesBuffered - fCurrRLEByte < alignedRowBytes) {
    430                         SkASSERT(alignedRowBytes < kBufferSize);
    431                         if (this->checkForMoreData() < alignedRowBytes) {
    432                             return y;
    433                         }
    434                     }
    435                     // Set numPixels number of pixels
    436                     while (numPixels > 0) {
    437                         switch(this->bitsPerPixel()) {
    438                             case 4: {
    439                                 SkASSERT(fCurrRLEByte < fBytesBuffered);
    440                                 uint8_t val = fStreamBuffer[fCurrRLEByte++];
    441                                 setPixel(dst, dstRowBytes, dstInfo, x++,
    442                                         y, val >> 4);
    443                                 numPixels--;
    444                                 if (numPixels != 0) {
    445                                     setPixel(dst, dstRowBytes, dstInfo,
    446                                             x++, y, val & 0xF);
    447                                     numPixels--;
    448                                 }
    449                                 break;
    450                             }
    451                             case 8:
    452                                 SkASSERT(fCurrRLEByte < fBytesBuffered);
    453                                 setPixel(dst, dstRowBytes, dstInfo, x++,
    454                                         y, fStreamBuffer[fCurrRLEByte++]);
    455                                 numPixels--;
    456                                 break;
    457                             case 24: {
    458                                 SkASSERT(fCurrRLEByte + 2 < fBytesBuffered);
    459                                 uint8_t blue = fStreamBuffer[fCurrRLEByte++];
    460                                 uint8_t green = fStreamBuffer[fCurrRLEByte++];
    461                                 uint8_t red = fStreamBuffer[fCurrRLEByte++];
    462                                 setRGBPixel(dst, dstRowBytes, dstInfo,
    463                                             x++, y, red, green, blue);
    464                                 numPixels--;
    465                                 break;
    466                             }
    467                             default:
    468                                 SkASSERT(false);
    469                                 return y;
    470                         }
    471                     }
    472                     // Skip a byte if necessary to maintain alignment
    473                     if (!SkIsAlign2(rowBytes)) {
    474                         fCurrRLEByte++;
    475                     }
    476                     break;
    477                 }
    478             }
    479         } else {
    480             // If the first byte read is not a flag, it indicates the number of
    481             // pixels to set in RLE mode.
    482             const uint8_t numPixels = flag;
    483             const int endX = SkTMin<int>(x + numPixels, width);
    484 
    485             if (24 == this->bitsPerPixel()) {
    486                 // In RLE24, the second byte read is part of the pixel color.
    487                 // There are two more required bytes to finish encoding the
    488                 // color.
    489                 if ((int) fBytesBuffered - fCurrRLEByte < 2) {
    490                     if (this->checkForMoreData() < 2) {
    491                         return y;
    492                     }
    493                 }
    494 
    495                 // Fill the pixels up to endX with the specified color
    496                 uint8_t blue = task;
    497                 uint8_t green = fStreamBuffer[fCurrRLEByte++];
    498                 uint8_t red = fStreamBuffer[fCurrRLEByte++];
    499                 while (x < endX) {
    500                     setRGBPixel(dst, dstRowBytes, dstInfo, x++, y, red, green, blue);
    501                 }
    502             } else {
    503                 // In RLE8 or RLE4, the second byte read gives the index in the
    504                 // color table to look up the pixel color.
    505                 // RLE8 has one color index that gets repeated
    506                 // RLE4 has two color indexes in the upper and lower 4 bits of
    507                 // the bytes, which are alternated
    508                 uint8_t indices[2] = { task, task };
    509                 if (4 == this->bitsPerPixel()) {
    510                     indices[0] >>= 4;
    511                     indices[1] &= 0xf;
    512                 }
    513 
    514                 // Set the indicated number of pixels
    515                 for (int which = 0; x < endX; x++) {
    516                     setPixel(dst, dstRowBytes, dstInfo, x, y, indices[which]);
    517                     which = !which;
    518                 }
    519             }
    520         }
    521     }
    522 }
    523 
    524 bool SkBmpRLECodec::skipRows(int count) {
    525     const SkImageInfo rowInfo = SkImageInfo::Make(this->getInfo().width(), count, kN32_SkColorType,
    526             kUnpremul_SkAlphaType);
    527 
    528     return count == this->decodeRows(rowInfo, nullptr, 0, this->options());
    529 }
    530 
    531 // FIXME: Make SkBmpRLECodec have no knowledge of sampling.
    532 //        Or it should do all sampling natively.
    533 //        It currently is a hybrid that needs to know what SkScaledCodec is doing.
    534 class SkBmpRLESampler : public SkSampler {
    535 public:
    536     SkBmpRLESampler(SkBmpRLECodec* codec)
    537         : fCodec(codec)
    538     {
    539         SkASSERT(fCodec);
    540     }
    541 
    542 private:
    543     int onSetSampleX(int sampleX) override {
    544         return fCodec->setSampleX(sampleX);
    545     }
    546 
    547     // Unowned pointer. fCodec will delete this class in its destructor.
    548     SkBmpRLECodec* fCodec;
    549 };
    550 
    551 SkSampler* SkBmpRLECodec::getSampler(bool /*createIfNecessary*/) {
    552     // We will always create an SkBmpRLESampler if one is requested.
    553     // This allows clients to always use the SkBmpRLESampler's
    554     // version of fill(), which does nothing since RLE decodes have
    555     // already filled pixel memory.  This seems fine, since creating
    556     // an SkBmpRLESampler is pretty inexpensive.
    557     if (!fSampler) {
    558         fSampler.reset(new SkBmpRLESampler(this));
    559     }
    560 
    561     return fSampler.get();
    562 }
    563 
    564 int SkBmpRLECodec::setSampleX(int sampleX){
    565     fSampleX = sampleX;
    566     return get_scaled_dimension(this->getInfo().width(), sampleX);
    567 }
    568