• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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