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