OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2012 The Android Open Source Project | 2 * Copyright 2012 The Android Open Source Project |
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 "SkMatrixConvolutionImageFilter.h" | 8 #include "SkMatrixConvolutionImageFilter.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
11 #include "SkDevice.h" | 11 #include "SkDevice.h" |
12 #include "SkReadBuffer.h" | 12 #include "SkReadBuffer.h" |
13 #include "SkWriteBuffer.h" | 13 #include "SkWriteBuffer.h" |
14 #include "SkRect.h" | 14 #include "SkRect.h" |
15 #include "SkUnPreMultiply.h" | 15 #include "SkUnPreMultiply.h" |
16 #include "SkOpts.h" | |
16 | 17 |
17 #if SK_SUPPORT_GPU | 18 #if SK_SUPPORT_GPU |
18 #include "effects/GrMatrixConvolutionEffect.h" | 19 #include "effects/GrMatrixConvolutionEffect.h" |
19 #endif | 20 #endif |
20 | 21 |
21 // We need to be able to read at most SK_MaxS32 bytes, so divide that | 22 // We need to be able to read at most SK_MaxS32 bytes, so divide that |
22 // by the size of a scalar to know how many scalars we can read. | 23 // by the size of a scalar to know how many scalars we can read. |
23 static const int32_t gMaxKernelSize = SK_MaxS32 / sizeof(SkScalar); | 24 static const int32_t gMaxKernelSize = SK_MaxS32 / sizeof(SkScalar); |
24 | 25 |
25 SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter( | 26 SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter( |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 buffer.writeInt(fKernelOffset.fX); | 111 buffer.writeInt(fKernelOffset.fX); |
111 buffer.writeInt(fKernelOffset.fY); | 112 buffer.writeInt(fKernelOffset.fY); |
112 buffer.writeInt((int) fTileMode); | 113 buffer.writeInt((int) fTileMode); |
113 buffer.writeBool(fConvolveAlpha); | 114 buffer.writeBool(fConvolveAlpha); |
114 } | 115 } |
115 | 116 |
116 SkMatrixConvolutionImageFilter::~SkMatrixConvolutionImageFilter() { | 117 SkMatrixConvolutionImageFilter::~SkMatrixConvolutionImageFilter() { |
117 delete[] fKernel; | 118 delete[] fKernel; |
118 } | 119 } |
119 | 120 |
120 class UncheckedPixelFetcher { | |
121 public: | |
122 static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRe ct& bounds) { | |
123 return *src.getAddr32(x, y); | |
124 } | |
125 }; | |
126 | |
127 class ClampPixelFetcher { | 121 class ClampPixelFetcher { |
128 public: | 122 public: |
129 static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRe ct& bounds) { | 123 static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRe ct& bounds) { |
130 x = SkTPin(x, bounds.fLeft, bounds.fRight - 1); | 124 x = SkTPin(x, bounds.fLeft, bounds.fRight - 1); |
131 y = SkTPin(y, bounds.fTop, bounds.fBottom - 1); | 125 y = SkTPin(y, bounds.fTop, bounds.fBottom - 1); |
132 return *src.getAddr32(x, y); | 126 return *src.getAddr32(x, y); |
133 } | 127 } |
134 }; | 128 }; |
135 | 129 |
136 class RepeatPixelFetcher { | 130 class RepeatPixelFetcher { |
(...skipping 15 matching lines...) Expand all Loading... | |
152 public: | 146 public: |
153 static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRe ct& bounds) { | 147 static inline SkPMColor fetch(const SkBitmap& src, int x, int y, const SkIRe ct& bounds) { |
154 if (x < bounds.fLeft || x >= bounds.fRight || y < bounds.fTop || y >= bo unds.fBottom) { | 148 if (x < bounds.fLeft || x >= bounds.fRight || y < bounds.fTop || y >= bo unds.fBottom) { |
155 return 0; | 149 return 0; |
156 } else { | 150 } else { |
157 return *src.getAddr32(x, y); | 151 return *src.getAddr32(x, y); |
158 } | 152 } |
159 } | 153 } |
160 }; | 154 }; |
161 | 155 |
162 template<class PixelFetcher, bool convolveAlpha> | 156 template<class PixelFetcher> |
163 void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, | 157 void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, |
164 SkBitmap* result, | 158 SkBitmap* result, |
165 const SkIRect& r, | 159 const SkIRect& r, |
166 const SkIRect& bounds) const { | 160 const SkIRect& bounds) const { |
167 SkIRect rect(r); | 161 SkIRect rect(r); |
168 if (!rect.intersect(bounds)) { | 162 if (!rect.intersect(bounds)) { |
169 return; | 163 return; |
170 } | 164 } |
171 for (int y = rect.fTop; y < rect.fBottom; ++y) { | 165 for (int y = rect.fTop; y < rect.fBottom; ++y) { |
172 SkPMColor* dptr = result->getAddr32(rect.fLeft - bounds.fLeft, y - bound s.fTop); | 166 SkPMColor* dptr = result->getAddr32(rect.fLeft - bounds.fLeft, y - bound s.fTop); |
173 for (int x = rect.fLeft; x < rect.fRight; ++x) { | 167 for (int x = rect.fLeft; x < rect.fRight; ++x) { |
174 SkScalar sumA = 0, sumR = 0, sumG = 0, sumB = 0; | 168 SkScalar sumA = 0, sumR = 0, sumG = 0, sumB = 0; |
175 for (int cy = 0; cy < fKernelSize.fHeight; cy++) { | 169 for (int cy = 0; cy < fKernelSize.fHeight; cy++) { |
176 for (int cx = 0; cx < fKernelSize.fWidth; cx++) { | 170 for (int cx = 0; cx < fKernelSize.fWidth; cx++) { |
177 SkPMColor s = PixelFetcher::fetch(src, | 171 SkPMColor s = PixelFetcher::fetch(src, |
178 x + cx - fKernelOffset.fX, | 172 x + cx - fKernelOffset.fX, |
179 y + cy - fKernelOffset.fY, | 173 y + cy - fKernelOffset.fY, |
180 bounds); | 174 bounds); |
181 SkScalar k = fKernel[cy * fKernelSize.fWidth + cx]; | 175 SkScalar k = fKernel[cy * fKernelSize.fWidth + cx]; |
182 if (convolveAlpha) { | 176 if (fConvolveAlpha) { |
Stephen White
2016/04/12 20:01:58
IIRC, this did actually have a measurable impact w
| |
183 sumA += SkScalarMul(SkIntToScalar(SkGetPackedA32(s)), k) ; | 177 sumA += SkScalarMul(SkIntToScalar(SkGetPackedA32(s)), k) ; |
184 } | 178 } |
185 sumR += SkScalarMul(SkIntToScalar(SkGetPackedR32(s)), k); | 179 sumR += SkScalarMul(SkIntToScalar(SkGetPackedR32(s)), k); |
186 sumG += SkScalarMul(SkIntToScalar(SkGetPackedG32(s)), k); | 180 sumG += SkScalarMul(SkIntToScalar(SkGetPackedG32(s)), k); |
187 sumB += SkScalarMul(SkIntToScalar(SkGetPackedB32(s)), k); | 181 sumB += SkScalarMul(SkIntToScalar(SkGetPackedB32(s)), k); |
188 } | 182 } |
189 } | 183 } |
190 int a = convolveAlpha | 184 int a = fConvolveAlpha |
191 ? SkClampMax(SkScalarFloorToInt(SkScalarMul(sumA, fGain) + fBi as), 255) | 185 ? SkClampMax(SkScalarFloorToInt(SkScalarMul(sumA, fGain) + fBi as), 255) |
192 : 255; | 186 : 255; |
193 int r = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumR, fGain) + fBi as), a); | 187 int r = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumR, fGain) + fBi as), a); |
194 int g = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumG, fGain) + fBi as), a); | 188 int g = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumG, fGain) + fBi as), a); |
195 int b = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumB, fGain) + fBi as), a); | 189 int b = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumB, fGain) + fBi as), a); |
196 if (!convolveAlpha) { | 190 if (!fConvolveAlpha) { |
197 a = SkGetPackedA32(PixelFetcher::fetch(src, x, y, bounds)); | 191 a = SkGetPackedA32(PixelFetcher::fetch(src, x, y, bounds)); |
198 *dptr++ = SkPreMultiplyARGB(a, r, g, b); | 192 *dptr++ = SkPreMultiplyARGB(a, r, g, b); |
199 } else { | 193 } else { |
200 *dptr++ = SkPackARGB32(a, r, g, b); | 194 *dptr++ = SkPackARGB32(a, r, g, b); |
201 } | 195 } |
202 } | 196 } |
203 } | 197 } |
204 } | 198 } |
205 | 199 |
206 template<class PixelFetcher> | |
207 void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, | |
208 SkBitmap* result, | |
209 const SkIRect& rect, | |
210 const SkIRect& bounds) const { | |
211 if (fConvolveAlpha) { | |
212 filterPixels<PixelFetcher, true>(src, result, rect, bounds); | |
213 } else { | |
214 filterPixels<PixelFetcher, false>(src, result, rect, bounds); | |
215 } | |
216 } | |
217 | 200 |
218 void SkMatrixConvolutionImageFilter::filterInteriorPixels(const SkBitmap& src, | 201 void SkMatrixConvolutionImageFilter::filterInteriorPixels(const SkBitmap& src, |
219 SkBitmap* result, | 202 SkBitmap* result, |
220 const SkIRect& rect, | 203 const SkIRect& rect, |
221 const SkIRect& bounds) const { | 204 const SkIRect& bounds) const { |
222 filterPixels<UncheckedPixelFetcher>(src, result, rect, bounds); | 205 SkOpts::matrix_convolution_image_filter_filter_pixels( |
206 » src, | |
Stephen White
2016/04/12 20:01:58
Please use spaces instead of tabs.
| |
207 » result, | |
208 » rect, | |
209 » bounds, | |
210 » fConvolveAlpha, | |
211 » fKernel, | |
212 » fKernelSize, | |
213 » fKernelOffset, | |
214 » fGain, | |
215 » fBias); | |
223 } | 216 } |
224 | 217 |
225 void SkMatrixConvolutionImageFilter::filterBorderPixels(const SkBitmap& src, | 218 void SkMatrixConvolutionImageFilter::filterBorderPixels(const SkBitmap& src, |
226 SkBitmap* result, | 219 SkBitmap* result, |
227 const SkIRect& rect, | 220 const SkIRect& rect, |
228 const SkIRect& bounds) c onst { | 221 const SkIRect& bounds) c onst { |
229 switch (fTileMode) { | 222 switch (fTileMode) { |
230 case kClamp_TileMode: | 223 case kClamp_TileMode: |
231 filterPixels<ClampPixelFetcher>(src, result, rect, bounds); | 224 filterPixels<ClampPixelFetcher>(src, result, rect, bounds); |
232 break; | 225 break; |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 str->appendf("%f ", fKernel[y * fKernelSize.width() + x]); | 383 str->appendf("%f ", fKernel[y * fKernelSize.width() + x]); |
391 } | 384 } |
392 } | 385 } |
393 str->appendf(")"); | 386 str->appendf(")"); |
394 str->appendf("gain: %f bias: %f ", fGain, fBias); | 387 str->appendf("gain: %f bias: %f ", fGain, fBias); |
395 str->appendf("offset: (%d, %d) ", fKernelOffset.fX, fKernelOffset.fY); | 388 str->appendf("offset: (%d, %d) ", fKernelOffset.fX, fKernelOffset.fY); |
396 str->appendf("convolveAlpha: %s", fConvolveAlpha ? "true" : "false"); | 389 str->appendf("convolveAlpha: %s", fConvolveAlpha ? "true" : "false"); |
397 str->append(")"); | 390 str->append(")"); |
398 } | 391 } |
399 #endif | 392 #endif |
OLD | NEW |