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