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 "SkBmpMaskCodec.h"
9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h"
11
12 /*
13 * Creates an instance of the decoder
14 */
SkBmpMaskCodec(const SkImageInfo & info,SkStream * stream,uint16_t bitsPerPixel,SkMasks * masks,SkCodec::SkScanlineOrder rowOrder)15 SkBmpMaskCodec::SkBmpMaskCodec(const SkImageInfo& info, SkStream* stream,
16 uint16_t bitsPerPixel, SkMasks* masks,
17 SkCodec::SkScanlineOrder rowOrder)
18 : INHERITED(info, stream, bitsPerPixel, rowOrder)
19 , fMasks(masks)
20 , fMaskSwizzler(nullptr)
21 , fSrcBuffer(new uint8_t [this->srcRowBytes()])
22 {}
23
24 /*
25 * Initiates the bitmap decode
26 */
onGetPixels(const SkImageInfo & dstInfo,void * dst,size_t dstRowBytes,const Options & opts,SkPMColor * inputColorPtr,int * inputColorCount,int * rowsDecoded)27 SkCodec::Result SkBmpMaskCodec::onGetPixels(const SkImageInfo& dstInfo,
28 void* dst, size_t dstRowBytes,
29 const Options& opts,
30 SkPMColor* inputColorPtr,
31 int* inputColorCount,
32 int* rowsDecoded) {
33 if (opts.fSubset) {
34 // Subsets are not supported.
35 return kUnimplemented;
36 }
37 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
38 SkCodecPrintf("Error: scaling not supported.\n");
39 return kInvalidScale;
40 }
41
42 if (!conversion_possible(dstInfo, this->getInfo())) {
43 SkCodecPrintf("Error: cannot convert input type to output type.\n");
44 return kInvalidConversion;
45 }
46
47 Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputColorCount);
48 if (kSuccess != result) {
49 return result;
50 }
51
52 int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts);
53 if (rows != dstInfo.height()) {
54 *rowsDecoded = rows;
55 return kIncompleteInput;
56 }
57 return kSuccess;
58 }
59
prepareToDecode(const SkImageInfo & dstInfo,const SkCodec::Options & options,SkPMColor inputColorPtr[],int * inputColorCount)60 SkCodec::Result SkBmpMaskCodec::prepareToDecode(const SkImageInfo& dstInfo,
61 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputColorCount) {
62 // Initialize the mask swizzler
63 fMaskSwizzler.reset(SkMaskSwizzler::CreateMaskSwizzler(dstInfo, this->getInfo(), fMasks,
64 this->bitsPerPixel(), options));
65 SkASSERT(fMaskSwizzler);
66
67 return SkCodec::kSuccess;
68 }
69
70 /*
71 * Performs the decoding
72 */
decodeRows(const SkImageInfo & dstInfo,void * dst,size_t dstRowBytes,const Options & opts)73 int SkBmpMaskCodec::decodeRows(const SkImageInfo& dstInfo,
74 void* dst, size_t dstRowBytes,
75 const Options& opts) {
76 // Iterate over rows of the image
77 uint8_t* srcRow = fSrcBuffer.get();
78 const int height = dstInfo.height();
79 for (int y = 0; y < height; y++) {
80 // Read a row of the input
81 if (this->stream()->read(srcRow, this->srcRowBytes()) != this->srcRowBytes()) {
82 SkCodecPrintf("Warning: incomplete input stream.\n");
83 return y;
84 }
85
86 // Decode the row in destination format
87 uint32_t row = this->getDstRow(y, height);
88 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes);
89 fMaskSwizzler->swizzle(dstRow, srcRow);
90 }
91
92 // Finished decoding the entire image
93 return height;
94 }
95