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 |