1 /* 2 * Copyright 2019 Google LLC 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 #ifndef SkImageFilters_DEFINED 9 #define SkImageFilters_DEFINED 10 11 #include "include/core/SkColor.h" 12 #include "include/core/SkColorSpace.h" 13 #include "include/core/SkImage.h" 14 #include "include/core/SkImageFilter.h" 15 #include "include/core/SkPicture.h" 16 #include "include/core/SkRect.h" 17 #include "include/core/SkRefCnt.h" 18 #include "include/core/SkScalar.h" 19 #include "include/core/SkShader.h" 20 #include "include/core/SkTileMode.h" 21 #include "include/core/SkTypes.h" 22 23 #include <cstddef> 24 #include <optional> 25 #include <string_view> 26 #include <utility> 27 28 class SkBlender; 29 class SkColorFilter; 30 class SkMatrix; 31 class SkRuntimeEffectBuilder; 32 enum class SkBlendMode; 33 struct SkIPoint; 34 struct SkISize; 35 struct SkPoint3; 36 struct SkSamplingOptions; 37 38 // A set of factory functions providing useful SkImageFilter effects. For image filters that take an 39 // input filter, providing nullptr means it will automatically use the dynamic source image. This 40 // source depends on how the filter is applied, but is either the contents of a saved layer when 41 // drawing with SkCanvas, or an explicit SkImage if using one of the SkImages::MakeWithFilter 42 // factories. 43 class SK_API SkImageFilters { 44 public: 45 // This is just a convenience type to allow passing SkIRects, SkRects, and optional pointers 46 // to those types as a crop rect for the image filter factories. It's not intended to be used 47 // directly. 48 struct CropRect : public std::optional<SkRect> { CropRectCropRect49 CropRect() {} 50 // Intentionally not explicit so callers don't have to use this type but can use SkIRect or 51 // SkRect as desired. CropRectCropRect52 CropRect(const SkIRect& crop) : std::optional<SkRect>(SkRect::Make(crop)) {} CropRectCropRect53 CropRect(const SkRect& crop) : std::optional<SkRect>(crop) {} CropRectCropRect54 CropRect(const std::optional<SkRect>& crop) : std::optional<SkRect>(crop) {} CropRectCropRect55 CropRect(const std::nullopt_t&) : std::optional<SkRect>() {} 56 57 // Backwards compatibility for when the APIs used to explicitly accept "const SkRect*" CropRectCropRect58 CropRect(std::nullptr_t) {} CropRectCropRect59 CropRect(const SkIRect* optionalCrop) { 60 if (optionalCrop) { 61 *this = SkRect::Make(*optionalCrop); 62 } 63 } CropRectCropRect64 CropRect(const SkRect* optionalCrop) { 65 if (optionalCrop) { 66 *this = *optionalCrop; 67 } 68 } 69 70 // std::optional doesn't define == when comparing to another optional... 71 bool operator==(const CropRect& o) const { 72 return this->has_value() == o.has_value() && 73 (!this->has_value() || this->value() == *o); 74 } 75 }; 76 77 /** 78 * Create a filter that implements a custom blend mode. Each output pixel is the result of 79 * combining the corresponding background and foreground pixels using the 4 coefficients: 80 * k1 * foreground * background + k2 * foreground + k3 * background + k4 81 * @param k1, k2, k3, k4 The four coefficients used to combine the foreground and background. 82 * @param enforcePMColor If true, the RGB channels will be clamped to the calculated alpha. 83 * @param background The background content, using the source bitmap when this is null. 84 * @param foreground The foreground content, using the source bitmap when this is null. 85 * @param cropRect Optional rectangle that crops the inputs and output. 86 */ 87 static sk_sp<SkImageFilter> Arithmetic(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, 88 bool enforcePMColor, sk_sp<SkImageFilter> background, 89 sk_sp<SkImageFilter> foreground, 90 const CropRect& cropRect = {}); 91 92 /** 93 * This filter takes an SkBlendMode and uses it to composite the two filters together. 94 * @param mode The blend mode that defines the compositing operation 95 * @param background The Dst pixels used in blending, if null the source bitmap is used. 96 * @param foreground The Src pixels used in blending, if null the source bitmap is used. 97 * @cropRect Optional rectangle to crop input and output. 98 */ 99 static sk_sp<SkImageFilter> Blend(SkBlendMode mode, sk_sp<SkImageFilter> background, 100 sk_sp<SkImageFilter> foreground = nullptr, 101 const CropRect& cropRect = {}); 102 103 /** 104 * This filter takes an SkBlendMode and uses it to composite the two filters together. 105 * @param blender The blender that defines the compositing operation 106 * @param background The Dst pixels used in blending, if null the source bitmap is used. 107 * @param foreground The Src pixels used in blending, if null the source bitmap is used. 108 * @cropRect Optional rectangle to crop input and output. 109 */ 110 static sk_sp<SkImageFilter> Blend(sk_sp<SkBlender> blender, sk_sp<SkImageFilter> background, 111 sk_sp<SkImageFilter> foreground = nullptr, 112 const CropRect& cropRect = {}); 113 114 /** 115 * Create a filter that blurs its input by the separate X and Y sigmas. The provided tile mode 116 * is used when the blur kernel goes outside the input image. 117 * @param sigmaX The Gaussian sigma value for blurring along the X axis. 118 * @param sigmaY The Gaussian sigma value for blurring along the Y axis. 119 * @param tileMode The tile mode applied at edges . 120 * TODO (michaelludwig) - kMirror is not supported yet 121 * @param input The input filter that is blurred, uses source bitmap if this is null. 122 * @param cropRect Optional rectangle that crops the input and output. 123 */ 124 static sk_sp<SkImageFilter> Blur(SkScalar sigmaX, SkScalar sigmaY, SkTileMode tileMode, 125 sk_sp<SkImageFilter> input, const CropRect& cropRect = {}); 126 // As above, but defaults to the decal tile mode. 127 static sk_sp<SkImageFilter> Blur(SkScalar sigmaX, SkScalar sigmaY, sk_sp<SkImageFilter> input, 128 const CropRect& cropRect = {}) { 129 return Blur(sigmaX, sigmaY, SkTileMode::kDecal, std::move(input), cropRect); 130 } 131 132 /** 133 * Create a filter that applies the color filter to the input filter results. 134 * @param cf The color filter that transforms the input image. 135 * @param input The input filter, or uses the source bitmap if this is null. 136 * @param cropRect Optional rectangle that crops the input and output. 137 */ 138 static sk_sp<SkImageFilter> ColorFilter(sk_sp<SkColorFilter> cf, sk_sp<SkImageFilter> input, 139 const CropRect& cropRect = {}); 140 141 /** 142 * Create a filter that composes 'inner' with 'outer', such that the results of 'inner' are 143 * treated as the source bitmap passed to 'outer', i.e. result = outer(inner(source)). 144 * @param outer The outer filter that evaluates the results of inner. 145 * @param inner The inner filter that produces the input to outer. 146 */ 147 static sk_sp<SkImageFilter> Compose(sk_sp<SkImageFilter> outer, sk_sp<SkImageFilter> inner); 148 149 /** 150 * Create a filter that applies a crop to the result of the 'input' filter. Pixels within the 151 * crop rectangle are unmodified from what 'input' produced. Pixels outside of crop match the 152 * provided SkTileMode (defaulting to kDecal). 153 * 154 * NOTE: The optional CropRect argument for many of the factories is equivalent to creating the 155 * filter without a CropRect and then wrapping it in ::Crop(rect, kDecal). Explicitly adding 156 * Crop filters lets you control their tiling and use different geometry for the input and the 157 * output of another filter. 158 * 159 * @param rect The cropping geometry 160 * @param tileMode The tilemode applied to pixels *outside* of 'crop' 161 * @param input The input filter that is cropped, uses source image if this is null 162 */ 163 static sk_sp<SkImageFilter> Crop(const SkRect& rect, 164 SkTileMode tileMode, 165 sk_sp<SkImageFilter> input); Crop(const SkRect & rect,sk_sp<SkImageFilter> input)166 static sk_sp<SkImageFilter> Crop(const SkRect& rect, sk_sp<SkImageFilter> input) { 167 return Crop(rect, SkTileMode::kDecal, std::move(input)); 168 } 169 170 /** 171 * Create a filter that moves each pixel in its color input based on an (x,y) vector encoded 172 * in its displacement input filter. Two color components of the displacement image are 173 * mapped into a vector as scale * (color[xChannel], color[yChannel]), where the channel 174 * selectors are one of R, G, B, or A. 175 * @param xChannelSelector RGBA channel that encodes the x displacement per pixel. 176 * @param yChannelSelector RGBA channel that encodes the y displacement per pixel. 177 * @param scale Scale applied to displacement extracted from image. 178 * @param displacement The filter defining the displacement image, or null to use source. 179 * @param color The filter providing the color pixels to be displaced. If null, 180 * it will use the source. 181 * @param cropRect Optional rectangle that crops the color input and output. 182 */ 183 static sk_sp<SkImageFilter> DisplacementMap(SkColorChannel xChannelSelector, 184 SkColorChannel yChannelSelector, 185 SkScalar scale, sk_sp<SkImageFilter> displacement, 186 sk_sp<SkImageFilter> color, 187 const CropRect& cropRect = {}); 188 189 /** 190 * Create a filter that draws a drop shadow under the input content. This filter produces an 191 * image that includes the inputs' content. 192 * @param dx X offset of the shadow. 193 * @param dy Y offset of the shadow. 194 * @param sigmaX blur radius for the shadow, along the X axis. 195 * @param sigmaY blur radius for the shadow, along the Y axis. 196 * @param color color of the drop shadow. 197 * @param colorSpace The color space of the drop shadow color. 198 * @param input The input filter, or will use the source bitmap if this is null. 199 * @param cropRect Optional rectangle that crops the input and output. 200 */ 201 static sk_sp<SkImageFilter> DropShadow(SkScalar dx, SkScalar dy, 202 SkScalar sigmaX, SkScalar sigmaY, 203 SkColor4f color, sk_sp<SkColorSpace> colorSpace, 204 sk_sp<SkImageFilter> input, 205 const CropRect& cropRect = {}); 206 static sk_sp<SkImageFilter> DropShadow(SkScalar dx, SkScalar dy, 207 SkScalar sigmaX, SkScalar sigmaY, 208 SkColor color, sk_sp<SkImageFilter> input, 209 const CropRect& cropRect = {}) { 210 return DropShadow(dx, dy, 211 sigmaX, sigmaY, 212 SkColor4f::FromColor(color), /*colorSpace=*/nullptr, 213 std::move(input), 214 cropRect); 215 } 216 217 /** 218 * Create a filter that renders a drop shadow, in exactly the same manner as ::DropShadow, 219 * except that the resulting image does not include the input content. This allows the shadow 220 * and input to be composed by a filter DAG in a more flexible manner. 221 * @param dx The X offset of the shadow. 222 * @param dy The Y offset of the shadow. 223 * @param sigmaX The blur radius for the shadow, along the X axis. 224 * @param sigmaY The blur radius for the shadow, along the Y axis. 225 * @param color The color of the drop shadow. 226 * @param colorSpace The color space of the drop shadow color. 227 * @param input The input filter, or will use the source bitmap if this is null. 228 * @param cropRect Optional rectangle that crops the input and output. 229 */ 230 static sk_sp<SkImageFilter> DropShadowOnly(SkScalar dx, SkScalar dy, 231 SkScalar sigmaX, SkScalar sigmaY, 232 SkColor4f color, sk_sp<SkColorSpace>, 233 sk_sp<SkImageFilter> input, 234 const CropRect& cropRect = {}); 235 static sk_sp<SkImageFilter> DropShadowOnly(SkScalar dx, SkScalar dy, 236 SkScalar sigmaX, SkScalar sigmaY, 237 SkColor color, sk_sp<SkImageFilter> input, 238 const CropRect& cropRect = {}) { 239 return DropShadowOnly(dx, dy, 240 sigmaX, sigmaY, 241 SkColor4f::FromColor(color), /*colorSpace=*/nullptr, 242 std::move(input), 243 cropRect); 244 } 245 246 /** 247 * Create a filter that always produces transparent black. 248 */ 249 static sk_sp<SkImageFilter> Empty(); 250 251 /** 252 * Create a filter that draws the 'srcRect' portion of image into 'dstRect' using the given 253 * filter quality. Similar to SkCanvas::drawImageRect. The returned image filter evaluates 254 * to transparent black if 'image' is null. 255 * 256 * @param image The image that is output by the filter, subset by 'srcRect'. 257 * @param srcRect The source pixels sampled into 'dstRect' 258 * @param dstRect The local rectangle to draw the image into. 259 * @param sampling The sampling to use when drawing the image. 260 */ 261 static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image, const SkRect& srcRect, 262 const SkRect& dstRect, const SkSamplingOptions& sampling); 263 264 /** 265 * Create a filter that draws the image using the given sampling. 266 * Similar to SkCanvas::drawImage. The returned image filter evaluates to transparent black if 267 * 'image' is null. 268 * 269 * @param image The image that is output by the filter. 270 * @param sampling The sampling to use when drawing the image. 271 */ Image(sk_sp<SkImage> image,const SkSamplingOptions & sampling)272 static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image, const SkSamplingOptions& sampling) { 273 if (image) { 274 SkRect r = SkRect::Make(image->bounds()); 275 return Image(std::move(image), r, r, sampling); 276 } else { 277 return nullptr; 278 } 279 } 280 281 /** 282 * Create a filter that fills 'lensBounds' with a magnification of the input. 283 * 284 * @param lensBounds The outer bounds of the magnifier effect 285 * @param zoomAmount The amount of magnification applied to the input image 286 * @param inset The size or width of the fish-eye distortion around the magnified content 287 * @param sampling The SkSamplingOptions applied to the input image when magnified 288 * @param input The input filter that is magnified; if null the source bitmap is used 289 * @param cropRect Optional rectangle that crops the input and output. 290 */ 291 static sk_sp<SkImageFilter> Magnifier(const SkRect& lensBounds, 292 SkScalar zoomAmount, 293 SkScalar inset, 294 const SkSamplingOptions& sampling, 295 sk_sp<SkImageFilter> input, 296 const CropRect& cropRect = {}); 297 298 /** 299 * Create a filter that applies an NxM image processing kernel to the input image. This can be 300 * used to produce effects such as sharpening, blurring, edge detection, etc. 301 * @param kernelSize The kernel size in pixels, in each dimension (N by M). 302 * @param kernel The image processing kernel. Must contain N * M elements, in row order. 303 * @param gain A scale factor applied to each pixel after convolution. This can be 304 * used to normalize the kernel, if it does not already sum to 1. 305 * @param bias A bias factor added to each pixel after convolution. 306 * @param kernelOffset An offset applied to each pixel coordinate before convolution. 307 * This can be used to center the kernel over the image 308 * (e.g., a 3x3 kernel should have an offset of {1, 1}). 309 * @param tileMode How accesses outside the image are treated. 310 * TODO (michaelludwig) - kMirror is not supported yet 311 * @param convolveAlpha If true, all channels are convolved. If false, only the RGB channels 312 * are convolved, and alpha is copied from the source image. 313 * @param input The input image filter, if null the source bitmap is used instead. 314 * @param cropRect Optional rectangle to which the output processing will be limited. 315 */ 316 static sk_sp<SkImageFilter> MatrixConvolution(const SkISize& kernelSize, 317 const SkScalar kernel[], SkScalar gain, 318 SkScalar bias, const SkIPoint& kernelOffset, 319 SkTileMode tileMode, bool convolveAlpha, 320 sk_sp<SkImageFilter> input, 321 const CropRect& cropRect = {}); 322 323 /** 324 * Create a filter that transforms the input image by 'matrix'. This matrix transforms the 325 * local space, which means it effectively happens prior to any transformation coming from the 326 * SkCanvas initiating the filtering. 327 * @param matrix The matrix to apply to the original content. 328 * @param sampling How the image will be sampled when it is transformed 329 * @param input The image filter to transform, or null to use the source image. 330 */ 331 static sk_sp<SkImageFilter> MatrixTransform(const SkMatrix& matrix, 332 const SkSamplingOptions& sampling, 333 sk_sp<SkImageFilter> input); 334 335 /** 336 * Create a filter that merges the 'count' filters together by drawing their results in order 337 * with src-over blending. 338 * @param filters The input filter array to merge, which must have 'count' elements. Any null 339 * filter pointers will use the source bitmap instead. 340 * @param count The number of input filters to be merged. 341 * @param cropRect Optional rectangle that crops all input filters and the output. 342 */ 343 static sk_sp<SkImageFilter> Merge(sk_sp<SkImageFilter>* const filters, int count, 344 const CropRect& cropRect = {}); 345 /** 346 * Create a filter that merges the results of the two filters together with src-over blending. 347 * @param first The first input filter, or the source bitmap if this is null. 348 * @param second The second input filter, or the source bitmap if this null. 349 * @param cropRect Optional rectangle that crops the inputs and output. 350 */ 351 static sk_sp<SkImageFilter> Merge(sk_sp<SkImageFilter> first, sk_sp<SkImageFilter> second, 352 const CropRect& cropRect = {}) { 353 sk_sp<SkImageFilter> array[] = { std::move(first), std::move(second) }; 354 return Merge(array, 2, cropRect); 355 } 356 357 /** 358 * Create a filter that offsets the input filter by the given vector. 359 * @param dx The x offset in local space that the image is shifted. 360 * @param dy The y offset in local space that the image is shifted. 361 * @param input The input that will be moved, if null the source bitmap is used instead. 362 * @param cropRect Optional rectangle to crop the input and output. 363 */ 364 static sk_sp<SkImageFilter> Offset(SkScalar dx, SkScalar dy, sk_sp<SkImageFilter> input, 365 const CropRect& cropRect = {}); 366 367 /** 368 * Create a filter that produces the SkPicture as its output, clipped to both 'targetRect' and 369 * the picture's internal cull rect. 370 * 371 * If 'pic' is null, the returned image filter produces transparent black. 372 * 373 * @param pic The picture that is drawn for the filter output. 374 * @param targetRect The drawing region for the picture. 375 */ 376 static sk_sp<SkImageFilter> Picture(sk_sp<SkPicture> pic, const SkRect& targetRect); 377 // As above, but uses SkPicture::cullRect for the drawing region. Picture(sk_sp<SkPicture> pic)378 static sk_sp<SkImageFilter> Picture(sk_sp<SkPicture> pic) { 379 SkRect target = pic ? pic->cullRect() : SkRect::MakeEmpty(); 380 return Picture(std::move(pic), target); 381 } 382 383 /** 384 * Create a filter that fills the output with the per-pixel evaluation of the SkShader produced 385 * by the SkRuntimeEffectBuilder. The shader is defined in the image filter's local coordinate 386 * system, so it will automatically be affected by SkCanvas' transform. 387 * 388 * This variant assumes that the runtime shader samples 'childShaderName' with the same input 389 * coordinate passed to to shader. 390 * 391 * This requires a GPU backend or SkSL to be compiled in. 392 * 393 * @param builder The builder used to produce the runtime shader, that will in turn 394 * fill the result image 395 * @param childShaderName The name of the child shader defined in the builder that will be 396 * bound to the input param (or the source image if the input param 397 * is null). If empty, the builder can have exactly one child shader, 398 * which automatically binds the input param. 399 * @param input The image filter that will be provided as input to the runtime 400 * shader. If null the implicit source image is used instead 401 */ RuntimeShader(const SkRuntimeEffectBuilder & builder,std::string_view childShaderName,sk_sp<SkImageFilter> input)402 static sk_sp<SkImageFilter> RuntimeShader(const SkRuntimeEffectBuilder& builder, 403 std::string_view childShaderName, 404 sk_sp<SkImageFilter> input) { 405 return RuntimeShader(builder, /*sampleRadius=*/0.f, childShaderName, std::move(input)); 406 } 407 408 /** 409 * As above, but 'sampleRadius' defines the sampling radius of 'childShaderName' relative to 410 * the runtime shader produced by 'builder'. If greater than 0, the coordinate passed to 411 * childShader.eval() will be up to 'sampleRadius' away (maximum absolute offset in 'x' or 'y') 412 * from the coordinate passed into the runtime shader. 413 * 414 * This allows Skia to provide sampleable values for the image filter without worrying about 415 * boundary conditions. 416 * 417 * This requires a GPU backend or SkSL to be compiled in. 418 */ 419 static sk_sp<SkImageFilter> RuntimeShader(const SkRuntimeEffectBuilder& builder, 420 SkScalar sampleRadius, 421 std::string_view childShaderName, 422 sk_sp<SkImageFilter> input); 423 424 /** 425 * Create a filter that fills the output with the per-pixel evaluation of the SkShader produced 426 * by the SkRuntimeEffectBuilder. The shader is defined in the image filter's local coordinate 427 * system, so it will automatically be affected by SkCanvas' transform. 428 * 429 * This requires a GPU backend or SkSL to be compiled in. 430 * 431 * @param builder The builder used to produce the runtime shader, that will in turn 432 * fill the result image 433 * @param childShaderNames The names of the child shaders defined in the builder that will be 434 * bound to the input params (or the source image if the input param 435 * is null). If any name is null, or appears more than once, factory 436 * fails and returns nullptr. 437 * @param inputs The image filters that will be provided as input to the runtime 438 * shader. If any are null, the implicit source image is used instead. 439 * @param inputCount How many entries are present in 'childShaderNames' and 'inputs'. 440 */ RuntimeShader(const SkRuntimeEffectBuilder & builder,std::string_view childShaderNames[],const sk_sp<SkImageFilter> inputs[],int inputCount)441 static sk_sp<SkImageFilter> RuntimeShader(const SkRuntimeEffectBuilder& builder, 442 std::string_view childShaderNames[], 443 const sk_sp<SkImageFilter> inputs[], 444 int inputCount) { 445 return RuntimeShader(builder, /*maxSampleRadius=*/0.f, childShaderNames, 446 inputs, inputCount); 447 } 448 449 /** 450 * As above, but 'maxSampleRadius' defines the sampling limit on coordinates provided to all 451 * child shaders. Like the single-child variant with a sample radius, this can be used to 452 * inform Skia that the runtime shader guarantees that all dynamic children (defined in 453 * childShaderNames) will be evaluated with coordinates at most 'maxSampleRadius' away from the 454 * coordinate provided to the runtime shader itself. 455 * 456 * This requires a GPU backend or SkSL to be compiled in. 457 */ 458 static sk_sp<SkImageFilter> RuntimeShader(const SkRuntimeEffectBuilder& builder, 459 SkScalar maxSampleRadius, 460 std::string_view childShaderNames[], 461 const sk_sp<SkImageFilter> inputs[], 462 int inputCount); 463 464 enum class Dither : bool { 465 kNo = false, 466 kYes = true 467 }; 468 469 /** 470 * Create a filter that fills the output with the per-pixel evaluation of the SkShader. The 471 * shader is defined in the image filter's local coordinate system, so will automatically 472 * be affected by SkCanvas' transform. 473 * 474 * Like Image() and Picture(), this is a leaf filter that can be used to introduce inputs to 475 * a complex filter graph, but should generally be combined with a filter that as at least 476 * one null input to use the implicit source image. 477 * 478 * Returns an image filter that evaluates to transparent black if 'shader' is null. 479 * 480 * @param shader The shader that fills the result image 481 */ 482 static sk_sp<SkImageFilter> Shader(sk_sp<SkShader> shader, const CropRect& cropRect = {}) { 483 return Shader(std::move(shader), Dither::kNo, cropRect); 484 } 485 static sk_sp<SkImageFilter> Shader(sk_sp<SkShader> shader, Dither dither, 486 const CropRect& cropRect = {}); 487 488 /** 489 * Create a tile image filter. 490 * @param src Defines the pixels to tile 491 * @param dst Defines the pixel region that the tiles will be drawn to 492 * @param input The input that will be tiled, if null the source bitmap is used instead. 493 */ 494 static sk_sp<SkImageFilter> Tile(const SkRect& src, const SkRect& dst, 495 sk_sp<SkImageFilter> input); 496 497 // Morphology filter effects 498 499 /** 500 * Create a filter that dilates each input pixel's channel values to the max value within the 501 * given radii along the x and y axes. 502 * @param radiusX The distance to dilate along the x axis to either side of each pixel. 503 * @param radiusY The distance to dilate along the y axis to either side of each pixel. 504 * @param input The image filter that is dilated, using source bitmap if this is null. 505 * @param cropRect Optional rectangle that crops the input and output. 506 */ 507 static sk_sp<SkImageFilter> Dilate(SkScalar radiusX, SkScalar radiusY, 508 sk_sp<SkImageFilter> input, 509 const CropRect& cropRect = {}); 510 511 /** 512 * Create a filter that erodes each input pixel's channel values to the minimum channel value 513 * within the given radii along the x and y axes. 514 * @param radiusX The distance to erode along the x axis to either side of each pixel. 515 * @param radiusY The distance to erode along the y axis to either side of each pixel. 516 * @param input The image filter that is eroded, using source bitmap if this is null. 517 * @param cropRect Optional rectangle that crops the input and output. 518 */ 519 static sk_sp<SkImageFilter> Erode(SkScalar radiusX, SkScalar radiusY, 520 sk_sp<SkImageFilter> input, 521 const CropRect& cropRect = {}); 522 523 // Lighting filter effects 524 525 /** 526 * Create a filter that calculates the diffuse illumination from a distant light source, 527 * interpreting the alpha channel of the input as the height profile of the surface (to 528 * approximate normal vectors). 529 * @param direction The direction to the distance light. 530 * @param lightColor The color of the diffuse light source. 531 * @param surfaceScale Scale factor to transform from alpha values to physical height. 532 * @param kd Diffuse reflectance coefficient. 533 * @param input The input filter that defines surface normals (as alpha), or uses the 534 * source bitmap when null. 535 * @param cropRect Optional rectangle that crops the input and output. 536 */ 537 static sk_sp<SkImageFilter> DistantLitDiffuse(const SkPoint3& direction, SkColor lightColor, 538 SkScalar surfaceScale, SkScalar kd, 539 sk_sp<SkImageFilter> input, 540 const CropRect& cropRect = {}); 541 /** 542 * Create a filter that calculates the diffuse illumination from a point light source, using 543 * alpha channel of the input as the height profile of the surface (to approximate normal 544 * vectors). 545 * @param location The location of the point light. 546 * @param lightColor The color of the diffuse light source. 547 * @param surfaceScale Scale factor to transform from alpha values to physical height. 548 * @param kd Diffuse reflectance coefficient. 549 * @param input The input filter that defines surface normals (as alpha), or uses the 550 * source bitmap when null. 551 * @param cropRect Optional rectangle that crops the input and output. 552 */ 553 static sk_sp<SkImageFilter> PointLitDiffuse(const SkPoint3& location, SkColor lightColor, 554 SkScalar surfaceScale, SkScalar kd, 555 sk_sp<SkImageFilter> input, 556 const CropRect& cropRect = {}); 557 /** 558 * Create a filter that calculates the diffuse illumination from a spot light source, using 559 * alpha channel of the input as the height profile of the surface (to approximate normal 560 * vectors). The spot light is restricted to be within 'cutoffAngle' of the vector between 561 * the location and target. 562 * @param location The location of the spot light. 563 * @param target The location that the spot light is point towards 564 * @param falloffExponent Exponential falloff parameter for illumination outside of cutoffAngle 565 * @param cutoffAngle Maximum angle from lighting direction that receives full light 566 * @param lightColor The color of the diffuse light source. 567 * @param surfaceScale Scale factor to transform from alpha values to physical height. 568 * @param kd Diffuse reflectance coefficient. 569 * @param input The input filter that defines surface normals (as alpha), or uses the 570 * source bitmap when null. 571 * @param cropRect Optional rectangle that crops the input and output. 572 */ 573 static sk_sp<SkImageFilter> SpotLitDiffuse(const SkPoint3& location, const SkPoint3& target, 574 SkScalar falloffExponent, SkScalar cutoffAngle, 575 SkColor lightColor, SkScalar surfaceScale, 576 SkScalar kd, sk_sp<SkImageFilter> input, 577 const CropRect& cropRect = {}); 578 579 /** 580 * Create a filter that calculates the specular illumination from a distant light source, 581 * interpreting the alpha channel of the input as the height profile of the surface (to 582 * approximate normal vectors). 583 * @param direction The direction to the distance light. 584 * @param lightColor The color of the specular light source. 585 * @param surfaceScale Scale factor to transform from alpha values to physical height. 586 * @param ks Specular reflectance coefficient. 587 * @param shininess The specular exponent determining how shiny the surface is. 588 * @param input The input filter that defines surface normals (as alpha), or uses the 589 * source bitmap when null. 590 * @param cropRect Optional rectangle that crops the input and output. 591 */ 592 static sk_sp<SkImageFilter> DistantLitSpecular(const SkPoint3& direction, SkColor lightColor, 593 SkScalar surfaceScale, SkScalar ks, 594 SkScalar shininess, sk_sp<SkImageFilter> input, 595 const CropRect& cropRect = {}); 596 /** 597 * Create a filter that calculates the specular illumination from a point light source, using 598 * alpha channel of the input as the height profile of the surface (to approximate normal 599 * vectors). 600 * @param location The location of the point light. 601 * @param lightColor The color of the specular light source. 602 * @param surfaceScale Scale factor to transform from alpha values to physical height. 603 * @param ks Specular reflectance coefficient. 604 * @param shininess The specular exponent determining how shiny the surface is. 605 * @param input The input filter that defines surface normals (as alpha), or uses the 606 * source bitmap when null. 607 * @param cropRect Optional rectangle that crops the input and output. 608 */ 609 static sk_sp<SkImageFilter> PointLitSpecular(const SkPoint3& location, SkColor lightColor, 610 SkScalar surfaceScale, SkScalar ks, 611 SkScalar shininess, sk_sp<SkImageFilter> input, 612 const CropRect& cropRect = {}); 613 /** 614 * Create a filter that calculates the specular illumination from a spot light source, using 615 * alpha channel of the input as the height profile of the surface (to approximate normal 616 * vectors). The spot light is restricted to be within 'cutoffAngle' of the vector between 617 * the location and target. 618 * @param location The location of the spot light. 619 * @param target The location that the spot light is point towards 620 * @param falloffExponent Exponential falloff parameter for illumination outside of cutoffAngle 621 * @param cutoffAngle Maximum angle from lighting direction that receives full light 622 * @param lightColor The color of the specular light source. 623 * @param surfaceScale Scale factor to transform from alpha values to physical height. 624 * @param ks Specular reflectance coefficient. 625 * @param shininess The specular exponent determining how shiny the surface is. 626 * @param input The input filter that defines surface normals (as alpha), or uses the 627 * source bitmap when null. 628 * @param cropRect Optional rectangle that crops the input and output. 629 */ 630 static sk_sp<SkImageFilter> SpotLitSpecular(const SkPoint3& location, const SkPoint3& target, 631 SkScalar falloffExponent, SkScalar cutoffAngle, 632 SkColor lightColor, SkScalar surfaceScale, 633 SkScalar ks, SkScalar shininess, 634 sk_sp<SkImageFilter> input, 635 const CropRect& cropRect = {}); 636 637 private: 638 SkImageFilters() = delete; 639 }; 640 641 #endif // SkImageFilters_DEFINED 642