| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBmpRLECodec.h" | 8 #include "SkBmpRLECodec.h" |
| 9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| 11 #include "SkStream.h" | 11 #include "SkStream.h" |
| 12 | 12 |
| 13 /* | 13 /* |
| 14 * Creates an instance of the decoder | 14 * Creates an instance of the decoder |
| 15 * Called only by NewFromStream | 15 * Called only by NewFromStream |
| 16 */ | 16 */ |
| 17 SkBmpRLECodec::SkBmpRLECodec(const SkImageInfo& info, SkStream* stream, | 17 SkBmpRLECodec::SkBmpRLECodec(const SkImageInfo& info, SkStream* stream, |
| 18 uint16_t bitsPerPixel, uint32_t numColors, | 18 uint16_t bitsPerPixel, uint32_t numColors, |
| 19 uint32_t bytesPerColor, uint32_t offset, | 19 uint32_t bytesPerColor, uint32_t offset, |
| 20 SkCodec::SkScanlineOrder rowOrder, | 20 SkCodec::SkScanlineOrder rowOrder, |
| 21 size_t RLEBytes) | 21 size_t RLEBytes) |
| 22 : INHERITED(info, stream, bitsPerPixel, rowOrder) | 22 : INHERITED(info, stream, bitsPerPixel, rowOrder) |
| 23 , fColorTable(nullptr) | 23 , fColorTable(nullptr) |
| 24 , fNumColors(numColors) | 24 , fNumColors(numColors) |
| 25 , fBytesPerColor(bytesPerColor) | 25 , fBytesPerColor(bytesPerColor) |
| 26 , fOffset(offset) | 26 , fOffset(offset) |
| 27 , fStreamBuffer(new uint8_t[RLEBytes]) | 27 , fStreamBuffer(new uint8_t[RLEBytes]) |
| 28 , fRLEBytes(RLEBytes) | 28 , fRLEBytes(RLEBytes) |
| 29 , fOrigRLEBytes(RLEBytes) |
| 29 , fCurrRLEByte(0) | 30 , fCurrRLEByte(0) |
| 30 , fSampleX(1) | 31 , fSampleX(1) |
| 31 {} | 32 {} |
| 32 | 33 |
| 33 /* | 34 /* |
| 34 * Initiates the bitmap decode | 35 * Initiates the bitmap decode |
| 35 */ | 36 */ |
| 36 SkCodec::Result SkBmpRLECodec::onGetPixels(const SkImageInfo& dstInfo, | 37 SkCodec::Result SkBmpRLECodec::onGetPixels(const SkImageInfo& dstInfo, |
| 37 void* dst, size_t dstRowBytes, | 38 void* dst, size_t dstRowBytes, |
| 38 const Options& opts, | 39 const Options& opts, |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputCo
lorCount) { | 264 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputCo
lorCount) { |
| 264 // FIXME: Support subsets for scanline decodes. | 265 // FIXME: Support subsets for scanline decodes. |
| 265 if (options.fSubset) { | 266 if (options.fSubset) { |
| 266 // Subsets are not supported. | 267 // Subsets are not supported. |
| 267 return kUnimplemented; | 268 return kUnimplemented; |
| 268 } | 269 } |
| 269 | 270 |
| 270 // Reset fSampleX. If it needs to be a value other than 1, it will get modif
ied by | 271 // Reset fSampleX. If it needs to be a value other than 1, it will get modif
ied by |
| 271 // the sampler. | 272 // the sampler. |
| 272 fSampleX = 1; | 273 fSampleX = 1; |
| 274 fLinesToSkip = 0; |
| 275 |
| 273 // Create the color table if necessary and prepare the stream for decode | 276 // Create the color table if necessary and prepare the stream for decode |
| 274 // Note that if it is non-NULL, inputColorCount will be modified | 277 // Note that if it is non-NULL, inputColorCount will be modified |
| 275 if (!this->createColorTable(inputColorCount)) { | 278 if (!this->createColorTable(inputColorCount)) { |
| 276 SkCodecPrintf("Error: could not create color table.\n"); | 279 SkCodecPrintf("Error: could not create color table.\n"); |
| 277 return SkCodec::kInvalidInput; | 280 return SkCodec::kInvalidInput; |
| 278 } | 281 } |
| 279 | 282 |
| 280 // Copy the color table to the client if necessary | 283 // Copy the color table to the client if necessary |
| 281 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount)
; | 284 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount)
; |
| 282 | 285 |
| 283 // Initialize a buffer for encoded RLE data | 286 // Initialize a buffer for encoded RLE data |
| 287 fRLEBytes = fOrigRLEBytes; |
| 284 if (!this->initializeStreamBuffer()) { | 288 if (!this->initializeStreamBuffer()) { |
| 285 SkCodecPrintf("Error: cannot initialize stream buffer.\n"); | 289 SkCodecPrintf("Error: cannot initialize stream buffer.\n"); |
| 286 return SkCodec::kInvalidConversion; | 290 return SkCodec::kInvalidConversion; |
| 287 } | 291 } |
| 288 | 292 |
| 289 return SkCodec::kSuccess; | 293 return SkCodec::kSuccess; |
| 290 } | 294 } |
| 291 | 295 |
| 292 /* | 296 /* |
| 293 * Performs the bitmap decoding for RLE input format | 297 * Performs the bitmap decoding for RLE input format |
| 294 * RLE decoding is performed all at once, rather than a one row at a time | 298 * RLE decoding is performed all at once, rather than a one row at a time |
| 295 */ | 299 */ |
| 296 int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowB
ytes, | 300 int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowB
ytes, |
| 297 const Options& opts) { | 301 const Options& opts) { |
| 298 // Set RLE flags | 302 // Set RLE flags |
| 299 static const uint8_t RLE_ESCAPE = 0; | 303 static const uint8_t RLE_ESCAPE = 0; |
| 300 static const uint8_t RLE_EOL = 0; | 304 static const uint8_t RLE_EOL = 0; |
| 301 static const uint8_t RLE_EOF = 1; | 305 static const uint8_t RLE_EOF = 1; |
| 302 static const uint8_t RLE_DELTA = 2; | 306 static const uint8_t RLE_DELTA = 2; |
| 303 | 307 |
| 304 // Set constant values | |
| 305 const int width = this->getInfo().width(); | 308 const int width = this->getInfo().width(); |
| 306 const int height = info.height(); | 309 int height = info.height(); |
| 307 | 310 |
| 308 // Account for sampling. | 311 // Account for sampling. |
| 309 SkImageInfo dstInfo = info.makeWH(get_scaled_dimension(width, fSampleX), hei
ght); | 312 SkImageInfo dstInfo = info.makeWH(get_scaled_dimension(width, fSampleX), hei
ght); |
| 310 | 313 |
| 311 // Destination parameters | |
| 312 int x = 0; | |
| 313 int y = 0; | |
| 314 | |
| 315 // Set the background as transparent. Then, if the RLE code skips pixels, | 314 // Set the background as transparent. Then, if the RLE code skips pixels, |
| 316 // the skipped pixels will be transparent. | 315 // the skipped pixels will be transparent. |
| 317 // Because of the need for transparent pixels, kN32 is the only color | 316 // Because of the need for transparent pixels, kN32 is the only color |
| 318 // type that makes sense for the destination format. | 317 // type that makes sense for the destination format. |
| 319 SkASSERT(kN32_SkColorType == dstInfo.colorType()); | 318 SkASSERT(kN32_SkColorType == dstInfo.colorType()); |
| 320 SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZeroIn
itialized); | 319 SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZeroIn
itialized); |
| 321 | 320 |
| 321 // Adjust the height and the dst if the previous call to decodeRows() left u
s |
| 322 // with lines that need to be skipped. |
| 323 if (height > fLinesToSkip) { |
| 324 height -= fLinesToSkip; |
| 325 dst = SkTAddOffset<void>(dst, fLinesToSkip * dstRowBytes); |
| 326 fLinesToSkip = 0; |
| 327 } else { |
| 328 fLinesToSkip -= height; |
| 329 return height; |
| 330 } |
| 331 |
| 332 // Destination parameters |
| 333 int x = 0; |
| 334 int y = 0; |
| 335 |
| 322 while (true) { | 336 while (true) { |
| 323 // If we have reached a row that is beyond the requested height, we have | 337 // If we have reached a row that is beyond the requested height, we have |
| 324 // succeeded. | 338 // succeeded. |
| 325 if (y >= height) { | 339 if (y >= height) { |
| 326 // It would be better to check for the EOF marker before indicating | 340 // It would be better to check for the EOF marker before indicating |
| 327 // success, but we may be performing a scanline decode, which | 341 // success, but we may be performing a scanline decode, which |
| 328 // would require us to stop before decoding the full height. | 342 // would require us to stop before decoding the full height. |
| 329 return height; | 343 return height; |
| 330 } | 344 } |
| 331 | 345 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 359 SkCodecPrintf("Warning: might be incomplete RLE input.\n
"); | 373 SkCodecPrintf("Warning: might be incomplete RLE input.\n
"); |
| 360 if (this->checkForMoreData() < 2) { | 374 if (this->checkForMoreData() < 2) { |
| 361 return y; | 375 return y; |
| 362 } | 376 } |
| 363 } | 377 } |
| 364 // Modify x and y | 378 // Modify x and y |
| 365 const uint8_t dx = fStreamBuffer.get()[fCurrRLEByte++]; | 379 const uint8_t dx = fStreamBuffer.get()[fCurrRLEByte++]; |
| 366 const uint8_t dy = fStreamBuffer.get()[fCurrRLEByte++]; | 380 const uint8_t dy = fStreamBuffer.get()[fCurrRLEByte++]; |
| 367 x += dx; | 381 x += dx; |
| 368 y += dy; | 382 y += dy; |
| 369 if (x > width || y > height) { | 383 if (x > width) { |
| 370 SkCodecPrintf("Warning: invalid RLE input.\n"); | 384 SkCodecPrintf("Warning: invalid RLE input.\n"); |
| 371 return y - dy; | 385 return y - dy; |
| 386 } else if (y > height) { |
| 387 fLinesToSkip = y - height; |
| 388 return height; |
| 372 } | 389 } |
| 373 break; | 390 break; |
| 374 } | 391 } |
| 375 default: { | 392 default: { |
| 376 // If task does not match any of the above signals, it | 393 // If task does not match any of the above signals, it |
| 377 // indicates that we have a sequence of non-RLE pixels. | 394 // indicates that we have a sequence of non-RLE pixels. |
| 378 // Furthermore, the value of task is equal to the number | 395 // Furthermore, the value of task is equal to the number |
| 379 // of pixels to interpret. | 396 // of pixels to interpret. |
| 380 uint8_t numPixels = task; | 397 uint8_t numPixels = task; |
| 381 const size_t rowBytes = compute_row_bytes(numPixels, | 398 const size_t rowBytes = compute_row_bytes(numPixels, |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 fSampler.reset(new SkBmpRLESampler(this)); | 525 fSampler.reset(new SkBmpRLESampler(this)); |
| 509 } | 526 } |
| 510 | 527 |
| 511 return fSampler; | 528 return fSampler; |
| 512 } | 529 } |
| 513 | 530 |
| 514 int SkBmpRLECodec::setSampleX(int sampleX){ | 531 int SkBmpRLECodec::setSampleX(int sampleX){ |
| 515 fSampleX = sampleX; | 532 fSampleX = sampleX; |
| 516 return get_scaled_dimension(this->getInfo().width(), sampleX); | 533 return get_scaled_dimension(this->getInfo().width(), sampleX); |
| 517 } | 534 } |
| OLD | NEW |