OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2013 Google Inc. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. |
| 6 */ |
| 7 |
| 8 #include "SkBitmapProcBicubic.h" |
| 9 #include "SkBitmap.h" |
| 10 #include "SkColor.h" |
| 11 #include "SkColorPriv.h" |
| 12 #include "SkUnPreMultiply.h" |
| 13 #include "SkRTConf.h" |
| 14 #include "SkShader.h" |
| 15 |
| 16 #define DS(x) SkDoubleToScalar(x) |
| 17 |
| 18 inline SkPMColor cubicBlend(const SkScalar c[16], SkScalar t, SkPMColor c0, SkPM
Color c1, SkPMColor c2, SkPMColor c3) { |
| 19 SkScalar t2 = t * t, t3 = t2 * t; |
| 20 SkScalar cc[4]; |
| 21 cc[0] = c[0] + SkScalarMul(c[1], t) + SkScalarMul(c[2], t2) + SkScalarMul(c
[3], t3); |
| 22 cc[1] = c[4] + SkScalarMul(c[5], t) + SkScalarMul(c[6], t2) + SkScalarMul(c
[7], t3); |
| 23 cc[2] = c[8] + SkScalarMul(c[9], t) + SkScalarMul(c[10], t2) + SkScalarMul(
c[11], t3); |
| 24 cc[3] = c[12] + SkScalarMul(c[13], t) + SkScalarMul(c[14], t2) + SkScalarMul
(c[15], t3); |
| 25 SkScalar a = SkScalarClampMax(SkScalarMul(cc[0], SkGetPackedA32(c0)) + SkSca
larMul(cc[1], SkGetPackedA32(c1)) + SkScalarMul(cc[2], SkGetPackedA32(c2)) + SkS
calarMul(cc[3], SkGetPackedA32(c3)), 255); |
| 26 SkScalar r = SkScalarMul(cc[0], SkGetPackedR32(c0)) + SkScalarMul(cc[1], SkG
etPackedR32(c1)) + SkScalarMul(cc[2], SkGetPackedR32(c2)) + SkScalarMul(cc[3], S
kGetPackedR32(c3)); |
| 27 SkScalar g = SkScalarMul(cc[0], SkGetPackedG32(c0)) + SkScalarMul(cc[1], SkG
etPackedG32(c1)) + SkScalarMul(cc[2], SkGetPackedG32(c2)) + SkScalarMul(cc[3], S
kGetPackedG32(c3)); |
| 28 SkScalar b = SkScalarMul(cc[0], SkGetPackedB32(c0)) + SkScalarMul(cc[1], SkG
etPackedB32(c1)) + SkScalarMul(cc[2], SkGetPackedB32(c2)) + SkScalarMul(cc[3], S
kGetPackedB32(c3)); |
| 29 return SkPackARGB32(SkScalarRoundToInt(a), |
| 30 SkScalarRoundToInt(SkScalarClampMax(r, a)), |
| 31 SkScalarRoundToInt(SkScalarClampMax(g, a)), |
| 32 SkScalarRoundToInt(SkScalarClampMax(b, a))); |
| 33 } |
| 34 |
| 35 static void bicubicFilter(const SkBitmapProcState& s, int x, int y, |
| 36 SkPMColor colors[], int count) { |
| 37 |
| 38 static const SkScalar coefficients[16] = { |
| 39 DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0), |
| 40 DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0), |
| 41 DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0), |
| 42 DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0), |
| 43 }; |
| 44 |
| 45 SkPMColor *dptr = &(colors[0]); |
| 46 while (count-- > 0) { |
| 47 SkPoint srcPt; |
| 48 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x), |
| 49 SkIntToScalar(y), &srcPt); |
| 50 srcPt.fX -= SK_ScalarHalf; |
| 51 srcPt.fY -= SK_ScalarHalf; |
| 52 SkScalar fractx = srcPt.fX - SkScalarFloorToScalar(srcPt.fX); |
| 53 SkScalar fracty = srcPt.fY - SkScalarFloorToScalar(srcPt.fY); |
| 54 int sx = SkScalarFloorToInt(srcPt.fX); |
| 55 int sy = SkScalarFloorToInt(srcPt.fY); |
| 56 int x0 = SkClampMax(sx - 1, s.fBitmap->width() - 1); |
| 57 int x1 = SkClampMax(sx , s.fBitmap->width() - 1); |
| 58 int x2 = SkClampMax(sx + 1, s.fBitmap->width() - 1); |
| 59 int x3 = SkClampMax(sx + 2, s.fBitmap->width() - 1); |
| 60 int y0 = SkClampMax(sy - 1, s.fBitmap->height() - 1); |
| 61 int y1 = SkClampMax(sy , s.fBitmap->height() - 1); |
| 62 int y2 = SkClampMax(sy + 1, s.fBitmap->height() - 1); |
| 63 int y3 = SkClampMax(sy + 2, s.fBitmap->height() - 1); |
| 64 SkPMColor s00 = *s.fBitmap->getAddr32(x0, y0); |
| 65 SkPMColor s10 = *s.fBitmap->getAddr32(x1, y0); |
| 66 SkPMColor s20 = *s.fBitmap->getAddr32(x2, y0); |
| 67 SkPMColor s30 = *s.fBitmap->getAddr32(x3, y0); |
| 68 SkPMColor s0 = cubicBlend(coefficients, fractx, s00, s10, s20, s30); |
| 69 SkPMColor s01 = *s.fBitmap->getAddr32(x0, y1); |
| 70 SkPMColor s11 = *s.fBitmap->getAddr32(x1, y1); |
| 71 SkPMColor s21 = *s.fBitmap->getAddr32(x2, y1); |
| 72 SkPMColor s31 = *s.fBitmap->getAddr32(x3, y1); |
| 73 SkPMColor s1 = cubicBlend(coefficients, fractx, s01, s11, s21, s31); |
| 74 SkPMColor s02 = *s.fBitmap->getAddr32(x0, y2); |
| 75 SkPMColor s12 = *s.fBitmap->getAddr32(x1, y2); |
| 76 SkPMColor s22 = *s.fBitmap->getAddr32(x2, y2); |
| 77 SkPMColor s32 = *s.fBitmap->getAddr32(x3, y2); |
| 78 SkPMColor s2 = cubicBlend(coefficients, fractx, s02, s12, s22, s32); |
| 79 SkPMColor s03 = *s.fBitmap->getAddr32(x0, y3); |
| 80 SkPMColor s13 = *s.fBitmap->getAddr32(x1, y3); |
| 81 SkPMColor s23 = *s.fBitmap->getAddr32(x2, y3); |
| 82 SkPMColor s33 = *s.fBitmap->getAddr32(x3, y3); |
| 83 SkPMColor s3 = cubicBlend(coefficients, fractx, s03, s13, s23, s33); |
| 84 *dptr++ = cubicBlend(coefficients, fracty, s0, s1, s2, s3); |
| 85 x++; |
| 86 } |
| 87 } |
| 88 |
| 89 SkBitmapProcState::ShaderProc32 |
| 90 SkBitmapProcState::chooseBicubicFilterProc(const SkPaint& paint) { |
| 91 // we need to be requested |
| 92 uint32_t mask = SkPaint::kFilterBitmap_Flag |
| 93 | SkPaint::kBicubicFilterBitmap_Flag |
| 94 ; |
| 95 if ((paint.getFlags() & mask) != mask) { |
| 96 return NULL; |
| 97 } |
| 98 |
| 99 // TODO: consider supporting other configs (e.g. 565, A8) |
| 100 if (fBitmap->config() != SkBitmap::kARGB_8888_Config) { |
| 101 return NULL; |
| 102 } |
| 103 |
| 104 // TODO: consider supporting repeat and mirror |
| 105 if (SkShader::kClamp_TileMode != fTileModeX || SkShader::kClamp_TileMode !=
fTileModeY) { |
| 106 return NULL; |
| 107 } |
| 108 |
| 109 // TODO: support blending inside our procs |
| 110 if (0xFF != paint.getAlpha()) { |
| 111 return NULL; |
| 112 } |
| 113 |
| 114 return bicubicFilter; |
| 115 } |
OLD | NEW |