14ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett/* 24ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * Copyright 2015 Google Inc. 34ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * 44ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * Use of this source code is governed by a BSD-style license that can be 54ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * found in the LICENSE file. 64ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett */ 74ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 84ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett#include "SkBmpRLECodec.h" 94ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett#include "SkCodecPriv.h" 10a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.h" 114ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett#include "SkStream.h" 124ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 134ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett/* 144ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * Creates an instance of the decoder 154ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * Called only by NewFromStream 164ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett */ 17ede7bac43fbc69b9fdf1c178890ba6353f5bb140Mike ReedSkBmpRLECodec::SkBmpRLECodec(int width, int height, const SkEncodedInfo& info, 18ede7bac43fbc69b9fdf1c178890ba6353f5bb140Mike Reed std::unique_ptr<SkStream> stream, 195406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett uint16_t bitsPerPixel, uint32_t numColors, 205406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett uint32_t bytesPerColor, uint32_t offset, 21b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III SkCodec::SkScanlineOrder rowOrder) 22ede7bac43fbc69b9fdf1c178890ba6353f5bb140Mike Reed : INHERITED(width, height, info, std::move(stream), bitsPerPixel, rowOrder) 2396fcdcc219d2a0d3579719b84b28bede76efba64halcanary , fColorTable(nullptr) 24886e5e41db5d6d42368f225785013c9308dc66bcbenjaminwagner , fNumColors(numColors) 254ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett , fBytesPerColor(bytesPerColor) 264ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett , fOffset(offset) 27b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III , fBytesBuffered(0) 285406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett , fCurrRLEByte(0) 295406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett , fSampleX(1) 305406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett{} 314ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 324ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett/* 334ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * Initiates the bitmap decode 344ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett */ 354ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarettSkCodec::Result SkBmpRLECodec::onGetPixels(const SkImageInfo& dstInfo, 365406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett void* dst, size_t dstRowBytes, 375406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett const Options& opts, 38e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett int* rowsDecoded) { 394ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if (opts.fSubset) { 404ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Subsets are not supported. 414ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett return kUnimplemented; 424ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 434ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 44571b30f6117eede6d64cd2b924dc1f6aaa59e70eLeon Scroggins Result result = this->prepareToDecode(dstInfo, opts); 455406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett if (kSuccess != result) { 465406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett return result; 474ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 484ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 494ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Perform the decode 50f724b99435e0c7a6a95112229cc44a2ba813ecc9msarett int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts); 51e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett if (rows != dstInfo.height()) { 52e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett // We set rowsDecoded equal to the height because the background has already 53e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett // been filled. RLE encodings sometimes skip pixels, so we always start by 54e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett // filling the background. 55e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett *rowsDecoded = dstInfo.height(); 56e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett return kIncompleteInput; 57e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett } 58e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett 59e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett return kSuccess; 604ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett} 614ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 624ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett/* 634ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * Process the color table for the bmp input 644ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett */ 65571b30f6117eede6d64cd2b924dc1f6aaa59e70eLeon Scroggins bool SkBmpRLECodec::createColorTable(SkColorType dstColorType) { 664ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Allocate memory for color table 674ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint32_t colorBytes = 0; 684ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett SkPMColor colorTable[256]; 694ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if (this->bitsPerPixel() <= 8) { 704ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Inform the caller of the number of colors 714ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint32_t maxColors = 1 << this->bitsPerPixel(); 72886e5e41db5d6d42368f225785013c9308dc66bcbenjaminwagner // Don't bother reading more than maxColors. 73886e5e41db5d6d42368f225785013c9308dc66bcbenjaminwagner const uint32_t numColorsToRead = 74886e5e41db5d6d42368f225785013c9308dc66bcbenjaminwagner fNumColors == 0 ? maxColors : SkTMin(fNumColors, maxColors); 754ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 764ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Read the color table from the stream 77886e5e41db5d6d42368f225785013c9308dc66bcbenjaminwagner colorBytes = numColorsToRead * fBytesPerColor; 787ecc59610de72043e9b7ebaf1ef45c43425e54fcBen Wagner std::unique_ptr<uint8_t[]> cBuffer(new uint8_t[colorBytes]); 794ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { 804ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett SkCodecPrintf("Error: unable to read color table.\n"); 814ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett return false; 824ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 834ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 844ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Fill in the color table 8534e0ec40b10320765d4a4432f56e090556f9c75emsarett PackColorProc packARGB = choose_pack_color_proc(false, dstColorType); 864ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint32_t i = 0; 87886e5e41db5d6d42368f225785013c9308dc66bcbenjaminwagner for (; i < numColorsToRead; i++) { 884ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor); 894ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1); 904ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2); 9134e0ec40b10320765d4a4432f56e090556f9c75emsarett colorTable[i] = packARGB(0xFF, red, green, blue); 924ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 934ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 944ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // To avoid segmentation faults on bad pixel data, fill the end of the 954ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // color table with black. This is the same the behavior as the 964ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // chromium decoder. 974ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett for (; i < maxColors; i++) { 984ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); 994ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 1004ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 1014ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Set the color table 102385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary fColorTable.reset(new SkColorTable(colorTable, maxColors)); 1034ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 1044ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 1054ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Check that we have not read past the pixel array offset 1064ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if(fOffset < colorBytes) { 1074ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // This may occur on OS 2.1 and other old versions where the color 1084ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // table defaults to max size, and the bmp tries to use a smaller 1094ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // color table. This is invalid, and our decision is to indicate 1104ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // an error, rather than try to guess the intended size of the 1114ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // color table. 1124ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett SkCodecPrintf("Error: pixel data offset less than color table size.\n"); 1134ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett return false; 1144ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 1154ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 1164ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // After reading the color table, skip to the start of the pixel array 1174ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { 1184ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett SkCodecPrintf("Error: unable to skip to image data.\n"); 1194ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett return false; 1204ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 1214ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 1224ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Return true on success 1234ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett return true; 1244ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett} 1254ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 1264ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarettbool SkBmpRLECodec::initializeStreamBuffer() { 127b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III fBytesBuffered = this->stream()->read(fStreamBuffer, kBufferSize); 128b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III if (fBytesBuffered == 0) { 1294ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett SkCodecPrintf("Error: could not read RLE image data.\n"); 1304ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett return false; 1314ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 1325406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett fCurrRLEByte = 0; 1334ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett return true; 1344ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett} 1354ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 1364ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett/* 137d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett * @return the number of bytes remaining in the stream buffer after 138d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett * attempting to read more bytes from the stream 139d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett */ 140d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarettsize_t SkBmpRLECodec::checkForMoreData() { 141b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III const size_t remainingBytes = fBytesBuffered - fCurrRLEByte; 142b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III uint8_t* buffer = fStreamBuffer; 143d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett 144d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // We will be reusing the same buffer, starting over from the beginning. 145d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // Move any remaining bytes to the start of the buffer. 146d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // We use memmove() instead of memcpy() because there is risk that the dst 147d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // and src memory will overlap in corrupt images. 148d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett memmove(buffer, SkTAddOffset<uint8_t>(buffer, fCurrRLEByte), remainingBytes); 149d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett 150d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // Adjust the buffer ptr to the start of the unfilled data. 151d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett buffer += remainingBytes; 152d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett 153d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // Try to read additional bytes from the stream. There are fCurrRLEByte 154d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // bytes of additional space remaining in the buffer, assuming that we 155d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // have already copied remainingBytes to the start of the buffer. 156d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett size_t additionalBytes = this->stream()->read(buffer, fCurrRLEByte); 157d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett 158d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // Update counters and return the number of bytes we currently have 159d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // available. We are at the start of the buffer again. 160d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett fCurrRLEByte = 0; 161b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III fBytesBuffered = remainingBytes + additionalBytes; 162b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III return fBytesBuffered; 163d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett} 164d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett 165d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett/* 1664ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * Set an RLE pixel using the color table 1674ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett */ 1684ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarettvoid SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes, 1694ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett const SkImageInfo& dstInfo, uint32_t x, uint32_t y, 1704ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint8_t index) { 1719b9497ef14f23562a95afe989d1efe41c603a6f6msarett if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) { 1725406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // Set the row 1735406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett uint32_t row = this->getDstRow(y, dstInfo.height()); 1744ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 1755406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // Set the pixel based on destination color type 1765406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett const int dstX = get_dst_coord(x, fSampleX); 1775406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett switch (dstInfo.colorType()) { 17834e0ec40b10320765d4a4432f56e090556f9c75emsarett case kRGBA_8888_SkColorType: 17934e0ec40b10320765d4a4432f56e090556f9c75emsarett case kBGRA_8888_SkColorType: { 1805406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dstRowBytes); 1815406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett dstRow[dstX] = fColorTable->operator[](index); 1825406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett break; 1835406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett } 1845406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett case kRGB_565_SkColorType: { 1855406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRowBytes); 1865406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett dstRow[dstX] = SkPixel32ToPixel16(fColorTable->operator[](index)); 1875406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett break; 1885406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett } 1895406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett default: 1905406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // This case should not be reached. We should catch an invalid 1915406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // color type when we check that the conversion is possible. 1925406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett SkASSERT(false); 1935406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett break; 1944ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 1954ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 1964ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett} 1974ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 1984ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett/* 1994ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * Set an RLE pixel from R, G, B values 2004ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett */ 2014ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarettvoid SkBmpRLECodec::setRGBPixel(void* dst, size_t dstRowBytes, 2024ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett const SkImageInfo& dstInfo, uint32_t x, 2034ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint32_t y, uint8_t red, uint8_t green, 2044ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint8_t blue) { 2059b9497ef14f23562a95afe989d1efe41c603a6f6msarett if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) { 2065406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // Set the row 2075406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett uint32_t row = this->getDstRow(y, dstInfo.height()); 2084ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 2095406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // Set the pixel based on destination color type 2105406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett const int dstX = get_dst_coord(x, fSampleX); 2115406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett switch (dstInfo.colorType()) { 21234e0ec40b10320765d4a4432f56e090556f9c75emsarett case kRGBA_8888_SkColorType: { 2135406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dstRowBytes); 21434e0ec40b10320765d4a4432f56e090556f9c75emsarett dstRow[dstX] = SkPackARGB_as_RGBA(0xFF, red, green, blue); 21534e0ec40b10320765d4a4432f56e090556f9c75emsarett break; 21634e0ec40b10320765d4a4432f56e090556f9c75emsarett } 21734e0ec40b10320765d4a4432f56e090556f9c75emsarett case kBGRA_8888_SkColorType: { 21834e0ec40b10320765d4a4432f56e090556f9c75emsarett SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dstRowBytes); 21934e0ec40b10320765d4a4432f56e090556f9c75emsarett dstRow[dstX] = SkPackARGB_as_BGRA(0xFF, red, green, blue); 2205406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett break; 2215406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett } 2225406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett case kRGB_565_SkColorType: { 2235406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRowBytes); 2245406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett dstRow[dstX] = SkPack888ToRGB16(red, green, blue); 2255406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett break; 2265406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett } 2275406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett default: 2285406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // This case should not be reached. We should catch an invalid 2295406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // color type when we check that the conversion is possible. 2305406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett SkASSERT(false); 2315406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett break; 232cc2feb161f756c4035a407296567654d86bc7be7scroggo } 2334ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 2344ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett} 2354ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 2361b96c6f91377431cd407c43fedac613fff21c2edMatt SarettSkCodec::Result SkBmpRLECodec::onPrepareToDecode(const SkImageInfo& dstInfo, 237571b30f6117eede6d64cd2b924dc1f6aaa59e70eLeon Scroggins const SkCodec::Options& options) { 238fdb47571a3b5e72469b67de44e32ac14d9352ab4msarett // FIXME: Support subsets for scanline decodes. 239fdb47571a3b5e72469b67de44e32ac14d9352ab4msarett if (options.fSubset) { 240fdb47571a3b5e72469b67de44e32ac14d9352ab4msarett // Subsets are not supported. 241fdb47571a3b5e72469b67de44e32ac14d9352ab4msarett return kUnimplemented; 242fdb47571a3b5e72469b67de44e32ac14d9352ab4msarett } 243fdb47571a3b5e72469b67de44e32ac14d9352ab4msarett 244e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo // Reset fSampleX. If it needs to be a value other than 1, it will get modified by 245e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo // the sampler. 246e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo fSampleX = 1; 2474946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett fLinesToSkip = 0; 2484946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett 2491a85ca5c908b421ea8f07798d56c4481bbc5d5afMatt Sarett SkColorType colorTableColorType = dstInfo.colorType(); 2501a85ca5c908b421ea8f07798d56c4481bbc5d5afMatt Sarett if (this->colorXform()) { 2511a85ca5c908b421ea8f07798d56c4481bbc5d5afMatt Sarett // Just set a known colorType for the colorTable. No need to actually transform 252571b30f6117eede6d64cd2b924dc1f6aaa59e70eLeon Scroggins // the colors in the colorTable. 2531a85ca5c908b421ea8f07798d56c4481bbc5d5afMatt Sarett colorTableColorType = kBGRA_8888_SkColorType; 2541a85ca5c908b421ea8f07798d56c4481bbc5d5afMatt Sarett } 2551a85ca5c908b421ea8f07798d56c4481bbc5d5afMatt Sarett 2565406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // Create the color table if necessary and prepare the stream for decode 2575406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // Note that if it is non-NULL, inputColorCount will be modified 258571b30f6117eede6d64cd2b924dc1f6aaa59e70eLeon Scroggins if (!this->createColorTable(colorTableColorType)) { 2595406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett SkCodecPrintf("Error: could not create color table.\n"); 2605406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett return SkCodec::kInvalidInput; 2615406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett } 2625406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett 2635406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett // Initialize a buffer for encoded RLE data 2645406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett if (!this->initializeStreamBuffer()) { 2655406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett SkCodecPrintf("Error: cannot initialize stream buffer.\n"); 2662a98bac9cbc6ad657de09bafd2ca7e83422a2877msarett return SkCodec::kInvalidInput; 2675406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett } 2685406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett 2695406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett return SkCodec::kSuccess; 2705406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett} 2715406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett 2724ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett/* 2734ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * Performs the bitmap decoding for RLE input format 2744ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett * RLE decoding is performed all at once, rather than a one row at a time 2754ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett */ 276e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarettint SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowBytes, 277e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett const Options& opts) { 2785406d6f39ad042e7a0a0d4ea16beca4fe2b66492msarett const int width = this->getInfo().width(); 2794946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett int height = info.height(); 280e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo 2816193568fed3983e406544a46a5e1fd292729ca84Matt Sarett // Account for sampling. 2826193568fed3983e406544a46a5e1fd292729ca84Matt Sarett SkImageInfo dstInfo = info.makeWH(get_scaled_dimension(width, fSampleX), height); 2836193568fed3983e406544a46a5e1fd292729ca84Matt Sarett 2846193568fed3983e406544a46a5e1fd292729ca84Matt Sarett // Set the background as transparent. Then, if the RLE code skips pixels, 2856193568fed3983e406544a46a5e1fd292729ca84Matt Sarett // the skipped pixels will be transparent. 2866193568fed3983e406544a46a5e1fd292729ca84Matt Sarett if (dst) { 2876193568fed3983e406544a46a5e1fd292729ca84Matt Sarett SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZeroInitialized); 2886193568fed3983e406544a46a5e1fd292729ca84Matt Sarett } 2896193568fed3983e406544a46a5e1fd292729ca84Matt Sarett 2904946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett // Adjust the height and the dst if the previous call to decodeRows() left us 2914946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett // with lines that need to be skipped. 2924946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett if (height > fLinesToSkip) { 2934946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett height -= fLinesToSkip; 2941b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett if (dst) { 2951b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett dst = SkTAddOffset<void>(dst, fLinesToSkip * dstRowBytes); 2961b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett } 2974946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett fLinesToSkip = 0; 2981b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett 2991b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett dstInfo = dstInfo.makeWH(dstInfo.width(), height); 3004946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett } else { 3014946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett fLinesToSkip -= height; 3024946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett return height; 3034946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett } 3044946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett 3051b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett void* decodeDst = dst; 3061b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett size_t decodeRowBytes = dstRowBytes; 3071b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett SkImageInfo decodeInfo = dstInfo; 3081b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett if (decodeDst) { 3091b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett if (this->colorXform()) { 310562e681e5c600e919c3b57201b85776c4789f5aaMatt Sarett decodeInfo = decodeInfo.makeColorType(kXformSrcColorType); 3111b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett if (kRGBA_F16_SkColorType == dstInfo.colorType()) { 3121b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett int count = height * dstInfo.width(); 3131b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett this->resetXformBuffer(count); 3141b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett sk_bzero(this->xformBuffer(), count * sizeof(uint32_t)); 3151b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett decodeDst = this->xformBuffer(); 3161b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett decodeRowBytes = dstInfo.width() * sizeof(uint32_t); 3171b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett } 3181b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett } 3191b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett } 3201b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett 3211b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett int decodedHeight = this->decodeRLE(decodeInfo, decodeDst, decodeRowBytes); 3221b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett if (this->colorXform() && decodeDst) { 3231b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett for (int y = 0; y < decodedHeight; y++) { 324c6e6a5f45e54006e861275a6d5c165830f403dcdLeon Scroggins III this->applyColorXform(dst, decodeDst, dstInfo.width()); 3251b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett decodeDst = SkTAddOffset<void>(decodeDst, decodeRowBytes); 3261b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett dst = SkTAddOffset<void>(dst, dstRowBytes); 3271b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett } 3281b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett } 3291b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett 3301b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett return decodedHeight; 3311b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett} 3321b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett 3331b96c6f91377431cd407c43fedac613fff21c2edMatt Sarettint SkBmpRLECodec::decodeRLE(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes) { 3341b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett // Use the original width to count the number of pixels in each row. 3351b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett const int width = this->getInfo().width(); 3361b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett 3371b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett // This tells us the number of rows that we are meant to decode. 3381b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett const int height = dstInfo.height(); 3391b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett 3401b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett // Set RLE flags 341862c19675edb26ed7cba56ae6ca9f98c1e4cbef1Leon Scroggins III constexpr uint8_t RLE_ESCAPE = 0; 342862c19675edb26ed7cba56ae6ca9f98c1e4cbef1Leon Scroggins III constexpr uint8_t RLE_EOL = 0; 343862c19675edb26ed7cba56ae6ca9f98c1e4cbef1Leon Scroggins III constexpr uint8_t RLE_EOF = 1; 344862c19675edb26ed7cba56ae6ca9f98c1e4cbef1Leon Scroggins III constexpr uint8_t RLE_DELTA = 2; 3451b96c6f91377431cd407c43fedac613fff21c2edMatt Sarett 3464946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett // Destination parameters 3474946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett int x = 0; 3484946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett int y = 0; 3494946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett 3504ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett while (true) { 3514ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // If we have reached a row that is beyond the requested height, we have 3524ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // succeeded. 3534ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if (y >= height) { 354e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett // It would be better to check for the EOF marker before indicating 3554ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // success, but we may be performing a scanline decode, which 356e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett // would require us to stop before decoding the full height. 357e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett return height; 3584ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 3594ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 3604ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Every entry takes at least two bytes 361b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III if ((int) fBytesBuffered - fCurrRLEByte < 2) { 362d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett if (this->checkForMoreData() < 2) { 363e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett return y; 364d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett } 3654ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 3664ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 3674ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Read the next two bytes. These bytes have different meanings 3684ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // depending on their values. In the first interpretation, the first 3694ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // byte is an escape flag and the second byte indicates what special 3704ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // task to perform. 371b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III const uint8_t flag = fStreamBuffer[fCurrRLEByte++]; 372b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III const uint8_t task = fStreamBuffer[fCurrRLEByte++]; 3734ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 3744ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Perform decoding 3754ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if (RLE_ESCAPE == flag) { 3764ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett switch (task) { 3774ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett case RLE_EOL: 3784ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett x = 0; 3794ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett y++; 3804ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett break; 3814ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett case RLE_EOF: 382a37662937cb0a44b5d75a9240cfa9587b4d60e9cmsarett return height; 3834ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett case RLE_DELTA: { 3844ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Two bytes are needed to specify delta 385b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III if ((int) fBytesBuffered - fCurrRLEByte < 2) { 386d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett if (this->checkForMoreData() < 2) { 387e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett return y; 388d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett } 3894ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 3904ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Modify x and y 391b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III const uint8_t dx = fStreamBuffer[fCurrRLEByte++]; 392b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III const uint8_t dy = fStreamBuffer[fCurrRLEByte++]; 3934ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett x += dx; 3944ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett y += dy; 3954946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett if (x > width) { 396d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett SkCodecPrintf("Warning: invalid RLE input.\n"); 397e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett return y - dy; 3984946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett } else if (y > height) { 3994946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett fLinesToSkip = y - height; 4004946b9419f650ef7a2dc684ce98bb771e1ce8f40msarett return height; 4014ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4024ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett break; 4034ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4044ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett default: { 4054ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // If task does not match any of the above signals, it 4064ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // indicates that we have a sequence of non-RLE pixels. 4074ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Furthermore, the value of task is equal to the number 4084ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // of pixels to interpret. 4094ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint8_t numPixels = task; 4104ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett const size_t rowBytes = compute_row_bytes(numPixels, 4114ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett this->bitsPerPixel()); 4124ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Abort if setting numPixels moves us off the edge of the 413d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // image. 414d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett if (x + numPixels > width) { 415d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett SkCodecPrintf("Warning: invalid RLE input.\n"); 416e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett return y; 417d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett } 418b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III 419d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett // Also abort if there are not enough bytes 4204ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // remaining in the stream to set numPixels. 421b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III 422b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III // At most, alignedRowBytes can be 255 (max uint8_t) * 423b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III // 3 (max bytes per pixel) + 1 (aligned) = 766. If 424b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III // fStreamBuffer was smaller than this, 425b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III // checkForMoreData would never succeed for some bmps. 426b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III static_assert(255 * 3 + 1 < kBufferSize, 427b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III "kBufferSize needs to be larger!"); 428b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III const size_t alignedRowBytes = SkAlign2(rowBytes); 429b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III if ((int) fBytesBuffered - fCurrRLEByte < alignedRowBytes) { 430b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III SkASSERT(alignedRowBytes < kBufferSize); 431b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III if (this->checkForMoreData() < alignedRowBytes) { 432e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett return y; 433d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett } 4344ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4354ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Set numPixels number of pixels 4364ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett while (numPixels > 0) { 4374ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett switch(this->bitsPerPixel()) { 4384ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett case 4: { 439b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III SkASSERT(fCurrRLEByte < fBytesBuffered); 440b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III uint8_t val = fStreamBuffer[fCurrRLEByte++]; 4414ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett setPixel(dst, dstRowBytes, dstInfo, x++, 4424ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett y, val >> 4); 4434ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett numPixels--; 4444ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if (numPixels != 0) { 4454ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett setPixel(dst, dstRowBytes, dstInfo, 4464ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett x++, y, val & 0xF); 4474ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett numPixels--; 4484ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4494ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett break; 4504ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4514ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett case 8: 452b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III SkASSERT(fCurrRLEByte < fBytesBuffered); 4534ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett setPixel(dst, dstRowBytes, dstInfo, x++, 454b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III y, fStreamBuffer[fCurrRLEByte++]); 4554ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett numPixels--; 4564ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett break; 4574ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett case 24: { 458b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III SkASSERT(fCurrRLEByte + 2 < fBytesBuffered); 459b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III uint8_t blue = fStreamBuffer[fCurrRLEByte++]; 460b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III uint8_t green = fStreamBuffer[fCurrRLEByte++]; 461b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III uint8_t red = fStreamBuffer[fCurrRLEByte++]; 4624ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett setRGBPixel(dst, dstRowBytes, dstInfo, 4634ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett x++, y, red, green, blue); 4644ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett numPixels--; 465d567a815b0eef3f0cdaee6b45bac71414a437f0emsarett break; 4664ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4674ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett default: 4684ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett SkASSERT(false); 469e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett return y; 4704ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4714ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4724ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Skip a byte if necessary to maintain alignment 4734ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if (!SkIsAlign2(rowBytes)) { 4744ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett fCurrRLEByte++; 4754ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4764ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett break; 4774ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4784ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4794ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } else { 4804ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // If the first byte read is not a flag, it indicates the number of 4814ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // pixels to set in RLE mode. 4824ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett const uint8_t numPixels = flag; 4834ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett const int endX = SkTMin<int>(x + numPixels, width); 4844ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 4854ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if (24 == this->bitsPerPixel()) { 4864ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // In RLE24, the second byte read is part of the pixel color. 4874ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // There are two more required bytes to finish encoding the 4884ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // color. 489b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III if ((int) fBytesBuffered - fCurrRLEByte < 2) { 490d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett if (this->checkForMoreData() < 2) { 491e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett return y; 492d0375bc4607f9d3f2ec427771e90ec7d284c174dmsarett } 4934ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 4944ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 4954ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Fill the pixels up to endX with the specified color 4964ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint8_t blue = task; 497b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III uint8_t green = fStreamBuffer[fCurrRLEByte++]; 498b3b24538e02ead0c3f5bc528818982475890efd6Leon Scroggins III uint8_t red = fStreamBuffer[fCurrRLEByte++]; 4994ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett while (x < endX) { 5000153dea2f9c2fb23fb5e39933d21e11e162aac59bungeman setRGBPixel(dst, dstRowBytes, dstInfo, x++, y, red, green, blue); 5014ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 5024ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } else { 5034ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // In RLE8 or RLE4, the second byte read gives the index in the 5044ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // color table to look up the pixel color. 5054ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // RLE8 has one color index that gets repeated 5064ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // RLE4 has two color indexes in the upper and lower 4 bits of 5074ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // the bytes, which are alternated 5084ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett uint8_t indices[2] = { task, task }; 5094ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett if (4 == this->bitsPerPixel()) { 5104ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett indices[0] >>= 4; 5114ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett indices[1] &= 0xf; 5124ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 5134ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett 5144ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett // Set the indicated number of pixels 5154ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett for (int which = 0; x < endX; x++) { 5160153dea2f9c2fb23fb5e39933d21e11e162aac59bungeman setPixel(dst, dstRowBytes, dstInfo, x, y, indices[which]); 5174ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett which = !which; 5184ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 5194ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 5204ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 5214ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett } 5224ab9d5f1bc6d05c49dc765c3de5ade816f4c968emsarett} 523e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo 5249b9497ef14f23562a95afe989d1efe41c603a6f6msarettbool SkBmpRLECodec::skipRows(int count) { 5259b9497ef14f23562a95afe989d1efe41c603a6f6msarett const SkImageInfo rowInfo = SkImageInfo::Make(this->getInfo().width(), count, kN32_SkColorType, 5269b9497ef14f23562a95afe989d1efe41c603a6f6msarett kUnpremul_SkAlphaType); 5279b9497ef14f23562a95afe989d1efe41c603a6f6msarett 5289b9497ef14f23562a95afe989d1efe41c603a6f6msarett return count == this->decodeRows(rowInfo, nullptr, 0, this->options()); 5299b9497ef14f23562a95afe989d1efe41c603a6f6msarett} 5309b9497ef14f23562a95afe989d1efe41c603a6f6msarett 531e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett// FIXME: Make SkBmpRLECodec have no knowledge of sampling. 532e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett// Or it should do all sampling natively. 533e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett// It currently is a hybrid that needs to know what SkScaledCodec is doing. 534e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggoclass SkBmpRLESampler : public SkSampler { 535e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggopublic: 536e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo SkBmpRLESampler(SkBmpRLECodec* codec) 537e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo : fCodec(codec) 538e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo { 539e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo SkASSERT(fCodec); 540e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo } 541e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo 542e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggoprivate: 543e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarett int onSetSampleX(int sampleX) override { 544e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo return fCodec->setSampleX(sampleX); 545e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo } 546e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo 547e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo // Unowned pointer. fCodec will delete this class in its destructor. 548e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo SkBmpRLECodec* fCodec; 549e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo}; 550e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo 55117315c20e7a87d6e92fdc4623d2e27303037a051msarettSkSampler* SkBmpRLECodec::getSampler(bool /*createIfNecessary*/) { 55217315c20e7a87d6e92fdc4623d2e27303037a051msarett // We will always create an SkBmpRLESampler if one is requested. 55317315c20e7a87d6e92fdc4623d2e27303037a051msarett // This allows clients to always use the SkBmpRLESampler's 55417315c20e7a87d6e92fdc4623d2e27303037a051msarett // version of fill(), which does nothing since RLE decodes have 55517315c20e7a87d6e92fdc4623d2e27303037a051msarett // already filled pixel memory. This seems fine, since creating 55617315c20e7a87d6e92fdc4623d2e27303037a051msarett // an SkBmpRLESampler is pretty inexpensive. 55717315c20e7a87d6e92fdc4623d2e27303037a051msarett if (!fSampler) { 558e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo fSampler.reset(new SkBmpRLESampler(this)); 559e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo } 560e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo 561145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner return fSampler.get(); 562e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo} 563e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo 564e6dd004c1b8a81dc37a370570877b8b7d6dbe308msarettint SkBmpRLECodec::setSampleX(int sampleX){ 565e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo fSampleX = sampleX; 566e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo return get_scaled_dimension(this->getInfo().width(), sampleX); 567e7fc14b55bb8c41ba054abf0bfa09cdd6ec84671scroggo} 568