OLD | NEW |
---|---|
(Empty) | |
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 "SkColorPriv.h" | |
9 #include "SkMaskSwizzler.h" | |
10 | |
11 /* | |
12 * | |
13 * Used to convert 1-7 bit color components into 8-bit color components | |
14 * | |
15 */ | |
16 const static uint8_t n_bit_to_8_bit_lookup_table[] = { | |
17 // 1 bit | |
18 0, 255, | |
19 // 2 bits | |
20 0, 85, 170, 255, | |
21 // 3 bits | |
22 0, 36, 73, 109, 146, 182, 219, 255, | |
23 // 4 bits | |
24 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255, | |
25 // 5 bits | |
26 0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, | |
27 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255, | |
28 // 6 bits | |
29 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, | |
30 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, | |
31 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198, | |
32 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255, | |
33 // 7 bits | |
34 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, | |
35 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, | |
36 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, | |
37 112, 114, 116, 118, 120, 122, 124, 126, 129, 131, 133, 135, 137, 139, 141, | |
38 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, | |
39 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, | |
40 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, | |
41 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 | |
42 }; | |
43 | |
44 /* | |
45 * | |
46 * Convert an n bit component to an 8-bit component | |
47 * | |
48 */ | |
49 static uint8_t convert_to_8(uint32_t component, uint32_t n) { | |
50 if (0 == n) { | |
51 return 0; | |
52 } else if (8 > n) { | |
53 return n_bit_to_8_bit_lookup_table[(1 << n) - 2 + component]; | |
54 } else { | |
55 SkASSERT(8 == n); | |
56 return component; | |
57 } | |
58 } | |
59 | |
60 /* | |
61 * | |
62 * Get the color component | |
63 * | |
64 */ | |
65 static uint8_t get_comp(uint32_t pixel, uint32_t mask, uint32_t shift, | |
66 uint32_t size) { | |
67 return convert_to_8((pixel & mask) >> shift, size); | |
68 } | |
69 | |
70 /* | |
71 * | |
72 * Row procedure for masked color components with 16 bits per pixel | |
73 * | |
74 */ | |
75 static SkSwizzler::ResultAlpha swizzle_mask16_to_n32( | |
76 void* dstRow, const uint8_t* srcRow, int width, | |
77 const SkMaskSwizzler::Masks& masks) { | |
78 | |
79 // Use the masks to decode to the destination | |
80 uint16_t* srcPtr = (uint16_t*) srcRow; | |
81 SkPMColor* dstPtr = (SkPMColor*) dstRow; | |
82 for (uint32_t i = 0; i < width; i++) { | |
83 uint16_t p = srcPtr[i]; | |
84 uint8_t red = get_comp(p, masks.red.mask, masks.red.shift, | |
scroggo
2015/03/11 14:23:10
get_comp is a step in the right direction.
What i
msarett
2015/03/11 18:53:05
Agreed this is done.
| |
85 masks.red.size); | |
86 uint8_t green = get_comp(p, masks.green.mask, masks.green.shift, | |
87 masks.green.size); | |
88 uint8_t blue = get_comp(p, masks.blue.mask, masks.blue.shift, | |
89 masks.blue.size); | |
90 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); | |
91 } | |
92 return SkSwizzler::kOpaque_ResultAlpha; | |
93 } | |
94 | |
95 /* | |
96 * | |
97 * Row procedure for masked color components with 16 bits per pixel with alpha | |
98 * | |
99 */ | |
100 static SkSwizzler::ResultAlpha swizzle_mask16_alpha_to_n32( | |
101 void* dstRow, const uint8_t* srcRow, int width, | |
102 const SkMaskSwizzler::Masks& masks) { | |
103 | |
104 // Use the masks to decode to the destination | |
105 uint16_t* srcPtr = (uint16_t*) srcRow; | |
106 SkPMColor* dstPtr = (SkPMColor*) dstRow; | |
107 uint8_t zeroAlpha = 0; | |
108 uint8_t maxAlpha = 0xFF; | |
109 for (uint32_t i = 0; i < width; i++) { | |
110 uint16_t p = srcPtr[i]; | |
111 uint8_t red = get_comp(p, masks.red.mask, masks.red.shift, | |
112 masks.red.size); | |
113 uint8_t green = get_comp(p, masks.green.mask, masks.green.shift, | |
114 masks.green.size); | |
115 uint8_t blue = get_comp(p, masks.blue.mask, masks.blue.shift, | |
116 masks.blue.size); | |
117 uint8_t alpha = get_comp(p, masks.alpha.mask, masks.alpha.shift, | |
118 masks.alpha.size); | |
119 zeroAlpha |= alpha; | |
120 maxAlpha &= alpha; | |
121 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue); | |
122 } | |
123 return SkSwizzler::GetResult(zeroAlpha, maxAlpha); | |
124 } | |
125 | |
126 /* | |
127 * | |
128 * Row procedure for masked color components with 24 bits per pixel | |
129 * | |
130 */ | |
131 static SkSwizzler::ResultAlpha swizzle_mask24_to_n32( | |
132 void* dstRow, const uint8_t* srcRow, int width, | |
133 const SkMaskSwizzler::Masks& masks) { | |
134 | |
135 // Use the masks to decode to the destination | |
136 SkPMColor* dstPtr = (SkPMColor*) dstRow; | |
137 for (uint32_t i = 0; i < 3*width; i += 3) { | |
138 uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16; | |
139 uint8_t red = get_comp(p, masks.red.mask, masks.red.shift, | |
140 masks.red.size); | |
141 uint8_t green = get_comp(p, masks.green.mask, masks.green.shift, | |
142 masks.green.size); | |
143 uint8_t blue = get_comp(p, masks.blue.mask, masks.blue.shift, | |
144 masks.blue.size); | |
145 dstPtr[i/3] = SkPackARGB32NoCheck(0xFF, red, green, blue); | |
146 } | |
147 return SkSwizzler::kOpaque_ResultAlpha; | |
148 } | |
149 | |
150 /* | |
151 * | |
152 * Row procedure for masked color components with 24 bits per pixel with alpha | |
153 * | |
154 */ | |
155 static SkSwizzler::ResultAlpha swizzle_mask24_alpha_to_n32( | |
156 void* dstRow, const uint8_t* srcRow, int width, | |
157 const SkMaskSwizzler::Masks& masks) { | |
158 | |
159 // Use the masks to decode to the destination | |
160 SkPMColor* dstPtr = (SkPMColor*) dstRow; | |
161 uint8_t zeroAlpha = 0; | |
162 uint8_t maxAlpha = 0xFF; | |
163 for (uint32_t i = 0; i < 3*width; i += 3) { | |
164 uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16; | |
165 uint8_t red = get_comp(p, masks.red.mask, masks.red.shift, | |
166 masks.red.size); | |
167 uint8_t green = get_comp(p, masks.green.mask, masks.green.shift, | |
168 masks.green.size); | |
169 uint8_t blue = get_comp(p, masks.blue.mask, masks.blue.shift, | |
170 masks.blue.size); | |
171 uint8_t alpha = get_comp(p, masks.alpha.mask, masks.alpha.shift, | |
172 masks.alpha.size); | |
173 zeroAlpha |= alpha; | |
174 maxAlpha &= alpha; | |
175 dstPtr[i/3] = SkPackARGB32NoCheck(alpha, red, green, blue); | |
176 } | |
177 return SkSwizzler::GetResult(zeroAlpha, maxAlpha); | |
178 } | |
179 | |
180 /* | |
181 * | |
182 * Row procedure for masked color components with 32 bits per pixel | |
183 * | |
184 */ | |
185 static SkSwizzler::ResultAlpha swizzle_mask32_to_n32( | |
186 void* dstRow, const uint8_t* srcRow, int width, | |
187 const SkMaskSwizzler::Masks& masks) { | |
188 | |
189 // Use the masks to decode to the destination | |
190 uint32_t* srcPtr = (uint32_t*) srcRow; | |
191 SkPMColor* dstPtr = (SkPMColor*) dstRow; | |
192 for (uint32_t i = 0; i < width; i++) { | |
193 uint32_t p = srcPtr[i]; | |
194 uint8_t red = get_comp(p, masks.red.mask, masks.red.shift, | |
195 masks.red.size); | |
196 uint8_t green = get_comp(p, masks.green.mask, masks.green.shift, | |
197 masks.green.size); | |
198 uint8_t blue = get_comp(p, masks.blue.mask, masks.blue.shift, | |
199 masks.blue.size); | |
200 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); | |
201 } | |
202 return SkSwizzler::kOpaque_ResultAlpha; | |
203 } | |
204 | |
205 /* | |
206 * | |
207 * Row procedure for masked color components with 32 bits per pixel | |
208 * | |
209 */ | |
210 static SkSwizzler::ResultAlpha swizzle_mask32_alpha_to_n32( | |
211 void* dstRow, const uint8_t* srcRow, int width, | |
212 const SkMaskSwizzler::Masks& masks) { | |
213 | |
214 // Use the masks to decode to the destination | |
215 uint32_t* srcPtr = (uint32_t*) srcRow; | |
216 SkPMColor* dstPtr = (SkPMColor*) dstRow; | |
217 uint8_t zeroAlpha = 0; | |
218 uint8_t maxAlpha = 0xFF; | |
219 for (uint32_t i = 0; i < width; i++) { | |
220 uint32_t p = srcPtr[i]; | |
221 uint8_t red = get_comp(p, masks.red.mask, masks.red.shift, | |
222 masks.red.size); | |
223 uint8_t green = get_comp(p, masks.green.mask, masks.green.shift, | |
224 masks.green.size); | |
225 uint8_t blue = get_comp(p, masks.blue.mask, masks.blue.shift, | |
226 masks.blue.size); | |
227 uint8_t alpha = get_comp(p, masks.alpha.mask, masks.alpha.shift, | |
228 masks.alpha.size); | |
229 zeroAlpha |= alpha; | |
230 maxAlpha &= alpha; | |
231 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue); | |
232 } | |
233 return SkSwizzler::GetResult(zeroAlpha, maxAlpha); | |
234 } | |
235 | |
236 /* | |
237 * | |
238 * Process an input mask to obtain the necessary information | |
239 * | |
240 */ | |
241 const SkMaskSwizzler::MaskInfo& SkMaskSwizzler::ProcessMask(uint32_t mask, | |
242 uint32_t bpp) { | |
243 // Trim the masks to the allowed number of bits | |
244 if (bpp < 32) { | |
245 mask &= (1 << bpp) - 1; | |
246 } | |
247 | |
248 // Determine properties of the mask | |
249 uint32_t tempMask = mask; | |
250 uint32_t shift = 0; | |
251 uint32_t size = 0; | |
252 if (tempMask != 0) { | |
253 // Count trailing zeros on masks | |
254 for (; (tempMask & 1) == 0; tempMask >>= 1) { | |
255 shift++; | |
256 } | |
257 // Count the size of the mask | |
258 for (; tempMask & 1; tempMask >>= 1) { | |
259 size++; | |
260 } | |
261 // Truncate masks greater than 8 bits | |
262 if (size > 8) { | |
263 shift += size - 8; | |
264 size = 8; | |
265 } | |
266 } | |
267 | |
268 // Save the calculated values | |
269 const MaskInfo info = { mask, shift, size }; | |
270 return info; | |
271 } | |
272 | |
273 /* | |
274 * | |
275 * Create a new mask swizzler | |
276 * | |
277 */ | |
278 SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( | |
279 const SkImageInfo& imageInfo, InputMasks input, uint32_t bitsPerPixel) { | |
280 // Process input masks | |
281 const MaskInfo red = ProcessMask(input.red, bitsPerPixel); | |
282 const MaskInfo green = ProcessMask(input.green, bitsPerPixel); | |
283 const MaskInfo blue = ProcessMask(input.blue, bitsPerPixel); | |
284 const MaskInfo alpha = ProcessMask(input.alpha, bitsPerPixel); | |
285 const Masks masks = { red, green, blue, alpha }; | |
286 | |
287 // Choose the appropriate row procedure | |
288 RowProc proc = NULL; | |
289 switch (bitsPerPixel) { | |
290 case 16: | |
291 if (masks.alpha.mask == 0) { | |
292 proc = &swizzle_mask16_to_n32; | |
293 } else { | |
294 proc = &swizzle_mask16_alpha_to_n32; | |
295 } | |
296 break; | |
297 case 24: | |
298 if (masks.alpha.mask == 0) { | |
299 proc = &swizzle_mask24_to_n32; | |
300 } else { | |
301 proc = &swizzle_mask24_alpha_to_n32; | |
302 } | |
303 break; | |
304 case 32: | |
305 if (masks.alpha.mask == 0) { | |
306 proc = &swizzle_mask32_to_n32; | |
307 } else { | |
308 proc = &swizzle_mask32_alpha_to_n32; | |
309 } | |
310 break; | |
311 default: | |
312 SkASSERT(false); | |
313 return NULL; | |
314 } | |
315 return SkNEW_ARGS(SkMaskSwizzler, (imageInfo, masks, proc)); | |
316 } | |
317 | |
318 /* | |
319 * | |
320 * Constructor for mask swizzler | |
321 * | |
322 */ | |
323 SkMaskSwizzler::SkMaskSwizzler(const SkImageInfo& imageInfo, const Masks& masks, | |
324 RowProc proc) | |
325 : fImageInfo(imageInfo) | |
326 , fMasks(masks) | |
327 , fRowProc(proc) | |
328 {} | |
329 | |
330 /* | |
331 * | |
332 * Swizzle the next row | |
333 * | |
334 */ | |
335 SkSwizzler::ResultAlpha SkMaskSwizzler::next(void* dst, | |
336 const uint8_t* src) { | |
337 return fRowProc(dst, src, fImageInfo.width(), fMasks); | |
338 } | |
OLD | NEW |