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