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