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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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