1
2 /*
3 * Copyright 2007 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 "SkScaledBitmapSampler.h"
11 #include "SkBitmap.h"
12 #include "SkColorPriv.h"
13 #include "SkDither.h"
14
15 // 8888
16
Sample_Gray_D8888(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor[])17 static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow,
18 const uint8_t* SK_RESTRICT src,
19 int width, int deltaSrc, int, const SkPMColor[]) {
20 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
21 for (int x = 0; x < width; x++) {
22 dst[x] = SkPackARGB32(0xFF, src[0], src[0], src[0]);
23 src += deltaSrc;
24 }
25 return false;
26 }
27
Sample_RGBx_D8888(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor[])28 static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow,
29 const uint8_t* SK_RESTRICT src,
30 int width, int deltaSrc, int, const SkPMColor[]) {
31 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
32 for (int x = 0; x < width; x++) {
33 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
34 src += deltaSrc;
35 }
36 return false;
37 }
38
Sample_RGBA_D8888(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor[])39 static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow,
40 const uint8_t* SK_RESTRICT src,
41 int width, int deltaSrc, int, const SkPMColor[]) {
42 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
43 unsigned alphaMask = 0xFF;
44 for (int x = 0; x < width; x++) {
45 unsigned alpha = src[3];
46 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
47 src += deltaSrc;
48 alphaMask &= alpha;
49 }
50 return alphaMask != 0xFF;
51 }
52
53 // 565
54
Sample_Gray_D565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor[])55 static bool Sample_Gray_D565(void* SK_RESTRICT dstRow,
56 const uint8_t* SK_RESTRICT src,
57 int width, int deltaSrc, int, const SkPMColor[]) {
58 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
59 for (int x = 0; x < width; x++) {
60 dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
61 src += deltaSrc;
62 }
63 return false;
64 }
65
Sample_Gray_D565_D(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int y,const SkPMColor[])66 static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow,
67 const uint8_t* SK_RESTRICT src,
68 int width, int deltaSrc, int y, const SkPMColor[]) {
69 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
70 DITHER_565_SCAN(y);
71 for (int x = 0; x < width; x++) {
72 dst[x] = SkDitherRGBTo565(src[0], src[0], src[0], DITHER_VALUE(x));
73 src += deltaSrc;
74 }
75 return false;
76 }
77
Sample_RGBx_D565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor[])78 static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
79 const uint8_t* SK_RESTRICT src,
80 int width, int deltaSrc, int, const SkPMColor[]) {
81 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
82 for (int x = 0; x < width; x++) {
83 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
84 src += deltaSrc;
85 }
86 return false;
87 }
88
Sample_D565_D565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor[])89 static bool Sample_D565_D565(void* SK_RESTRICT dstRow,
90 const uint8_t* SK_RESTRICT src,
91 int width, int deltaSrc, int, const SkPMColor[]) {
92 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
93 uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src;
94 for (int x = 0; x < width; x++) {
95 dst[x] = castedSrc[0];
96 castedSrc += deltaSrc >> 1;
97 }
98 return false;
99 }
100
Sample_RGBx_D565_D(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int y,const SkPMColor[])101 static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
102 const uint8_t* SK_RESTRICT src,
103 int width, int deltaSrc, int y, const SkPMColor[]) {
104 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
105 DITHER_565_SCAN(y);
106 for (int x = 0; x < width; x++) {
107 dst[x] = SkDitherRGBTo565(src[0], src[1], src[2], DITHER_VALUE(x));
108 src += deltaSrc;
109 }
110 return false;
111 }
112
113 // 4444
114
Sample_Gray_D4444(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor[])115 static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow,
116 const uint8_t* SK_RESTRICT src,
117 int width, int deltaSrc, int, const SkPMColor[]) {
118 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
119 for (int x = 0; x < width; x++) {
120 unsigned gray = src[0] >> 4;
121 dst[x] = SkPackARGB4444(0xF, gray, gray, gray);
122 src += deltaSrc;
123 }
124 return false;
125 }
126
Sample_Gray_D4444_D(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int y,const SkPMColor[])127 static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow,
128 const uint8_t* SK_RESTRICT src,
129 int width, int deltaSrc, int y, const SkPMColor[]) {
130 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
131 DITHER_4444_SCAN(y);
132 for (int x = 0; x < width; x++) {
133 dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[0], src[0],
134 DITHER_VALUE(x));
135 src += deltaSrc;
136 }
137 return false;
138 }
139
Sample_RGBx_D4444(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor[])140 static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow,
141 const uint8_t* SK_RESTRICT src,
142 int width, int deltaSrc, int, const SkPMColor[]) {
143 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
144 for (int x = 0; x < width; x++) {
145 dst[x] = SkPackARGB4444(0xF, src[0] >> 4, src[1] >> 4, src[2] >> 4);
146 src += deltaSrc;
147 }
148 return false;
149 }
150
Sample_RGBx_D4444_D(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int y,const SkPMColor[])151 static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow,
152 const uint8_t* SK_RESTRICT src,
153 int width, int deltaSrc, int y, const SkPMColor[]) {
154 SkPMColor16* dst = (SkPMColor16*)dstRow;
155 DITHER_4444_SCAN(y);
156
157 for (int x = 0; x < width; x++) {
158 dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[1], src[2],
159 DITHER_VALUE(x));
160 src += deltaSrc;
161 }
162 return false;
163 }
164
Sample_RGBA_D4444(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor[])165 static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow,
166 const uint8_t* SK_RESTRICT src,
167 int width, int deltaSrc, int, const SkPMColor[]) {
168 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
169 unsigned alphaMask = 0xFF;
170
171 for (int x = 0; x < width; x++) {
172 unsigned alpha = src[3];
173 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
174 dst[x] = SkPixel32ToPixel4444(c);
175 src += deltaSrc;
176 alphaMask &= alpha;
177 }
178 return alphaMask != 0xFF;
179 }
180
Sample_RGBA_D4444_D(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int y,const SkPMColor[])181 static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow,
182 const uint8_t* SK_RESTRICT src,
183 int width, int deltaSrc, int y, const SkPMColor[]) {
184 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
185 unsigned alphaMask = 0xFF;
186 DITHER_4444_SCAN(y);
187
188 for (int x = 0; x < width; x++) {
189 unsigned alpha = src[3];
190 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
191 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
192 src += deltaSrc;
193 alphaMask &= alpha;
194 }
195 return alphaMask != 0xFF;
196 }
197
198 // Index
199
200 #define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT)
201
Sample_Index_D8888(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor ctable[])202 static bool Sample_Index_D8888(void* SK_RESTRICT dstRow,
203 const uint8_t* SK_RESTRICT src,
204 int width, int deltaSrc, int, const SkPMColor ctable[]) {
205
206 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
207 SkPMColor cc = A32_MASK_IN_PLACE;
208 for (int x = 0; x < width; x++) {
209 SkPMColor c = ctable[*src];
210 cc &= c;
211 dst[x] = c;
212 src += deltaSrc;
213 }
214 return cc != A32_MASK_IN_PLACE;
215 }
216
Sample_Index_D565(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor ctable[])217 static bool Sample_Index_D565(void* SK_RESTRICT dstRow,
218 const uint8_t* SK_RESTRICT src,
219 int width, int deltaSrc, int, const SkPMColor ctable[]) {
220
221 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
222 for (int x = 0; x < width; x++) {
223 dst[x] = SkPixel32ToPixel16(ctable[*src]);
224 src += deltaSrc;
225 }
226 return false;
227 }
228
Sample_Index_D565_D(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int y,const SkPMColor ctable[])229 static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow,
230 const uint8_t* SK_RESTRICT src, int width,
231 int deltaSrc, int y, const SkPMColor ctable[]) {
232
233 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
234 DITHER_565_SCAN(y);
235
236 for (int x = 0; x < width; x++) {
237 SkPMColor c = ctable[*src];
238 dst[x] = SkDitherRGBTo565(SkGetPackedR32(c), SkGetPackedG32(c),
239 SkGetPackedB32(c), DITHER_VALUE(x));
240 src += deltaSrc;
241 }
242 return false;
243 }
244
Sample_Index_D4444(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int y,const SkPMColor ctable[])245 static bool Sample_Index_D4444(void* SK_RESTRICT dstRow,
246 const uint8_t* SK_RESTRICT src, int width,
247 int deltaSrc, int y, const SkPMColor ctable[]) {
248
249 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
250 SkPMColor cc = A32_MASK_IN_PLACE;
251 for (int x = 0; x < width; x++) {
252 SkPMColor c = ctable[*src];
253 cc &= c;
254 dst[x] = SkPixel32ToPixel4444(c);
255 src += deltaSrc;
256 }
257 return cc != A32_MASK_IN_PLACE;
258 }
259
Sample_Index_D4444_D(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int y,const SkPMColor ctable[])260 static bool Sample_Index_D4444_D(void* SK_RESTRICT dstRow,
261 const uint8_t* SK_RESTRICT src, int width,
262 int deltaSrc, int y, const SkPMColor ctable[]) {
263
264 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
265 SkPMColor cc = A32_MASK_IN_PLACE;
266 DITHER_4444_SCAN(y);
267
268 for (int x = 0; x < width; x++) {
269 SkPMColor c = ctable[*src];
270 cc &= c;
271 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
272 src += deltaSrc;
273 }
274 return cc != A32_MASK_IN_PLACE;
275 }
276
Sample_Index_DI(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int deltaSrc,int,const SkPMColor[])277 static bool Sample_Index_DI(void* SK_RESTRICT dstRow,
278 const uint8_t* SK_RESTRICT src,
279 int width, int deltaSrc, int, const SkPMColor[]) {
280 if (1 == deltaSrc) {
281 memcpy(dstRow, src, width);
282 } else {
283 uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow;
284 for (int x = 0; x < width; x++) {
285 dst[x] = src[0];
286 src += deltaSrc;
287 }
288 }
289 return false;
290 }
291
292 ///////////////////////////////////////////////////////////////////////////////
293
294 #include "SkScaledBitmapSampler.h"
295
SkScaledBitmapSampler(int width,int height,int sampleSize)296 SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height,
297 int sampleSize) {
298 if (width <= 0 || height <= 0) {
299 sk_throw();
300 }
301
302 if (sampleSize <= 1) {
303 fScaledWidth = width;
304 fScaledHeight = height;
305 fX0 = fY0 = 0;
306 fDX = fDY = 1;
307 return;
308 }
309
310 int dx = SkMin32(sampleSize, width);
311 int dy = SkMin32(sampleSize, height);
312
313 fScaledWidth = width / dx;
314 fScaledHeight = height / dy;
315
316 SkASSERT(fScaledWidth > 0);
317 SkASSERT(fScaledHeight > 0);
318
319 fX0 = dx >> 1;
320 fY0 = dy >> 1;
321
322 SkASSERT(fX0 >= 0 && fX0 < width);
323 SkASSERT(fY0 >= 0 && fY0 < height);
324
325 fDX = dx;
326 fDY = dy;
327
328 SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width);
329 SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height);
330
331 fRowProc = NULL;
332 fCTable = NULL;
333 }
334
begin(SkBitmap * dst,SrcConfig sc,bool dither,const SkPMColor ctable[])335 bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
336 const SkPMColor ctable[]) {
337 static const RowProc gProcs[] = {
338 // 8888 (no dither distinction)
339 Sample_Gray_D8888, Sample_Gray_D8888,
340 Sample_RGBx_D8888, Sample_RGBx_D8888,
341 Sample_RGBA_D8888, Sample_RGBA_D8888,
342 Sample_Index_D8888, Sample_Index_D8888,
343 NULL, NULL,
344 // 565 (no alpha distinction)
345 Sample_Gray_D565, Sample_Gray_D565_D,
346 Sample_RGBx_D565, Sample_RGBx_D565_D,
347 Sample_RGBx_D565, Sample_RGBx_D565_D,
348 Sample_Index_D565, Sample_Index_D565_D,
349 Sample_D565_D565, Sample_D565_D565,
350 // 4444
351 Sample_Gray_D4444, Sample_Gray_D4444_D,
352 Sample_RGBx_D4444, Sample_RGBx_D4444_D,
353 Sample_RGBA_D4444, Sample_RGBA_D4444_D,
354 Sample_Index_D4444, Sample_Index_D4444_D,
355 NULL, NULL,
356 // Index8
357 NULL, NULL,
358 NULL, NULL,
359 NULL, NULL,
360 Sample_Index_DI, Sample_Index_DI,
361 NULL, NULL,
362 };
363
364 fCTable = ctable;
365
366 int index = 0;
367 if (dither) {
368 index += 1;
369 }
370 switch (sc) {
371 case SkScaledBitmapSampler::kGray:
372 fSrcPixelSize = 1;
373 index += 0;
374 break;
375 case SkScaledBitmapSampler::kRGB:
376 fSrcPixelSize = 3;
377 index += 2;
378 break;
379 case SkScaledBitmapSampler::kRGBX:
380 fSrcPixelSize = 4;
381 index += 2;
382 break;
383 case SkScaledBitmapSampler::kRGBA:
384 fSrcPixelSize = 4;
385 index += 4;
386 break;
387 case SkScaledBitmapSampler::kIndex:
388 fSrcPixelSize = 1;
389 index += 6;
390 break;
391 case SkScaledBitmapSampler::kRGB_565:
392 fSrcPixelSize = 2;
393 index += 8;
394 break;
395 default:
396 return false;
397 }
398
399 switch (dst->config()) {
400 case SkBitmap::kARGB_8888_Config:
401 index += 0;
402 break;
403 case SkBitmap::kRGB_565_Config:
404 index += 10;
405 break;
406 case SkBitmap::kARGB_4444_Config:
407 index += 20;
408 break;
409 case SkBitmap::kIndex8_Config:
410 index += 30;
411 break;
412 default:
413 return false;
414 }
415
416 fRowProc = gProcs[index];
417 fDstRow = (char*)dst->getPixels();
418 fDstRowBytes = dst->rowBytes();
419 fCurrY = 0;
420 return fRowProc != NULL;
421 }
422
next(const uint8_t * SK_RESTRICT src)423 bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) {
424 SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight);
425
426 bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
427 fDX * fSrcPixelSize, fCurrY, fCTable);
428 fDstRow += fDstRowBytes;
429 fCurrY += 1;
430 return hadAlpha;
431 }
432