blob: 15f44327a7071d9c29d88a8d193af7126c020903 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
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
24static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow,
25 const uint8_t* SK_RESTRICT src,
26 int width, int deltaSrc, int) {
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
35static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow,
36 const uint8_t* SK_RESTRICT src,
37 int width, int deltaSrc, int) {
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
46static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow,
47 const uint8_t* SK_RESTRICT src,
48 int width, int deltaSrc, int) {
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
62static bool Sample_Gray_D565(void* SK_RESTRICT dstRow,
63 const uint8_t* SK_RESTRICT src,
64 int width, int deltaSrc, int) {
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
73static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow,
74 const uint8_t* SK_RESTRICT src,
75 int width, int deltaSrc, int y) {
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
85static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
86 const uint8_t* SK_RESTRICT src,
87 int width, int deltaSrc, int) {
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
96static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
97 const uint8_t* SK_RESTRICT src,
98 int width, int deltaSrc, int y) {
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
110static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow,
111 const uint8_t* SK_RESTRICT src,
112 int width, int deltaSrc, int) {
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
122static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow,
123 const uint8_t* SK_RESTRICT src,
124 int width, int deltaSrc, int y) {
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
135static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow,
136 const uint8_t* SK_RESTRICT src,
137 int width, int deltaSrc, int) {
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
146static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow,
147 const uint8_t* SK_RESTRICT src,
148 int width, int deltaSrc, int y) {
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
160static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow,
161 const uint8_t* SK_RESTRICT src,
162 int width, int deltaSrc, int) {
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
176static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow,
177 const uint8_t* SK_RESTRICT src,
178 int width, int deltaSrc, int y) {
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
195static bool Sample_Index_DI(void* SK_RESTRICT dstRow,
196 const uint8_t* SK_RESTRICT src,
197 int width, int deltaSrc, int) {
198 if (1 == deltaSrc) {
199 memcpy(dstRow, src, width);
200 } else {
201 uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow;
202 for (int x = 0; x < width; x++) {
203 dst[x] = src[0];
204 src += deltaSrc;
205 }
206 }
207 return false;
208}
209
210///////////////////////////////////////////////////////////////////////////////
211
212#include "SkScaledBitmapSampler.h"
213
214SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height,
215 int sampleSize) {
216 if (width <= 0 || height <= 0) {
217 sk_throw();
218 }
219
220 if (sampleSize <= 1) {
221 fScaledWidth = width;
222 fScaledHeight = height;
223 fX0 = fY0 = 0;
224 fDX = fDY = 1;
225 return;
226 }
227
228 int dx = SkMin32(sampleSize, width);
229 int dy = SkMin32(sampleSize, height);
230
231 fScaledWidth = width / dx;
232 fScaledHeight = height / dy;
233
234 SkASSERT(fScaledWidth > 0);
235 SkASSERT(fScaledHeight > 0);
236
237 fX0 = dx >> 1;
238 fY0 = dy >> 1;
239
240 SkASSERT(fX0 >= 0 && fX0 < width);
241 SkASSERT(fY0 >= 0 && fY0 < height);
242
243 fDX = dx;
244 fDY = dy;
245
246 SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width);
247 SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height);
248
249 fRowProc = NULL;
250}
251
252bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither) {
253 static const RowProc gProcs[] = {
254 // 8888 (no dither distinction)
255 Sample_Gray_D8888, Sample_Gray_D8888,
256 Sample_RGBx_D8888, Sample_RGBx_D8888,
257 Sample_RGBA_D8888, Sample_RGBA_D8888,
258 NULL, NULL,
259 // 565 (no alpha distinction)
260 Sample_Gray_D565, Sample_Gray_D565_D,
261 Sample_RGBx_D565, Sample_RGBx_D565_D,
262 Sample_RGBx_D565, Sample_RGBx_D565_D,
263 NULL, NULL,
264 // 4444
265 Sample_Gray_D4444, Sample_Gray_D4444_D,
266 Sample_RGBx_D4444, Sample_RGBx_D4444_D,
267 Sample_RGBA_D4444, Sample_RGBA_D4444_D,
268 NULL, NULL,
269 // Index8
270 NULL, NULL,
271 NULL, NULL,
272 NULL, NULL,
273 Sample_Index_DI, Sample_Index_DI,
274 };
275
276
277 int index = 0;
278 if (dither) {
279 index += 1;
280 }
281 switch (sc) {
282 case SkScaledBitmapSampler::kGray:
283 fSrcPixelSize = 1;
284 index += 0;
285 break;
286 case SkScaledBitmapSampler::kRGB:
287 fSrcPixelSize = 3;
288 index += 2;
289 break;
290 case SkScaledBitmapSampler::kRGBX:
291 fSrcPixelSize = 4;
292 index += 2;
293 break;
294 case SkScaledBitmapSampler::kRGBA:
295 fSrcPixelSize = 4;
296 index += 4;
297 break;
298 case SkScaledBitmapSampler::kIndex:
299 fSrcPixelSize = 1;
300 index += 6;
301 break;
302 default:
303 return false;
304 }
305
306 switch (dst->config()) {
307 case SkBitmap::kARGB_8888_Config:
308 index += 0;
309 break;
310 case SkBitmap::kRGB_565_Config:
311 index += 8;
312 break;
313 case SkBitmap::kARGB_4444_Config:
314 index += 16;
315 break;
316 case SkBitmap::kIndex8_Config:
317 index += 24;
318 break;
319 default:
320 return false;
321 }
322
323 fRowProc = gProcs[index];
324 fDstRow = (char*)dst->getPixels();
325 fDstRowBytes = dst->rowBytes();
326 fCurrY = 0;
327 return fRowProc != NULL;
328}
329
330bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) {
331 SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight);
332
333 bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
334 fDX * fSrcPixelSize, fCurrY);
335 fDstRow += fDstRowBytes;
336 fCurrY += 1;
337 return hadAlpha;
338}