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