blob: e5facc1f0c7a70283d4518fbe9b4d725314372d9 [file] [log] [blame]
msarett74114382015-03-16 11:55:18 -07001/*
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 "SkCodecPriv.h"
9#include "SkColorPriv.h"
10#include "SkMaskSwizzler.h"
11
msaretteed039b2015-03-18 11:11:19 -070012static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_opaque(
msarett5406d6f2015-08-31 06:55:13 -070013 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
14 uint32_t startX, uint32_t sampleX) {
msarett74114382015-03-16 11:55:18 -070015
16 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -070017 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
msarett74114382015-03-16 11:55:18 -070018 SkPMColor* dstPtr = (SkPMColor*) dstRow;
19 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -070020 uint16_t p = srcPtr[0];
msarett74114382015-03-16 11:55:18 -070021 uint8_t red = masks->getRed(p);
22 uint8_t green = masks->getGreen(p);
23 uint8_t blue = masks->getBlue(p);
24 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -070025 srcPtr += sampleX;
msarett74114382015-03-16 11:55:18 -070026 }
27 return SkSwizzler::kOpaque_ResultAlpha;
28}
29
msaretteed039b2015-03-18 11:11:19 -070030static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_unpremul(
msarett5406d6f2015-08-31 06:55:13 -070031 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
32 uint32_t startX, uint32_t sampleX) {
msarett74114382015-03-16 11:55:18 -070033
34 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -070035 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
msarett74114382015-03-16 11:55:18 -070036 SkPMColor* dstPtr = (SkPMColor*) dstRow;
37 INIT_RESULT_ALPHA;
38 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -070039 uint16_t p = srcPtr[0];
msarett74114382015-03-16 11:55:18 -070040 uint8_t red = masks->getRed(p);
41 uint8_t green = masks->getGreen(p);
42 uint8_t blue = masks->getBlue(p);
43 uint8_t alpha = masks->getAlpha(p);
44 UPDATE_RESULT_ALPHA(alpha);
45 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -070046 srcPtr += sampleX;
msarett74114382015-03-16 11:55:18 -070047 }
48 return COMPUTE_RESULT_ALPHA;
49}
50
msaretteed039b2015-03-18 11:11:19 -070051static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_premul(
msarett5406d6f2015-08-31 06:55:13 -070052 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
53 uint32_t startX, uint32_t sampleX) {
msaretteed039b2015-03-18 11:11:19 -070054
55 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -070056 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
msaretteed039b2015-03-18 11:11:19 -070057 SkPMColor* dstPtr = (SkPMColor*) dstRow;
58 INIT_RESULT_ALPHA;
59 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -070060 uint16_t p = srcPtr[0];
msaretteed039b2015-03-18 11:11:19 -070061 uint8_t red = masks->getRed(p);
62 uint8_t green = masks->getGreen(p);
63 uint8_t blue = masks->getBlue(p);
64 uint8_t alpha = masks->getAlpha(p);
65 UPDATE_RESULT_ALPHA(alpha);
66 dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -070067 srcPtr += sampleX;
msaretteed039b2015-03-18 11:11:19 -070068 }
69 return COMPUTE_RESULT_ALPHA;
70}
71
scroggocc2feb12015-08-14 08:32:46 -070072// TODO (msarett): We have promoted a two byte per pixel image to 8888, only to
73// convert it back to 565. Instead, we should swizzle to 565 directly.
74static SkSwizzler::ResultAlpha swizzle_mask16_to_565(
msarett5406d6f2015-08-31 06:55:13 -070075 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
76 uint32_t startX, uint32_t sampleX) {
scroggocc2feb12015-08-14 08:32:46 -070077
78 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -070079 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
scroggocc2feb12015-08-14 08:32:46 -070080 uint16_t* dstPtr = (uint16_t*) dstRow;
81 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -070082 uint16_t p = srcPtr[0];
scroggocc2feb12015-08-14 08:32:46 -070083 uint8_t red = masks->getRed(p);
84 uint8_t green = masks->getGreen(p);
85 uint8_t blue = masks->getBlue(p);
86 dstPtr[i] = SkPack888ToRGB16(red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -070087 srcPtr += sampleX;
scroggocc2feb12015-08-14 08:32:46 -070088 }
89 return SkSwizzler::kOpaque_ResultAlpha;
90}
91
msaretteed039b2015-03-18 11:11:19 -070092static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_opaque(
msarett5406d6f2015-08-31 06:55:13 -070093 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
94 uint32_t startX, uint32_t sampleX) {
msarett74114382015-03-16 11:55:18 -070095
96 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -070097 srcRow += 3 * startX;
msarett74114382015-03-16 11:55:18 -070098 SkPMColor* dstPtr = (SkPMColor*) dstRow;
msarett5406d6f2015-08-31 06:55:13 -070099 for (int i = 0; i < width; i++) {
100 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
msarett74114382015-03-16 11:55:18 -0700101 uint8_t red = masks->getRed(p);
102 uint8_t green = masks->getGreen(p);
103 uint8_t blue = masks->getBlue(p);
msarett5406d6f2015-08-31 06:55:13 -0700104 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
105 srcRow += 3 * sampleX;
msarett74114382015-03-16 11:55:18 -0700106 }
107 return SkSwizzler::kOpaque_ResultAlpha;
108}
109
msaretteed039b2015-03-18 11:11:19 -0700110static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_unpremul(
msarett5406d6f2015-08-31 06:55:13 -0700111 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
112 uint32_t startX, uint32_t sampleX) {
msarett74114382015-03-16 11:55:18 -0700113
114 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -0700115 srcRow += 3 * startX;
msarett74114382015-03-16 11:55:18 -0700116 SkPMColor* dstPtr = (SkPMColor*) dstRow;
117 INIT_RESULT_ALPHA;
118 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -0700119 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
msarett74114382015-03-16 11:55:18 -0700120 uint8_t red = masks->getRed(p);
121 uint8_t green = masks->getGreen(p);
122 uint8_t blue = masks->getBlue(p);
123 uint8_t alpha = masks->getAlpha(p);
124 UPDATE_RESULT_ALPHA(alpha);
125 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -0700126 srcRow += 3 * sampleX;
msarett74114382015-03-16 11:55:18 -0700127 }
128 return COMPUTE_RESULT_ALPHA;
129}
130
msarett5406d6f2015-08-31 06:55:13 -0700131static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul(
132 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
133 uint32_t startX, uint32_t sampleX) {
msaretteed039b2015-03-18 11:11:19 -0700134
135 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -0700136 srcRow += 3 * startX;
msaretteed039b2015-03-18 11:11:19 -0700137 SkPMColor* dstPtr = (SkPMColor*) dstRow;
138 INIT_RESULT_ALPHA;
139 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -0700140 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
msaretteed039b2015-03-18 11:11:19 -0700141 uint8_t red = masks->getRed(p);
142 uint8_t green = masks->getGreen(p);
143 uint8_t blue = masks->getBlue(p);
144 uint8_t alpha = masks->getAlpha(p);
145 UPDATE_RESULT_ALPHA(alpha);
146 dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -0700147 srcRow += 3 * sampleX;
148 }
149 return COMPUTE_RESULT_ALPHA;
150}
151
152static SkSwizzler::ResultAlpha swizzle_mask24_to_565(
153 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
154 uint32_t startX, uint32_t sampleX) {
155
156 // Use the masks to decode to the destination
157 srcRow += 3 * startX;
158 uint16_t* dstPtr = (uint16_t*) dstRow;
159 for (int i = 0; i < width; i++) {
160 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
161 uint8_t red = masks->getRed(p);
162 uint8_t green = masks->getGreen(p);
163 uint8_t blue = masks->getBlue(p);
164 dstPtr[i] = SkPack888ToRGB16(red, green, blue);
165 srcRow += 3 * sampleX;
166 }
167 return SkSwizzler::kOpaque_ResultAlpha;
168}
169
170static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque(
171 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
172 uint32_t startX, uint32_t sampleX) {
173
174 // Use the masks to decode to the destination
175 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
176 SkPMColor* dstPtr = (SkPMColor*) dstRow;
177 for (int i = 0; i < width; i++) {
178 uint32_t p = srcPtr[0];
179 uint8_t red = masks->getRed(p);
180 uint8_t green = masks->getGreen(p);
181 uint8_t blue = masks->getBlue(p);
182 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
183 srcPtr += sampleX;
184 }
185 return SkSwizzler::kOpaque_ResultAlpha;
186}
187
188static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul(
189 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
190 uint32_t startX, uint32_t sampleX) {
191
192 // Use the masks to decode to the destination
193 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
194 SkPMColor* dstPtr = (SkPMColor*) dstRow;
195 INIT_RESULT_ALPHA;
196 for (int i = 0; i < width; i++) {
197 uint32_t p = srcPtr[0];
198 uint8_t red = masks->getRed(p);
199 uint8_t green = masks->getGreen(p);
200 uint8_t blue = masks->getBlue(p);
201 uint8_t alpha = masks->getAlpha(p);
202 UPDATE_RESULT_ALPHA(alpha);
203 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
204 srcPtr += sampleX;
205 }
206 return COMPUTE_RESULT_ALPHA;
207}
208
209static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul(
210 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
211 uint32_t startX, uint32_t sampleX) {
212
213 // Use the masks to decode to the destination
214 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
215 SkPMColor* dstPtr = (SkPMColor*) dstRow;
216 INIT_RESULT_ALPHA;
217 for (int i = 0; i < width; i++) {
218 uint32_t p = srcPtr[0];
219 uint8_t red = masks->getRed(p);
220 uint8_t green = masks->getGreen(p);
221 uint8_t blue = masks->getBlue(p);
222 uint8_t alpha = masks->getAlpha(p);
223 UPDATE_RESULT_ALPHA(alpha);
224 dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
225 srcPtr += sampleX;
msaretteed039b2015-03-18 11:11:19 -0700226 }
227 return COMPUTE_RESULT_ALPHA;
228}
229
scroggocc2feb12015-08-14 08:32:46 -0700230static SkSwizzler::ResultAlpha swizzle_mask32_to_565(
msarett5406d6f2015-08-31 06:55:13 -0700231 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
232 uint32_t startX, uint32_t sampleX) {
scroggocc2feb12015-08-14 08:32:46 -0700233 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -0700234 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
scroggocc2feb12015-08-14 08:32:46 -0700235 uint16_t* dstPtr = (uint16_t*) dstRow;
236 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -0700237 uint32_t p = srcPtr[0];
scroggocc2feb12015-08-14 08:32:46 -0700238 uint8_t red = masks->getRed(p);
239 uint8_t green = masks->getGreen(p);
240 uint8_t blue = masks->getBlue(p);
241 dstPtr[i] = SkPack888ToRGB16(red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -0700242 srcPtr += sampleX;
scroggocc2feb12015-08-14 08:32:46 -0700243 }
244 return SkSwizzler::kOpaque_ResultAlpha;
245}
246
msarett74114382015-03-16 11:55:18 -0700247/*
248 *
249 * Create a new mask swizzler
250 *
251 */
msarettfdb47572015-10-13 12:50:14 -0700252SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(const SkImageInfo& dstInfo,
253 const SkImageInfo& srcInfo, SkMasks* masks, uint32_t bitsPerPixel,
254 const SkCodec::Options& options) {
msarett74114382015-03-16 11:55:18 -0700255
256 // Choose the appropriate row procedure
halcanary96fcdcc2015-08-27 07:41:13 -0700257 RowProc proc = nullptr;
msarett74114382015-03-16 11:55:18 -0700258 switch (bitsPerPixel) {
259 case 16:
msarett5406d6f2015-08-31 06:55:13 -0700260 switch (dstInfo.colorType()) {
msaretteed039b2015-03-18 11:11:19 -0700261 case kN32_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700262 switch (dstInfo.alphaType()) {
msaretteed039b2015-03-18 11:11:19 -0700263 case kUnpremul_SkAlphaType:
264 proc = &swizzle_mask16_to_n32_unpremul;
265 break;
266 case kPremul_SkAlphaType:
267 proc = &swizzle_mask16_to_n32_premul;
268 break;
269 case kOpaque_SkAlphaType:
270 proc = &swizzle_mask16_to_n32_opaque;
271 break;
272 default:
273 break;
274 }
275 break;
scroggocc2feb12015-08-14 08:32:46 -0700276 case kRGB_565_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700277 switch (dstInfo.alphaType()) {
scroggocc2feb12015-08-14 08:32:46 -0700278 case kOpaque_SkAlphaType:
279 proc = &swizzle_mask16_to_565;
280 break;
281 default:
282 break;
283 }
284 break;
msaretteed039b2015-03-18 11:11:19 -0700285 default:
286 break;
msarett74114382015-03-16 11:55:18 -0700287 }
288 break;
289 case 24:
msarett5406d6f2015-08-31 06:55:13 -0700290 switch (dstInfo.colorType()) {
msaretteed039b2015-03-18 11:11:19 -0700291 case kN32_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700292 switch (dstInfo.alphaType()) {
msaretteed039b2015-03-18 11:11:19 -0700293 case kUnpremul_SkAlphaType:
294 proc = &swizzle_mask24_to_n32_unpremul;
295 break;
296 case kPremul_SkAlphaType:
297 proc = &swizzle_mask24_to_n32_premul;
298 break;
299 case kOpaque_SkAlphaType:
300 proc = &swizzle_mask24_to_n32_opaque;
301 break;
302 default:
303 break;
304 }
305 break;
scroggocc2feb12015-08-14 08:32:46 -0700306 case kRGB_565_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700307 switch (dstInfo.alphaType()) {
scroggocc2feb12015-08-14 08:32:46 -0700308 case kOpaque_SkAlphaType:
309 proc = &swizzle_mask24_to_565;
310 break;
311 default:
312 break;
313 }
314 break;
msaretteed039b2015-03-18 11:11:19 -0700315 default:
316 break;
msarett74114382015-03-16 11:55:18 -0700317 }
318 break;
319 case 32:
msarett5406d6f2015-08-31 06:55:13 -0700320 switch (dstInfo.colorType()) {
msaretteed039b2015-03-18 11:11:19 -0700321 case kN32_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700322 switch (dstInfo.alphaType()) {
msaretteed039b2015-03-18 11:11:19 -0700323 case kUnpremul_SkAlphaType:
324 proc = &swizzle_mask32_to_n32_unpremul;
325 break;
326 case kPremul_SkAlphaType:
327 proc = &swizzle_mask32_to_n32_premul;
328 break;
329 case kOpaque_SkAlphaType:
330 proc = &swizzle_mask32_to_n32_opaque;
331 break;
332 default:
333 break;
334 }
335 break;
scroggocc2feb12015-08-14 08:32:46 -0700336 case kRGB_565_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700337 switch (dstInfo.alphaType()) {
scroggocc2feb12015-08-14 08:32:46 -0700338 case kOpaque_SkAlphaType:
339 proc = &swizzle_mask32_to_565;
340 break;
341 default:
342 break;
343 }
344 break;
msaretteed039b2015-03-18 11:11:19 -0700345 default:
346 break;
msarett74114382015-03-16 11:55:18 -0700347 }
348 break;
349 default:
350 SkASSERT(false);
halcanary96fcdcc2015-08-27 07:41:13 -0700351 return nullptr;
msarett74114382015-03-16 11:55:18 -0700352 }
msarett5406d6f2015-08-31 06:55:13 -0700353
msarettfdb47572015-10-13 12:50:14 -0700354 int srcOffset = 0;
355 int srcWidth = dstInfo.width();
356 if (options.fSubset) {
357 srcOffset = options.fSubset->left();
358 srcWidth = options.fSubset->width();
359 }
360
361 return new SkMaskSwizzler(masks, proc, srcOffset, srcWidth);
msarett74114382015-03-16 11:55:18 -0700362}
363
364/*
365 *
366 * Constructor for mask swizzler
367 *
368 */
msarett80803ff2015-10-16 10:54:12 -0700369SkMaskSwizzler::SkMaskSwizzler(SkMasks* masks, RowProc proc, int srcOffset, int subsetWidth)
scroggoe7fc14b2015-10-02 13:14:46 -0700370 : fMasks(masks)
msarett74114382015-03-16 11:55:18 -0700371 , fRowProc(proc)
msarett80803ff2015-10-16 10:54:12 -0700372 , fSubsetWidth(subsetWidth)
373 , fDstWidth(subsetWidth)
scroggoe7fc14b2015-10-02 13:14:46 -0700374 , fSampleX(1)
msarettfdb47572015-10-13 12:50:14 -0700375 , fSrcOffset(srcOffset)
376 , fX0(srcOffset)
msarett74114382015-03-16 11:55:18 -0700377{}
378
scroggoe7fc14b2015-10-02 13:14:46 -0700379int SkMaskSwizzler::onSetSampleX(int sampleX) {
380 // FIXME: Share this function with SkSwizzler?
381 SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be
382 // way to report failure?
383 fSampleX = sampleX;
msarettfdb47572015-10-13 12:50:14 -0700384 fX0 = get_start_coord(sampleX) + fSrcOffset;
msarett80803ff2015-10-16 10:54:12 -0700385 fDstWidth = get_scaled_dimension(fSubsetWidth, sampleX);
scroggoe7fc14b2015-10-02 13:14:46 -0700386
msarett80803ff2015-10-16 10:54:12 -0700387 // check that fX0 is valid
388 SkASSERT(fX0 >= 0);
scroggoe7fc14b2015-10-02 13:14:46 -0700389 return fDstWidth;
390}
391
msarett74114382015-03-16 11:55:18 -0700392/*
393 *
msaretteed039b2015-03-18 11:11:19 -0700394 * Swizzle the specified row
msarett74114382015-03-16 11:55:18 -0700395 *
396 */
msarett614aa072015-07-27 15:13:17 -0700397SkSwizzler::ResultAlpha SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
halcanary96fcdcc2015-08-27 07:41:13 -0700398 SkASSERT(nullptr != dst && nullptr != src);
scroggoe7fc14b2015-10-02 13:14:46 -0700399 return fRowProc(dst, src, fDstWidth, fMasks, fX0, fSampleX);
msarett74114382015-03-16 11:55:18 -0700400}