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