Chromium Code Reviews| 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 |