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/SkBmpMaskCodec.h"
9
10 #include "include/core/SkAlphaType.h"
11 #include "include/core/SkImageInfo.h"
12 #include "include/core/SkSize.h"
13 #include "include/core/SkStream.h"
14 #include "include/private/SkEncodedInfo.h"
15 #include "include/private/base/SkTemplates.h"
16 #include "src/codec/SkCodecPriv.h"
17
18 #include <utility>
19
20 /*
21 * Creates an instance of the decoder
22 */
SkBmpMaskCodec(SkEncodedInfo && info,std::unique_ptr<SkStream> stream,uint16_t bitsPerPixel,SkMasks * masks,SkCodec::SkScanlineOrder rowOrder)23 SkBmpMaskCodec::SkBmpMaskCodec(SkEncodedInfo&& info,
24 std::unique_ptr<SkStream> stream,
25 uint16_t bitsPerPixel, SkMasks* masks,
26 SkCodec::SkScanlineOrder rowOrder)
27 : INHERITED(std::move(info), std::move(stream), bitsPerPixel, rowOrder)
28 , fMasks(masks)
29 , fMaskSwizzler(nullptr)
30 {}
31
32 /*
33 * Initiates the bitmap decode
34 */
onGetPixels(const SkImageInfo & dstInfo,void * dst,size_t dstRowBytes,const Options & opts,int * rowsDecoded)35 SkCodec::Result SkBmpMaskCodec::onGetPixels(const SkImageInfo& dstInfo,
36 void* dst, size_t dstRowBytes,
37 const Options& opts,
38 int* rowsDecoded) {
39 if (opts.fSubset) {
40 // Subsets are not supported.
41 return kUnimplemented;
42 }
43 if (dstInfo.dimensions() != this->dimensions()) {
44 SkCodecPrintf("Error: scaling not supported.\n");
45 return kInvalidScale;
46 }
47
48 Result result = this->prepareToDecode(dstInfo, opts);
49 if (kSuccess != result) {
50 return result;
51 }
52
53 int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts);
54 if (rows != dstInfo.height()) {
55 *rowsDecoded = rows;
56 return kIncompleteInput;
57 }
58 return kSuccess;
59 }
60
onPrepareToDecode(const SkImageInfo & dstInfo,const SkCodec::Options & options)61 SkCodec::Result SkBmpMaskCodec::onPrepareToDecode(const SkImageInfo& dstInfo,
62 const SkCodec::Options& options) {
63 if (this->colorXform()) {
64 this->resetXformBuffer(dstInfo.width());
65 }
66
67 SkImageInfo swizzlerInfo = dstInfo;
68 if (this->colorXform()) {
69 swizzlerInfo = swizzlerInfo.makeColorType(kXformSrcColorType);
70 if (kPremul_SkAlphaType == dstInfo.alphaType()) {
71 swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaType);
72 }
73 }
74
75 bool srcIsOpaque = this->getEncodedInfo().opaque();
76 fMaskSwizzler.reset(SkMaskSwizzler::CreateMaskSwizzler(swizzlerInfo, srcIsOpaque,
77 fMasks.get(), this->bitsPerPixel(), options));
78 SkASSERT(fMaskSwizzler);
79
80 return SkCodec::kSuccess;
81 }
82
83 /*
84 * Performs the decoding
85 */
decodeRows(const SkImageInfo & dstInfo,void * dst,size_t dstRowBytes,const Options & opts)86 int SkBmpMaskCodec::decodeRows(const SkImageInfo& dstInfo,
87 void* dst, size_t dstRowBytes,
88 const Options& opts) {
89 // Iterate over rows of the image
90 uint8_t* srcRow = this->srcBuffer();
91 const int height = dstInfo.height();
92 for (int y = 0; y < height; y++) {
93 // Read a row of the input
94 if (this->stream()->read(srcRow, this->srcRowBytes()) != this->srcRowBytes()) {
95 SkCodecPrintf("Warning: incomplete input stream.\n");
96 return y;
97 }
98
99 // Decode the row in destination format
100 uint32_t row = this->getDstRow(y, height);
101 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes);
102
103 if (this->colorXform()) {
104 fMaskSwizzler->swizzle(this->xformBuffer(), srcRow);
105 this->applyColorXform(dstRow, this->xformBuffer(), fMaskSwizzler->swizzleWidth());
106 } else {
107 fMaskSwizzler->swizzle(dstRow, srcRow);
108 }
109 }
110
111 // Finished decoding the entire image
112 return height;
113 }
114