Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: src/core/SkBitmapFilter.cpp

Issue 18978014: Working plumb of image scaling: (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: No need to special case scale=1 Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkBitmapProcState.h" 8 #include "SkBitmapProcState.h"
9 #include "SkBitmap.h" 9 #include "SkBitmap.h"
10 #include "SkColor.h" 10 #include "SkColor.h"
11 #include "SkColorPriv.h" 11 #include "SkColorPriv.h"
12 #include "SkUnPreMultiply.h" 12 #include "SkUnPreMultiply.h"
13 #include "SkShader.h" 13 #include "SkShader.h"
14 #include "SkRTConf.h" 14 #include "SkRTConf.h"
15 #include "SkMath.h" 15 #include "SkMath.h"
16 16
17 void highQualityFilter(const SkBitmapProcState& s, int x, int y, 17 void highQualityFilter(const SkBitmapProcState& s, int x, int y,
18 SkPMColor* SK_RESTRICT colors, int count) { 18 SkPMColor* SK_RESTRICT colors, int count) {
19 19
20 const int maxX = s.fBitmap->width() - 1; 20 const int maxX = s.fBitmap->width() - 1;
21 const int maxY = s.fBitmap->height() - 1; 21 const int maxY = s.fBitmap->height() - 1;
22 22
23 while (count-- > 0) { 23 while (count-- > 0) {
24 SkPoint srcPt; 24 SkPoint srcPt;
25 s.fInvProc(*s.fInvMatrix, SkFloatToScalar(x + 0.5f), 25 s.fInvProc(*s.fInvMatrix, SkFloatToScalar(x + 0.5f),
26 SkFloatToScalar(y + 0.5f), &srcPt); 26 SkFloatToScalar(y + 0.5f), &srcPt);
27 srcPt.fX -= SK_ScalarHalf; 27 srcPt.fX -= SK_ScalarHalf;
28 srcPt.fY -= SK_ScalarHalf; 28 srcPt.fY -= SK_ScalarHalf;
29 29
30 SkFixed weight = 0; 30 SkScalar weight = 0;
31 SkFixed fr = 0, fg = 0, fb = 0, fa = 0; 31 SkScalar fr = 0, fg = 0, fb = 0, fa = 0;
32 32
33 int y0 = SkClampMax(sk_float_ceil2int(SkScalarToFloat(srcPt.fY)-s.getBit mapFilter()->width()), maxY); 33 int y0 = SkClampMax(SkScalarCeilToInt(srcPt.fY-s.getBitmapFilter()->widt h()), maxY);
34 int y1 = SkClampMax(sk_float_floor2int(SkScalarToFloat(srcPt.fY)+s.getBi tmapFilter()->width()), maxY); 34 int y1 = SkClampMax(SkScalarFloorToInt(srcPt.fY+s.getBitmapFilter()->wid th()), maxY);
35 int x0 = SkClampMax(sk_float_ceil2int(SkScalarToFloat(srcPt.fX)-s.getBit mapFilter()->width()), maxX); 35 int x0 = SkClampMax(SkScalarCeilToInt(srcPt.fX-s.getBitmapFilter()->widt h()), maxX);
36 int x1 = SkClampMax(sk_float_floor2int(SkScalarToFloat(srcPt.fX)+s.getBi tmapFilter()->width()), maxX); 36 int x1 = SkClampMax(SkScalarFloorToInt(srcPt.fX+s.getBitmapFilter()->wid th()), maxX);
37 37
38 for (int src_y = y0; src_y <= y1; src_y++) { 38 for (int src_y = y0; src_y <= y1; src_y++) {
39 SkFixed yweight = s.getBitmapFilter()->lookup((srcPt.fY - src_y)); 39 SkScalar yweight = s.getBitmapFilter()->lookupScalar((srcPt.fY - src _y));
40 40
41 for (int src_x = x0; src_x <= x1 ; src_x++) { 41 for (int src_x = x0; src_x <= x1 ; src_x++) {
42 SkFixed xweight = s.getBitmapFilter()->lookup((srcPt.fX - src_x) ); 42 SkScalar xweight = s.getBitmapFilter()->lookupScalar((srcPt.fX - src_x));
43 43
44 SkFixed combined_weight = SkFixedMul(xweight, yweight); 44 SkScalar combined_weight = SkScalarMul(xweight, yweight);
45 45
46 SkPMColor c = *s.fBitmap->getAddr32(src_x, src_y); 46 SkPMColor c = *s.fBitmap->getAddr32(src_x, src_y);
47 fr += combined_weight * SkGetPackedR32(c); 47 fr += combined_weight * SkGetPackedR32(c);
48 fg += combined_weight * SkGetPackedG32(c); 48 fg += combined_weight * SkGetPackedG32(c);
49 fb += combined_weight * SkGetPackedB32(c); 49 fb += combined_weight * SkGetPackedB32(c);
50 fa += combined_weight * SkGetPackedA32(c); 50 fa += combined_weight * SkGetPackedA32(c);
51 weight += combined_weight; 51 weight += combined_weight;
52 } 52 }
53 } 53 }
54 54
55 fr = SkFixedDiv(fr, weight); 55 fr = SkScalarDiv(fr, weight);
reed1 2013/07/12 14:01:06 All of the SkScalarDiv() calls are correct, but we
56 fg = SkFixedDiv(fg, weight); 56 fg = SkScalarDiv(fg, weight);
57 fb = SkFixedDiv(fb, weight); 57 fb = SkScalarDiv(fb, weight);
58 fa = SkFixedDiv(fa, weight); 58 fa = SkScalarDiv(fa, weight);
59 59
60 int a = SkClampMax(SkFixedRoundToInt(fa), 255); 60 int a = SkClampMax(SkScalarRoundToInt(fa), 255);
61 int r = SkClampMax(SkFixedRoundToInt(fr), a); 61 int r = SkClampMax(SkScalarRoundToInt(fr), a);
62 int g = SkClampMax(SkFixedRoundToInt(fg), a); 62 int g = SkClampMax(SkScalarRoundToInt(fg), a);
63 int b = SkClampMax(SkFixedRoundToInt(fb), a); 63 int b = SkClampMax(SkScalarRoundToInt(fb), a);
64 64
65 *colors++ = SkPackARGB32(a, r, g, b); 65 *colors++ = SkPackARGB32(a, r, g, b);
66 66
67 x++; 67 x++;
68 } 68 }
69 } 69 }
70 70
71 void highQualityFilter_ScaleOnly(const SkBitmapProcState &s, int x, int y, 71 void highQualityFilter_ScaleOnly(const SkBitmapProcState &s, int x, int y,
72 SkPMColor *SK_RESTRICT colors, int count) { 72 SkPMColor *SK_RESTRICT colors, int count) {
73 const int maxX = s.fBitmap->width() - 1; 73 const int maxX = s.fBitmap->width() - 1;
74 const int maxY = s.fBitmap->height() - 1; 74 const int maxY = s.fBitmap->height() - 1;
75 75
76 SkPoint srcPt; 76 SkPoint srcPt;
77 77
78 s.fInvProc(*s.fInvMatrix, SkFloatToScalar(x + 0.5f), 78 s.fInvProc(*s.fInvMatrix, SkFloatToScalar(x + 0.5f),
79 SkFloatToScalar(y + 0.5f), &srcPt); 79 SkFloatToScalar(y + 0.5f), &srcPt);
80 srcPt.fY -= SK_ScalarHalf; 80 srcPt.fY -= SK_ScalarHalf;
81 int y0 = SkClampMax(sk_float_ceil2int(SkScalarToFloat(srcPt.fY)-s.getBitmap Filter()->width()), maxY); 81 int y0 = SkClampMax(SkScalarCeilToInt(srcPt.fY-s.getBitmapFilter()->width() ), maxY);
82 int y1 = SkClampMax(sk_float_floor2int(SkScalarToFloat(srcPt.fY)+s.getBitma pFilter()->width()), maxY); 82 int y1 = SkClampMax(SkScalarFloorToInt(srcPt.fY+s.getBitmapFilter()->width( )), maxY);
83 83
84 while (count-- > 0) { 84 while (count-- > 0) {
85 s.fInvProc(*s.fInvMatrix, SkFloatToScalar(x + 0.5f), 85 s.fInvProc(*s.fInvMatrix, SkFloatToScalar(x + 0.5f),
86 SkFloatToScalar(y + 0.5f), &srcPt); 86 SkFloatToScalar(y + 0.5f), &srcPt);
87 srcPt.fX -= SK_ScalarHalf; 87 srcPt.fX -= SK_ScalarHalf;
88 srcPt.fY -= SK_ScalarHalf; 88 srcPt.fY -= SK_ScalarHalf;
89 89
90 SkFixed weight = 0; 90 SkScalar weight = 0;
91 SkFixed fr = 0, fg = 0, fb = 0, fa = 0; 91 SkScalar fr = 0, fg = 0, fb = 0, fa = 0;
92 92
93 int x0 = SkClampMax(sk_float_ceil2int(SkScalarToFloat(srcPt.fX)-s.getBi tmapFilter()->width()), maxX); 93 int x0 = SkClampMax(SkScalarCeilToInt(srcPt.fX-s.getBitmapFilter()->wid th()), maxX);
94 int x1 = SkClampMax(sk_float_floor2int(SkScalarToFloat(srcPt.fX)+s.getB itmapFilter()->width()), maxX); 94 int x1 = SkClampMax(SkScalarFloorToInt(srcPt.fX+s.getBitmapFilter()->wi dth()), maxX);
95 95
96 for (int src_y = y0; src_y <= y1; src_y++) { 96 for (int src_y = y0; src_y <= y1; src_y++) {
97 SkFixed yweight = s.getBitmapFilter()->lookup((srcPt.fY - src_y)); 97 SkScalar yweight = s.getBitmapFilter()->lookupScalar((srcPt.fY - sr c_y));
98 98
99 for (int src_x = x0; src_x <= x1 ; src_x++) { 99 for (int src_x = x0; src_x <= x1 ; src_x++) {
100 SkFixed xweight = s.getBitmapFilter()->lookup((srcPt.fX - src_x )); 100 SkScalar xweight = s.getBitmapFilter()->lookupScalar((srcPt.fX - src_x));
101 101
102 SkFixed combined_weight = SkFixedMul(xweight, yweight); 102 SkScalar combined_weight = SkScalarMul(xweight, yweight);
103 103
104 SkPMColor c = *s.fBitmap->getAddr32(src_x, src_y); 104 SkPMColor c = *s.fBitmap->getAddr32(src_x, src_y);
105 fr += combined_weight * SkGetPackedR32(c); 105 fr += combined_weight * SkGetPackedR32(c);
106 fg += combined_weight * SkGetPackedG32(c); 106 fg += combined_weight * SkGetPackedG32(c);
107 fb += combined_weight * SkGetPackedB32(c); 107 fb += combined_weight * SkGetPackedB32(c);
108 fa += combined_weight * SkGetPackedA32(c); 108 fa += combined_weight * SkGetPackedA32(c);
109 weight += combined_weight; 109 weight += combined_weight;
110 } 110 }
111 } 111 }
112 112
113 fr = SkFixedDiv(fr, weight); 113 fr = SkScalarDiv(fr, weight);
114 fg = SkFixedDiv(fg, weight); 114 fg = SkScalarDiv(fg, weight);
115 fb = SkFixedDiv(fb, weight); 115 fb = SkScalarDiv(fb, weight);
116 fa = SkFixedDiv(fa, weight); 116 fa = SkScalarDiv(fa, weight);
117 117
118 int a = SkClampMax(SkFixedRoundToInt(fa), 255); 118 int a = SkClampMax(SkScalarRoundToInt(fa), 255);
119 int r = SkClampMax(SkFixedRoundToInt(fr), a); 119 int r = SkClampMax(SkScalarRoundToInt(fr), a);
120 int g = SkClampMax(SkFixedRoundToInt(fg), a); 120 int g = SkClampMax(SkScalarRoundToInt(fg), a);
121 int b = SkClampMax(SkFixedRoundToInt(fb), a); 121 int b = SkClampMax(SkScalarRoundToInt(fb), a);
122 122
123 *colors++ = SkPackARGB32(a, r, g, b); 123 *colors++ = SkPackARGB32(a, r, g, b);
124 124
125 x++; 125 x++;
126 } 126 }
127 } 127 }
128 128
129 SK_CONF_DECLARE(const char *, c_bitmapFilter, "bitmap.filter", "mitchell", "Whic h bitmap filter to use [mitchell, sinc, gaussian, triangle, box]"); 129 SK_CONF_DECLARE(const char *, c_bitmapFilter, "bitmap.filter", "mitchell", "Whic h bitmap filter to use [mitchell, sinc, gaussian, triangle, box]");
130 130
131 static SkBitmapFilter *allocateBitmapFilter() { 131 static SkBitmapFilter *allocateBitmapFilter() {
132 if (!strcmp(c_bitmapFilter, "mitchell")) { 132 if (!strcmp(c_bitmapFilter, "mitchell")) {
133 return SkNEW_ARGS(SkMitchellFilter,(1.f/3.f,1.f/3.f)); 133 return SkNEW_ARGS(SkMitchellFilter,(1.f/3.f,1.f/3.f));
134 } else if (!strcmp(c_bitmapFilter, "sinc")) { 134 } else if (!strcmp(c_bitmapFilter, "sinc")) {
135 return SkNEW_ARGS(SkSincFilter,(3)); 135 return SkNEW_ARGS(SkSincFilter,(3));
136 } else if (!strcmp(c_bitmapFilter, "gaussian")) { 136 } else if (!strcmp(c_bitmapFilter, "gaussian")) {
137 return SkNEW_ARGS(SkGaussianFilter,(2)); 137 return SkNEW_ARGS(SkGaussianFilter,(2));
138 } else if (!strcmp(c_bitmapFilter, "triangle")) { 138 } else if (!strcmp(c_bitmapFilter, "triangle")) {
139 return SkNEW(SkTriangleFilter); 139 return SkNEW(SkTriangleFilter);
140 } else if (!strcmp(c_bitmapFilter, "box")) { 140 } else if (!strcmp(c_bitmapFilter, "box")) {
141 return SkNEW(SkBoxFilter); 141 return SkNEW(SkBoxFilter);
142 } else { 142 } else {
143 SkASSERT(!!!"Unknown filter type"); 143 SkASSERT(!!!"Unknown filter type");
144 } 144 }
145 145
146 return NULL; 146 return NULL;
147 } 147 }
148 148
149 SkBitmapProcState::ShaderProc32 149 SkBitmapProcState::ShaderProc32
150 SkBitmapProcState::chooseBitmapFilterProc(const SkPaint& paint) { 150 SkBitmapProcState::chooseBitmapFilterProc() {
151 // we need to be requested 151
152 uint32_t mask = SkPaint::kFilterBitmap_Flag 152 if (fFilterQuality != kHQ_BitmapFilter) {
153 | SkPaint::kHighQualityFilterBitmap_Flag 153 return NULL;
154 ; 154 }
155 if ((paint.getFlags() & mask) != mask) { 155
156 if (fAlphaScale != 256) {
156 return NULL; 157 return NULL;
157 } 158 }
158 159
159 // TODO: consider supporting other configs (e.g. 565, A8) 160 // TODO: consider supporting other configs (e.g. 565, A8)
160 if (fBitmap->config() != SkBitmap::kARGB_8888_Config) { 161 if (fBitmap->config() != SkBitmap::kARGB_8888_Config) {
161 return NULL; 162 return NULL;
162 } 163 }
163 164
164 // TODO: consider supporting repeat and mirror 165 // TODO: consider supporting repeat and mirror
165 if (SkShader::kClamp_TileMode != fTileModeX || SkShader::kClamp_TileMode != fTileModeY) { 166 if (SkShader::kClamp_TileMode != fTileModeX || SkShader::kClamp_TileMode != fTileModeY) {
166 return NULL; 167 return NULL;
167 } 168 }
168 169
169 // TODO: support blending inside our procs
170 if (0xFF != paint.getAlpha()) {
171 return NULL;
172 }
173
174 if (fInvType & (SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask)) { 170 if (fInvType & (SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask)) {
175 fBitmapFilter = allocateBitmapFilter(); 171 fBitmapFilter = allocateBitmapFilter();
176 } 172 }
177 173
178 if (fInvType & SkMatrix::kAffine_Mask) { 174 if (fInvType & SkMatrix::kAffine_Mask) {
179 return highQualityFilter; 175 return highQualityFilter;
180 } else if (fInvType & SkMatrix::kScale_Mask) { 176 } else if (fInvType & SkMatrix::kScale_Mask) {
181 return highQualityFilter_ScaleOnly; 177 return highQualityFilter_ScaleOnly;
182 } else { 178 } else {
183 return NULL; 179 return NULL;
184 } 180 }
185 } 181 }
186 182
187 static void divideByWeights(SkFixed *sums, SkFixed *weights, SkBitmap *dst) { 183 static void divideByWeights(SkScalar *sums, SkScalar *weights, SkBitmap *dst) {
188 for (int y = 0 ; y < dst->height() ; y++) { 184 for (int y = 0 ; y < dst->height() ; y++) {
189 for (int x = 0 ; x < dst->width() ; x++) { 185 for (int x = 0 ; x < dst->width() ; x++) {
190 SkFixed fr = SkFixedDiv(sums[4*(y*dst->width() + x) + 0], weights[y* dst->width() + x]); 186 SkScalar fr = SkScalarDiv(sums[4*(y*dst->width() + x) + 0], weights[ y*dst->width() + x]);
191 SkFixed fg = SkFixedDiv(sums[4*(y*dst->width() + x) + 1], weights[y* dst->width() + x]); 187 SkScalar fg = SkScalarDiv(sums[4*(y*dst->width() + x) + 1], weights[ y*dst->width() + x]);
192 SkFixed fb = SkFixedDiv(sums[4*(y*dst->width() + x) + 2], weights[y* dst->width() + x]); 188 SkScalar fb = SkScalarDiv(sums[4*(y*dst->width() + x) + 2], weights[ y*dst->width() + x]);
193 SkFixed fa = SkFixedDiv(sums[4*(y*dst->width() + x) + 3], weights[y* dst->width() + x]); 189 SkScalar fa = SkScalarDiv(sums[4*(y*dst->width() + x) + 3], weights[ y*dst->width() + x]);
194 int a = SkClampMax(SkFixedRoundToInt(fa), 255); 190 int a = SkClampMax(SkScalarRoundToInt(fa), 255);
195 int r = SkClampMax(SkFixedRoundToInt(fr), a); 191 int r = SkClampMax(SkScalarRoundToInt(fr), a);
196 int g = SkClampMax(SkFixedRoundToInt(fg), a); 192 int g = SkClampMax(SkScalarRoundToInt(fg), a);
197 int b = SkClampMax(SkFixedRoundToInt(fb), a); 193 int b = SkClampMax(SkScalarRoundToInt(fb), a);
198 194
199 *dst->getAddr32(x,y) = SkPackARGB32(a, r, g, b); 195 *dst->getAddr32(x,y) = SkPackARGB32(a, r, g, b);
200 } 196 }
201 } 197 }
202 } 198 }
203 199
204 static void upScaleHoriz(const SkBitmap *src, SkBitmap *dst, float scale, SkBitm apFilter *filter) { 200 static void upScaleHorizTranspose(const SkBitmap *src, SkBitmap *dst, float scal e, SkBitmapFilter *filter) {
205 for (int y = 0 ; y < src->height() ; y++) { 201 for (int y = 0 ; y < dst->height() ; y++) {
206 for (int x = 0 ; x < dst->width() ; x++) { 202 for (int x = 0 ; x < dst->width() ; x++) {
207 float sx = (x + 0.5f) / scale - 0.5f; 203 float sx = (y + 0.5f) / scale - 0.5f;
208 int x0 = SkClampMax(sk_float_ceil2int(sx-filter->width()), src->widt h()-1); 204 int x0 = SkClampMax(sk_float_ceil2int(sx-filter->width()), src->widt h()-1);
209 int x1 = SkClampMax(sk_float_floor2int(sx+filter->width()), src->wid th()-1); 205 int x1 = SkClampMax(sk_float_floor2int(sx+filter->width()), src->wid th()-1);
210 206
211 SkFixed total_weight = 0; 207 SkScalar total_weight = 0;
212 SkFixed fr = 0, fg = 0, fb = 0, fa = 0; 208 SkScalar fr = 0, fg = 0, fb = 0, fa = 0;
213 209
214 for (int src_x = x0 ; src_x <= x1 ; src_x++) { 210 for (int src_x = x0 ; src_x <= x1 ; src_x++) {
215 SkFixed weight = filter->lookup(sx - src_x); 211 SkScalar weight = filter->lookupScalar(sx - src_x);
216 SkPMColor c = *src->getAddr32(src_x,y); 212 SkPMColor c = *src->getAddr32(src_x, x);
217 fr += weight * SkGetPackedR32(c); 213 fr += SkScalarMul(weight,SkGetPackedR32(c));
218 fg += weight * SkGetPackedG32(c); 214 fg += SkScalarMul(weight,SkGetPackedG32(c));
219 fb += weight * SkGetPackedB32(c); 215 fb += SkScalarMul(weight,SkGetPackedB32(c));
220 fa += weight * SkGetPackedA32(c); 216 fa += SkScalarMul(weight,SkGetPackedA32(c));
221 total_weight += weight; 217 total_weight += weight;
222 } 218 }
223 fr = SkFixedDiv(fr, total_weight); 219 fr = SkScalarDiv(fr,total_weight);
224 fg = SkFixedDiv(fg, total_weight); 220 fg = SkScalarDiv(fg,total_weight);
225 fb = SkFixedDiv(fb, total_weight); 221 fb = SkScalarDiv(fb,total_weight);
226 fa = SkFixedDiv(fa, total_weight); 222 fa = SkScalarDiv(fa,total_weight);
227 223
228 int a = SkClampMax(SkFixedRoundToInt(fa), 255); 224 int a = SkClampMax(SkScalarRoundToInt(fa), 255);
229 int r = SkClampMax(SkFixedRoundToInt(fr), a); 225 int r = SkClampMax(SkScalarRoundToInt(fr), a);
230 int g = SkClampMax(SkFixedRoundToInt(fg), a); 226 int g = SkClampMax(SkScalarRoundToInt(fg), a);
231 int b = SkClampMax(SkFixedRoundToInt(fb), a); 227 int b = SkClampMax(SkScalarRoundToInt(fb), a);
232 228
233 *dst->getAddr32(x,y) = SkPackARGB32(a, r, g, b); 229 *dst->getAddr32(x,y) = SkPackARGB32(a, r, g, b);
234 } 230 }
235 } 231 }
236 } 232 }
237 233
238 static void downScaleHoriz(const SkBitmap *src, SkBitmap *dst, float scale, SkBi tmapFilter *filter) { 234 static void downScaleHoriz(const SkBitmap *src, SkBitmap *dst, float scale, SkBi tmapFilter *filter) {
239 SkFixed *sums = SkNEW_ARRAY(SkFixed, dst->width() * dst->height() * 4); 235 SkScalar *sums = SkNEW_ARRAY(SkScalar, dst->width() * dst->height() * 4);
240 SkFixed *weights = SkNEW_ARRAY(SkFixed, dst->width() * dst->height()); 236 SkScalar *weights = SkNEW_ARRAY(SkScalar, dst->width() * dst->height());
241 237
242 SkAutoTDeleteArray<SkFixed> ada1(sums); 238 SkAutoTDeleteArray<SkScalar> ada1(sums);
243 SkAutoTDeleteArray<SkFixed> ada2(weights); 239 SkAutoTDeleteArray<SkScalar> ada2(weights);
244 240
245 memset(sums, 0, dst->width() * dst->height() * sizeof(SkFixed) * 4); 241 memset(sums, 0, dst->width() * dst->height() * sizeof(SkScalar) * 4);
246 memset(weights, 0, dst->width() * dst->height() * sizeof(SkFixed)); 242 memset(weights, 0, dst->width() * dst->height() * sizeof(SkScalar));
247 243
248 for (int y = 0 ; y < src->height() ; y++) { 244 for (int y = 0 ; y < src->height() ; y++) {
249 for (int x = 0 ; x < src->width() ; x++) { 245 for (int x = 0 ; x < src->width() ; x++) {
250 // splat each source pixel into the destination image 246 // splat each source pixel into the destination image
251 float dx = (x + 0.5f) * scale - 0.5f; 247 float dx = (x + 0.5f) * scale - 0.5f;
252 int x0 = SkClampMax(sk_float_ceil2int(dx-filter->width()), dst->widt h()-1); 248 int x0 = SkClampMax(sk_float_ceil2int(dx-filter->width()), dst->widt h()-1);
253 int x1 = SkClampMax(sk_float_floor2int(dx+filter->width()), dst->wid th()-1); 249 int x1 = SkClampMax(sk_float_floor2int(dx+filter->width()), dst->wid th()-1);
254 250
255 SkPMColor c = *src->getAddr32(x,y); 251 SkPMColor c = *src->getAddr32(x,y);
256 252
257 for (int dst_x = x0 ; dst_x <= x1 ; dst_x++) { 253 for (int dst_x = x0 ; dst_x <= x1 ; dst_x++) {
258 SkFixed weight = filter->lookup(dx - dst_x); 254 SkScalar weight = filter->lookup(dx - dst_x);
259 sums[4*(y*dst->width() + dst_x) + 0] += weight*SkGetPackedR32(c) ; 255 sums[4*(y*dst->width() + dst_x) + 0] += weight*SkGetPackedR32(c) ;
260 sums[4*(y*dst->width() + dst_x) + 1] += weight*SkGetPackedG32(c) ; 256 sums[4*(y*dst->width() + dst_x) + 1] += weight*SkGetPackedG32(c) ;
261 sums[4*(y*dst->width() + dst_x) + 2] += weight*SkGetPackedB32(c) ; 257 sums[4*(y*dst->width() + dst_x) + 2] += weight*SkGetPackedB32(c) ;
262 sums[4*(y*dst->width() + dst_x) + 3] += weight*SkGetPackedA32(c) ; 258 sums[4*(y*dst->width() + dst_x) + 3] += weight*SkGetPackedA32(c) ;
263 weights[y*dst->width() + dst_x] += weight; 259 weights[y*dst->width() + dst_x] += weight;
264 } 260 }
265 } 261 }
266 } 262 }
267 263
268 divideByWeights(sums, weights, dst); 264 divideByWeights(sums, weights, dst);
269 } 265 }
270 266
271 static void upScaleVert(const SkBitmap *src, SkBitmap *dst, float scale, SkBitma pFilter *filter) { 267 static void downScaleVert(const SkBitmap *src, SkBitmap *dst, float scale, SkBit mapFilter *filter) {
272 for (int y = 0 ; y < dst->height() ; y++) { 268 SkScalar *sums = SkNEW_ARRAY(SkScalar, dst->width() * dst->height() * 4);
273 for (int x = 0 ; x < dst->width() ; x++) { 269 SkScalar *weights = SkNEW_ARRAY(SkScalar, dst->width() * dst->height());
274 float sy = (y + 0.5f) / scale - 0.5f;
275 int y0 = SkClampMax(sk_float_ceil2int(sy-filter->width()), src->heig ht()-1);
276 int y1 = SkClampMax(sk_float_floor2int(sy+filter->width()), src->hei ght()-1);
277 270
278 SkFixed total_weight = 0; 271 SkAutoTDeleteArray<SkScalar> ada1(sums);
279 SkFixed fr = 0, fg = 0, fb = 0, fa = 0; 272 SkAutoTDeleteArray<SkScalar> ada2(weights);
280 273
281 for (int src_y = y0 ; src_y <= y1 ; src_y++) { 274 memset(sums, 0, dst->width() * dst->height() * sizeof(SkScalar) * 4);
282 SkFixed weight = filter->lookup(sy - src_y); 275 memset(weights, 0, dst->width() * dst->height() * sizeof(SkScalar));
283 SkPMColor c = *src->getAddr32(x,src_y);
284 fr += weight * SkGetPackedR32(c);
285 fg += weight * SkGetPackedG32(c);
286 fb += weight * SkGetPackedB32(c);
287 fa += weight * SkGetPackedA32(c);
288 total_weight += weight;
289 }
290 fr = SkFixedDiv(fr, total_weight);
291 fg = SkFixedDiv(fg, total_weight);
292 fb = SkFixedDiv(fb, total_weight);
293 fa = SkFixedDiv(fa, total_weight);
294
295 int a = SkClampMax(SkFixedRoundToInt(fa), 255);
296 int r = SkClampMax(SkFixedRoundToInt(fr), a);
297 int g = SkClampMax(SkFixedRoundToInt(fg), a);
298 int b = SkClampMax(SkFixedRoundToInt(fb), a);
299
300 *dst->getAddr32(x,y) = SkPackARGB32(a, r, g, b);
301 }
302 }
303 }
304
305 static void downScaleVert(const SkBitmap *src, SkBitmap *dst, float scale, SkBit mapFilter *filter) {
306 SkFixed *sums = SkNEW_ARRAY(SkFixed, dst->width() * dst->height() * 4);
307 SkFixed *weights = SkNEW_ARRAY(SkFixed, dst->width() * dst->height());
308
309 SkAutoTDeleteArray<SkFixed> ada1(sums);
310 SkAutoTDeleteArray<SkFixed> ada2(weights);
311
312 memset(sums, 0, dst->width() * dst->height() * sizeof(SkFixed) * 4);
313 memset(weights, 0, dst->width() * dst->height() * sizeof(SkFixed));
314 276
315 for (int y = 0 ; y < src->height() ; y++) { 277 for (int y = 0 ; y < src->height() ; y++) {
316 for (int x = 0 ; x < src->width() ; x++) { 278 for (int x = 0 ; x < src->width() ; x++) {
317 // splat each source pixel into the destination image 279 // splat each source pixel into the destination image
318 float dy = (y + 0.5f) * scale - 0.5f; 280 float dy = (y + 0.5f) * scale - 0.5f;
319 int y0 = SkClampMax(sk_float_ceil2int(dy-filter->width()), dst->heig ht()-1); 281 int y0 = SkClampMax(sk_float_ceil2int(dy-filter->width()), dst->heig ht()-1);
320 int y1 = SkClampMax(sk_float_ceil2int(dy+filter->width()), dst->heig ht()-1); 282 int y1 = SkClampMax(sk_float_ceil2int(dy+filter->width()), dst->heig ht()-1);
321 283
322 SkPMColor c = *src->getAddr32(x,y); 284 SkPMColor c = *src->getAddr32(x,y);
323 285
324 for (int dst_y = y0 ; dst_y <= y1 ; dst_y++) { 286 for (int dst_y = y0 ; dst_y <= y1 ; dst_y++) {
325 SkFixed weight = filter->lookup(dy - dst_y); 287 SkScalar weight = filter->lookupScalar(dy - dst_y);
326 sums[4*(dst_y*dst->width() + x) + 0] += weight*SkGetPackedR32(c) ; 288 sums[4*(dst_y*dst->width() + x) + 0] += weight*SkGetPackedR32(c) ;
327 sums[4*(dst_y*dst->width() + x) + 1] += weight*SkGetPackedG32(c) ; 289 sums[4*(dst_y*dst->width() + x) + 1] += weight*SkGetPackedG32(c) ;
328 sums[4*(dst_y*dst->width() + x) + 2] += weight*SkGetPackedB32(c) ; 290 sums[4*(dst_y*dst->width() + x) + 2] += weight*SkGetPackedB32(c) ;
329 sums[4*(dst_y*dst->width() + x) + 3] += weight*SkGetPackedA32(c) ; 291 sums[4*(dst_y*dst->width() + x) + 3] += weight*SkGetPackedA32(c) ;
330 weights[dst_y*dst->width() + x] += weight; 292 weights[dst_y*dst->width() + x] += weight;
331 } 293 }
332 } 294 }
333 } 295 }
334 296
335 divideByWeights(sums, weights, dst); 297 divideByWeights(sums, weights, dst);
336 } 298 }
337 299
338 void SkBitmap::scale(SkBitmap *dst) const { 300 void SkBitmap::scale(SkBitmap *dst) const {
339 301
340 SkBitmap horiz_temp; 302 SkBitmap horiz_temp;
341 303
342 horiz_temp.setConfig(SkBitmap::kARGB_8888_Config, dst->width(), height()); 304 horiz_temp.setConfig(SkBitmap::kARGB_8888_Config, height(), dst->width());
343 horiz_temp.allocPixels(); 305 horiz_temp.allocPixels();
344 306
345 SkBitmapFilter *filter = allocateBitmapFilter(); 307 SkBitmapFilter *filter = allocateBitmapFilter();
346 308
347 float horiz_scale = float(dst->width()) / width(); 309 float horiz_scale = float(dst->width()) / width();
348 310
349 if (horiz_scale == 1) { 311 if (horiz_scale >= 1) {
350 this->copyPixelsTo(horiz_temp.getPixels(), getSize()); 312 upScaleHorizTranspose(this, &horiz_temp, horiz_scale, filter);
351 } else if (horiz_scale > 1) {
352 upScaleHoriz(this, &horiz_temp, horiz_scale, filter);
353 } else if (horiz_scale < 1) { 313 } else if (horiz_scale < 1) {
354 downScaleHoriz(this, &horiz_temp, horiz_scale, filter); 314 downScaleHoriz(this, &horiz_temp, horiz_scale, filter);
355 } 315 }
356 316
357 float vert_scale = float(dst->height()) / height(); 317 float vert_scale = float(dst->height()) / height();
358 318
359 if (vert_scale == 1) { 319 if (vert_scale >= 1) {
360 horiz_temp.copyPixelsTo(dst->getPixels(), dst->getSize()); 320 upScaleHorizTranspose(&horiz_temp, dst, vert_scale, filter);
361 } else if (vert_scale > 1) {
362 upScaleVert(&horiz_temp, dst, vert_scale, filter);
363 } else if (vert_scale < 1) { 321 } else if (vert_scale < 1) {
364 downScaleVert(&horiz_temp, dst, vert_scale, filter); 322 downScaleVert(&horiz_temp, dst, vert_scale, filter);
365 } 323 }
366 324
367 SkDELETE(filter); 325 SkDELETE(filter);
368 } 326 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698