OLD | NEW |
| (Empty) |
1 | |
2 /* | |
3 * Copyright 2006 The Android Open Source Project | |
4 * | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 */ | |
8 | |
9 | |
10 #include "SkImageDecoder.h" | |
11 #include "SkColor.h" | |
12 #include "SkColorPriv.h" | |
13 #include "SkMath.h" | |
14 #include "SkStream.h" | |
15 #include "SkTemplates.h" | |
16 #include "SkUtils.h" | |
17 | |
18 class SkWBMPImageDecoder : public SkImageDecoder { | |
19 public: | |
20 Format getFormat() const override { | |
21 return kWBMP_Format; | |
22 } | |
23 | |
24 protected: | |
25 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override; | |
26 | |
27 private: | |
28 typedef SkImageDecoder INHERITED; | |
29 }; | |
30 | |
31 static bool read_byte(SkStream* stream, uint8_t* data) | |
32 { | |
33 return stream->read(data, 1) == 1; | |
34 } | |
35 | |
36 static bool read_mbf(SkStream* stream, int* value) | |
37 { | |
38 int n = 0; | |
39 uint8_t data; | |
40 do { | |
41 if (!read_byte(stream, &data)) { | |
42 return false; | |
43 } | |
44 n = (n << 7) | (data & 0x7F); | |
45 } while (data & 0x80); | |
46 | |
47 *value = n; | |
48 return true; | |
49 } | |
50 | |
51 struct wbmp_head { | |
52 int fWidth; | |
53 int fHeight; | |
54 | |
55 bool init(SkStream* stream) | |
56 { | |
57 uint8_t data; | |
58 | |
59 if (!read_byte(stream, &data) || data != 0) { // unknown type | |
60 return false; | |
61 } | |
62 if (!read_byte(stream, &data) || (data & 0x9F)) { // skip fixed header | |
63 return false; | |
64 } | |
65 if (!read_mbf(stream, &fWidth) || (unsigned)fWidth > 0xFFFF) { | |
66 return false; | |
67 } | |
68 if (!read_mbf(stream, &fHeight) || (unsigned)fHeight > 0xFFFF) { | |
69 return false; | |
70 } | |
71 return fWidth != 0 && fHeight != 0; | |
72 } | |
73 }; | |
74 | |
75 static void expand_bits_to_bytes(uint8_t dst[], const uint8_t src[], int bits) | |
76 { | |
77 int bytes = bits >> 3; | |
78 | |
79 for (int i = 0; i < bytes; i++) { | |
80 unsigned mask = *src++; | |
81 dst[0] = (mask >> 7) & 1; | |
82 dst[1] = (mask >> 6) & 1; | |
83 dst[2] = (mask >> 5) & 1; | |
84 dst[3] = (mask >> 4) & 1; | |
85 dst[4] = (mask >> 3) & 1; | |
86 dst[5] = (mask >> 2) & 1; | |
87 dst[6] = (mask >> 1) & 1; | |
88 dst[7] = (mask >> 0) & 1; | |
89 dst += 8; | |
90 } | |
91 | |
92 bits &= 7; | |
93 if (bits > 0) { | |
94 unsigned mask = *src; | |
95 do { | |
96 *dst++ = (mask >> 7) & 1; | |
97 mask <<= 1; | |
98 } while (--bits != 0); | |
99 } | |
100 } | |
101 | |
102 SkImageDecoder::Result SkWBMPImageDecoder::onDecode(SkStream* stream, SkBitmap*
decodedBitmap, | |
103 Mode mode) | |
104 { | |
105 wbmp_head head; | |
106 | |
107 if (!head.init(stream)) { | |
108 return kFailure; | |
109 } | |
110 | |
111 int width = head.fWidth; | |
112 int height = head.fHeight; | |
113 | |
114 decodedBitmap->setInfo(SkImageInfo::Make(width, height, | |
115 kIndex_8_SkColorType, kOpaque_SkAlp
haType)); | |
116 | |
117 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | |
118 return kSuccess; | |
119 } | |
120 | |
121 const SkPMColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; | |
122 SkColorTable* ct = new SkColorTable(colors, 2); | |
123 SkAutoUnref aur(ct); | |
124 | |
125 if (!this->allocPixelRef(decodedBitmap, ct)) { | |
126 return kFailure; | |
127 } | |
128 | |
129 SkAutoLockPixels alp(*decodedBitmap); | |
130 | |
131 uint8_t* dst = decodedBitmap->getAddr8(0, 0); | |
132 // store the 1-bit valuess at the end of our pixels, so we won't stomp | |
133 // on them before we're read them. Just trying to avoid a temp allocation | |
134 size_t srcRB = SkAlign8(width) >> 3; | |
135 size_t srcSize = height * srcRB; | |
136 uint8_t* src = dst + decodedBitmap->getSize() - srcSize; | |
137 if (stream->read(src, srcSize) != srcSize) { | |
138 return kFailure; | |
139 } | |
140 | |
141 for (int y = 0; y < height; y++) | |
142 { | |
143 expand_bits_to_bytes(dst, src, width); | |
144 dst += decodedBitmap->rowBytes(); | |
145 src += srcRB; | |
146 } | |
147 | |
148 return kSuccess; | |
149 } | |
150 | |
151 /////////////////////////////////////////////////////////////////////////////// | |
152 DEFINE_DECODER_CREATOR(WBMPImageDecoder); | |
153 /////////////////////////////////////////////////////////////////////////////// | |
154 | |
155 static SkImageDecoder* sk_wbmp_dfactory(SkStreamRewindable* stream) { | |
156 wbmp_head head; | |
157 | |
158 if (head.init(stream)) { | |
159 return new SkWBMPImageDecoder; | |
160 } | |
161 return nullptr; | |
162 } | |
163 | |
164 static SkImageDecoder::Format get_format_wbmp(SkStreamRewindable* stream) { | |
165 wbmp_head head; | |
166 if (head.init(stream)) { | |
167 return SkImageDecoder::kWBMP_Format; | |
168 } | |
169 return SkImageDecoder::kUnknown_Format; | |
170 } | |
171 | |
172 static SkImageDecoder_DecodeReg gDReg(sk_wbmp_dfactory); | |
173 static SkImageDecoder_FormatReg gFormatReg(get_format_wbmp); | |
OLD | NEW |