blob: 72dca28057ff5c82b13f6b6eaa883970011fee4d [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"
msarett5406d6f2015-08-31 06:55:13 -070011#include "SkScaledCodec.h"
msarett74114382015-03-16 11:55:18 -070012
msaretteed039b2015-03-18 11:11:19 -070013static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_opaque(
msarett5406d6f2015-08-31 06:55:13 -070014 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
15 uint32_t startX, uint32_t sampleX) {
msarett74114382015-03-16 11:55:18 -070016
17 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -070018 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
msarett74114382015-03-16 11:55:18 -070019 SkPMColor* dstPtr = (SkPMColor*) dstRow;
20 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -070021 uint16_t p = srcPtr[0];
msarett74114382015-03-16 11:55:18 -070022 uint8_t red = masks->getRed(p);
23 uint8_t green = masks->getGreen(p);
24 uint8_t blue = masks->getBlue(p);
25 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -070026 srcPtr += sampleX;
msarett74114382015-03-16 11:55:18 -070027 }
28 return SkSwizzler::kOpaque_ResultAlpha;
29}
30
msaretteed039b2015-03-18 11:11:19 -070031static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_unpremul(
msarett5406d6f2015-08-31 06:55:13 -070032 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
33 uint32_t startX, uint32_t sampleX) {
msarett74114382015-03-16 11:55:18 -070034
35 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -070036 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
msarett74114382015-03-16 11:55:18 -070037 SkPMColor* dstPtr = (SkPMColor*) dstRow;
38 INIT_RESULT_ALPHA;
39 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -070040 uint16_t p = srcPtr[0];
msarett74114382015-03-16 11:55:18 -070041 uint8_t red = masks->getRed(p);
42 uint8_t green = masks->getGreen(p);
43 uint8_t blue = masks->getBlue(p);
44 uint8_t alpha = masks->getAlpha(p);
45 UPDATE_RESULT_ALPHA(alpha);
46 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -070047 srcPtr += sampleX;
msarett74114382015-03-16 11:55:18 -070048 }
49 return COMPUTE_RESULT_ALPHA;
50}
51
msaretteed039b2015-03-18 11:11:19 -070052static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_premul(
msarett5406d6f2015-08-31 06:55:13 -070053 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
54 uint32_t startX, uint32_t sampleX) {
msaretteed039b2015-03-18 11:11:19 -070055
56 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -070057 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
msaretteed039b2015-03-18 11:11:19 -070058 SkPMColor* dstPtr = (SkPMColor*) dstRow;
59 INIT_RESULT_ALPHA;
60 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -070061 uint16_t p = srcPtr[0];
msaretteed039b2015-03-18 11:11:19 -070062 uint8_t red = masks->getRed(p);
63 uint8_t green = masks->getGreen(p);
64 uint8_t blue = masks->getBlue(p);
65 uint8_t alpha = masks->getAlpha(p);
66 UPDATE_RESULT_ALPHA(alpha);
67 dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -070068 srcPtr += sampleX;
msaretteed039b2015-03-18 11:11:19 -070069 }
70 return COMPUTE_RESULT_ALPHA;
71}
72
scroggocc2feb12015-08-14 08:32:46 -070073// TODO (msarett): We have promoted a two byte per pixel image to 8888, only to
74// convert it back to 565. Instead, we should swizzle to 565 directly.
75static SkSwizzler::ResultAlpha swizzle_mask16_to_565(
msarett5406d6f2015-08-31 06:55:13 -070076 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
77 uint32_t startX, uint32_t sampleX) {
scroggocc2feb12015-08-14 08:32:46 -070078
79 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -070080 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
scroggocc2feb12015-08-14 08:32:46 -070081 uint16_t* dstPtr = (uint16_t*) dstRow;
82 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -070083 uint16_t p = srcPtr[0];
scroggocc2feb12015-08-14 08:32:46 -070084 uint8_t red = masks->getRed(p);
85 uint8_t green = masks->getGreen(p);
86 uint8_t blue = masks->getBlue(p);
87 dstPtr[i] = SkPack888ToRGB16(red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -070088 srcPtr += sampleX;
scroggocc2feb12015-08-14 08:32:46 -070089 }
90 return SkSwizzler::kOpaque_ResultAlpha;
91}
92
msaretteed039b2015-03-18 11:11:19 -070093static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_opaque(
msarett5406d6f2015-08-31 06:55:13 -070094 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
95 uint32_t startX, uint32_t sampleX) {
msarett74114382015-03-16 11:55:18 -070096
97 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -070098 srcRow += 3 * startX;
msarett74114382015-03-16 11:55:18 -070099 SkPMColor* dstPtr = (SkPMColor*) dstRow;
msarett5406d6f2015-08-31 06:55:13 -0700100 for (int i = 0; i < width; i++) {
101 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
msarett74114382015-03-16 11:55:18 -0700102 uint8_t red = masks->getRed(p);
103 uint8_t green = masks->getGreen(p);
104 uint8_t blue = masks->getBlue(p);
msarett5406d6f2015-08-31 06:55:13 -0700105 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
106 srcRow += 3 * sampleX;
msarett74114382015-03-16 11:55:18 -0700107 }
108 return SkSwizzler::kOpaque_ResultAlpha;
109}
110
msaretteed039b2015-03-18 11:11:19 -0700111static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_unpremul(
msarett5406d6f2015-08-31 06:55:13 -0700112 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
113 uint32_t startX, uint32_t sampleX) {
msarett74114382015-03-16 11:55:18 -0700114
115 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -0700116 srcRow += 3 * startX;
msarett74114382015-03-16 11:55:18 -0700117 SkPMColor* dstPtr = (SkPMColor*) dstRow;
118 INIT_RESULT_ALPHA;
119 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -0700120 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
msarett74114382015-03-16 11:55:18 -0700121 uint8_t red = masks->getRed(p);
122 uint8_t green = masks->getGreen(p);
123 uint8_t blue = masks->getBlue(p);
124 uint8_t alpha = masks->getAlpha(p);
125 UPDATE_RESULT_ALPHA(alpha);
126 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -0700127 srcRow += 3 * sampleX;
msarett74114382015-03-16 11:55:18 -0700128 }
129 return COMPUTE_RESULT_ALPHA;
130}
131
msarett5406d6f2015-08-31 06:55:13 -0700132static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul(
133 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
134 uint32_t startX, uint32_t sampleX) {
msaretteed039b2015-03-18 11:11:19 -0700135
136 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -0700137 srcRow += 3 * startX;
msaretteed039b2015-03-18 11:11:19 -0700138 SkPMColor* dstPtr = (SkPMColor*) dstRow;
139 INIT_RESULT_ALPHA;
140 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -0700141 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
msaretteed039b2015-03-18 11:11:19 -0700142 uint8_t red = masks->getRed(p);
143 uint8_t green = masks->getGreen(p);
144 uint8_t blue = masks->getBlue(p);
145 uint8_t alpha = masks->getAlpha(p);
146 UPDATE_RESULT_ALPHA(alpha);
147 dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -0700148 srcRow += 3 * sampleX;
149 }
150 return COMPUTE_RESULT_ALPHA;
151}
152
153static SkSwizzler::ResultAlpha swizzle_mask24_to_565(
154 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
155 uint32_t startX, uint32_t sampleX) {
156
157 // Use the masks to decode to the destination
158 srcRow += 3 * startX;
159 uint16_t* dstPtr = (uint16_t*) dstRow;
160 for (int i = 0; i < width; i++) {
161 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
162 uint8_t red = masks->getRed(p);
163 uint8_t green = masks->getGreen(p);
164 uint8_t blue = masks->getBlue(p);
165 dstPtr[i] = SkPack888ToRGB16(red, green, blue);
166 srcRow += 3 * sampleX;
167 }
168 return SkSwizzler::kOpaque_ResultAlpha;
169}
170
171static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque(
172 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
173 uint32_t startX, uint32_t sampleX) {
174
175 // Use the masks to decode to the destination
176 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
177 SkPMColor* dstPtr = (SkPMColor*) dstRow;
178 for (int i = 0; i < width; i++) {
179 uint32_t p = srcPtr[0];
180 uint8_t red = masks->getRed(p);
181 uint8_t green = masks->getGreen(p);
182 uint8_t blue = masks->getBlue(p);
183 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
184 srcPtr += sampleX;
185 }
186 return SkSwizzler::kOpaque_ResultAlpha;
187}
188
189static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul(
190 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
191 uint32_t startX, uint32_t sampleX) {
192
193 // Use the masks to decode to the destination
194 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
195 SkPMColor* dstPtr = (SkPMColor*) dstRow;
196 INIT_RESULT_ALPHA;
197 for (int i = 0; i < width; i++) {
198 uint32_t p = srcPtr[0];
199 uint8_t red = masks->getRed(p);
200 uint8_t green = masks->getGreen(p);
201 uint8_t blue = masks->getBlue(p);
202 uint8_t alpha = masks->getAlpha(p);
203 UPDATE_RESULT_ALPHA(alpha);
204 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
205 srcPtr += sampleX;
206 }
207 return COMPUTE_RESULT_ALPHA;
208}
209
210static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul(
211 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
212 uint32_t startX, uint32_t sampleX) {
213
214 // Use the masks to decode to the destination
215 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
216 SkPMColor* dstPtr = (SkPMColor*) dstRow;
217 INIT_RESULT_ALPHA;
218 for (int i = 0; i < width; i++) {
219 uint32_t p = srcPtr[0];
220 uint8_t red = masks->getRed(p);
221 uint8_t green = masks->getGreen(p);
222 uint8_t blue = masks->getBlue(p);
223 uint8_t alpha = masks->getAlpha(p);
224 UPDATE_RESULT_ALPHA(alpha);
225 dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
226 srcPtr += sampleX;
msaretteed039b2015-03-18 11:11:19 -0700227 }
228 return COMPUTE_RESULT_ALPHA;
229}
230
scroggocc2feb12015-08-14 08:32:46 -0700231static SkSwizzler::ResultAlpha swizzle_mask32_to_565(
msarett5406d6f2015-08-31 06:55:13 -0700232 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
233 uint32_t startX, uint32_t sampleX) {
scroggocc2feb12015-08-14 08:32:46 -0700234 // Use the masks to decode to the destination
msarett5406d6f2015-08-31 06:55:13 -0700235 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
scroggocc2feb12015-08-14 08:32:46 -0700236 uint16_t* dstPtr = (uint16_t*) dstRow;
237 for (int i = 0; i < width; i++) {
msarett5406d6f2015-08-31 06:55:13 -0700238 uint32_t p = srcPtr[0];
scroggocc2feb12015-08-14 08:32:46 -0700239 uint8_t red = masks->getRed(p);
240 uint8_t green = masks->getGreen(p);
241 uint8_t blue = masks->getBlue(p);
242 dstPtr[i] = SkPack888ToRGB16(red, green, blue);
msarett5406d6f2015-08-31 06:55:13 -0700243 srcPtr += sampleX;
scroggocc2feb12015-08-14 08:32:46 -0700244 }
245 return SkSwizzler::kOpaque_ResultAlpha;
246}
247
msarett74114382015-03-16 11:55:18 -0700248/*
249 *
250 * Create a new mask swizzler
251 *
252 */
msarettfdb47572015-10-13 12:50:14 -0700253SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(const SkImageInfo& dstInfo,
254 const SkImageInfo& srcInfo, SkMasks* masks, uint32_t bitsPerPixel,
255 const SkCodec::Options& options) {
msarett74114382015-03-16 11:55:18 -0700256
257 // Choose the appropriate row procedure
halcanary96fcdcc2015-08-27 07:41:13 -0700258 RowProc proc = nullptr;
msarett74114382015-03-16 11:55:18 -0700259 switch (bitsPerPixel) {
260 case 16:
msarett5406d6f2015-08-31 06:55:13 -0700261 switch (dstInfo.colorType()) {
msaretteed039b2015-03-18 11:11:19 -0700262 case kN32_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700263 switch (dstInfo.alphaType()) {
msaretteed039b2015-03-18 11:11:19 -0700264 case kUnpremul_SkAlphaType:
265 proc = &swizzle_mask16_to_n32_unpremul;
266 break;
267 case kPremul_SkAlphaType:
268 proc = &swizzle_mask16_to_n32_premul;
269 break;
270 case kOpaque_SkAlphaType:
271 proc = &swizzle_mask16_to_n32_opaque;
272 break;
273 default:
274 break;
275 }
276 break;
scroggocc2feb12015-08-14 08:32:46 -0700277 case kRGB_565_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700278 switch (dstInfo.alphaType()) {
scroggocc2feb12015-08-14 08:32:46 -0700279 case kOpaque_SkAlphaType:
280 proc = &swizzle_mask16_to_565;
281 break;
282 default:
283 break;
284 }
285 break;
msaretteed039b2015-03-18 11:11:19 -0700286 default:
287 break;
msarett74114382015-03-16 11:55:18 -0700288 }
289 break;
290 case 24:
msarett5406d6f2015-08-31 06:55:13 -0700291 switch (dstInfo.colorType()) {
msaretteed039b2015-03-18 11:11:19 -0700292 case kN32_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700293 switch (dstInfo.alphaType()) {
msaretteed039b2015-03-18 11:11:19 -0700294 case kUnpremul_SkAlphaType:
295 proc = &swizzle_mask24_to_n32_unpremul;
296 break;
297 case kPremul_SkAlphaType:
298 proc = &swizzle_mask24_to_n32_premul;
299 break;
300 case kOpaque_SkAlphaType:
301 proc = &swizzle_mask24_to_n32_opaque;
302 break;
303 default:
304 break;
305 }
306 break;
scroggocc2feb12015-08-14 08:32:46 -0700307 case kRGB_565_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700308 switch (dstInfo.alphaType()) {
scroggocc2feb12015-08-14 08:32:46 -0700309 case kOpaque_SkAlphaType:
310 proc = &swizzle_mask24_to_565;
311 break;
312 default:
313 break;
314 }
315 break;
msaretteed039b2015-03-18 11:11:19 -0700316 default:
317 break;
msarett74114382015-03-16 11:55:18 -0700318 }
319 break;
320 case 32:
msarett5406d6f2015-08-31 06:55:13 -0700321 switch (dstInfo.colorType()) {
msaretteed039b2015-03-18 11:11:19 -0700322 case kN32_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700323 switch (dstInfo.alphaType()) {
msaretteed039b2015-03-18 11:11:19 -0700324 case kUnpremul_SkAlphaType:
325 proc = &swizzle_mask32_to_n32_unpremul;
326 break;
327 case kPremul_SkAlphaType:
328 proc = &swizzle_mask32_to_n32_premul;
329 break;
330 case kOpaque_SkAlphaType:
331 proc = &swizzle_mask32_to_n32_opaque;
332 break;
333 default:
334 break;
335 }
336 break;
scroggocc2feb12015-08-14 08:32:46 -0700337 case kRGB_565_SkColorType:
msarett5406d6f2015-08-31 06:55:13 -0700338 switch (dstInfo.alphaType()) {
scroggocc2feb12015-08-14 08:32:46 -0700339 case kOpaque_SkAlphaType:
340 proc = &swizzle_mask32_to_565;
341 break;
342 default:
343 break;
344 }
345 break;
msaretteed039b2015-03-18 11:11:19 -0700346 default:
347 break;
msarett74114382015-03-16 11:55:18 -0700348 }
349 break;
350 default:
351 SkASSERT(false);
halcanary96fcdcc2015-08-27 07:41:13 -0700352 return nullptr;
msarett74114382015-03-16 11:55:18 -0700353 }
msarett5406d6f2015-08-31 06:55:13 -0700354
msarettfdb47572015-10-13 12:50:14 -0700355 int srcOffset = 0;
356 int srcWidth = dstInfo.width();
357 if (options.fSubset) {
358 srcOffset = options.fSubset->left();
359 srcWidth = options.fSubset->width();
360 }
361
362 return new SkMaskSwizzler(masks, proc, srcOffset, srcWidth);
msarett74114382015-03-16 11:55:18 -0700363}
364
365/*
366 *
367 * Constructor for mask swizzler
368 *
369 */
msarettfdb47572015-10-13 12:50:14 -0700370SkMaskSwizzler::SkMaskSwizzler(SkMasks* masks, RowProc proc, int srcOffset, int srcWidth)
scroggoe7fc14b2015-10-02 13:14:46 -0700371 : fMasks(masks)
msarett74114382015-03-16 11:55:18 -0700372 , fRowProc(proc)
msarettfdb47572015-10-13 12:50:14 -0700373 , fSrcWidth(srcWidth)
374 , fDstWidth(srcWidth)
scroggoe7fc14b2015-10-02 13:14:46 -0700375 , fSampleX(1)
msarettfdb47572015-10-13 12:50:14 -0700376 , fSrcOffset(srcOffset)
377 , fX0(srcOffset)
msarett74114382015-03-16 11:55:18 -0700378{}
379
scroggoe7fc14b2015-10-02 13:14:46 -0700380int SkMaskSwizzler::onSetSampleX(int sampleX) {
381 // FIXME: Share this function with SkSwizzler?
382 SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be
383 // way to report failure?
384 fSampleX = sampleX;
msarettfdb47572015-10-13 12:50:14 -0700385 fX0 = get_start_coord(sampleX) + fSrcOffset;
scroggoe7fc14b2015-10-02 13:14:46 -0700386 fDstWidth = get_scaled_dimension(fSrcWidth, sampleX);
387
388 // check that fX0 is less than original width
389 SkASSERT(fX0 >= 0 && fX0 < fSrcWidth);
390 return fDstWidth;
391}
392
msarett74114382015-03-16 11:55:18 -0700393/*
394 *
msaretteed039b2015-03-18 11:11:19 -0700395 * Swizzle the specified row
msarett74114382015-03-16 11:55:18 -0700396 *
397 */
msarett614aa072015-07-27 15:13:17 -0700398SkSwizzler::ResultAlpha SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
halcanary96fcdcc2015-08-27 07:41:13 -0700399 SkASSERT(nullptr != dst && nullptr != src);
scroggoe7fc14b2015-10-02 13:14:46 -0700400 return fRowProc(dst, src, fDstWidth, fMasks, fX0, fSampleX);
msarett74114382015-03-16 11:55:18 -0700401}