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/SkBlendMode.h" 12 #include "include/core/SkColor.h" 13 #include "include/core/SkFilterQuality.h" 14 #include "include/core/SkImage.h" 15 #include "include/core/SkImageFilter.h" 16 #include "include/core/SkPicture.h" 17 #include "include/core/SkRect.h" 18 #include "include/core/SkTileMode.h" 19 20 class SkColorFilter; 21 class SkPaint; 22 class SkRegion; 23 24 // A set of factory functions providing useful SkImageFilter effects. For image filters that take an 25 // input filter, providing nullptr means it will automatically use the dynamic source image. This 26 // source depends on how the filter is applied, but is either the contents of a saved layer when 27 // drawing with SkCanvas, or an explicit SkImage if using SkImage::makeWithFilter. 28 class SK_API SkImageFilters { 29 public: 30 /** 31 * Create a filter that updates the alpha of the image based on 'region'. Pixels inside the 32 * region are made more opaque and pixels outside are made more transparent. 33 * 34 * Specifically, if a pixel is inside the region, its alpha will be set to 35 * max(innerMin, pixel's alpha). If a pixel is outside the region, its alpha will be updated to 36 * min(outerMax, pixel's alpha). 37 * @param region The geometric region controlling the inner and outer alpha thresholds. 38 * @param innerMin The minimum alpha value for pixels inside 'region'. 39 * @param outerMax The maximum alpha value for pixels outside of 'region'. 40 * @param input The input filter, or uses the source bitmap if this is null. 41 * @param cropRect Optional rectangle that crops the input and output. 42 */ 43 static sk_sp<SkImageFilter> AlphaThreshold(const SkRegion& region, SkScalar innerMin, 44 SkScalar outerMax, sk_sp<SkImageFilter> input, 45 const SkIRect* cropRect = nullptr); 46 47 /** 48 * Create a filter that implements a custom blend mode. Each output pixel is the result of 49 * combining the corresponding background and foreground pixels using the 4 coefficients: 50 * k1 * foreground * background + k2 * foreground + k3 * background + k4 51 * @param k1, k2, k3, k4 The four coefficients used to combine the foreground and background. 52 * @param enforcePMColor If true, the RGB channels will be clamped to the calculated alpha. 53 * @param background The background content, using the source bitmap when this is null. 54 * @param foreground The foreground content, using the source bitmap when this is null. 55 * @param cropRect Optional rectangle that crops the inputs and output. 56 */ 57 static sk_sp<SkImageFilter> Arithmetic(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, 58 bool enforcePMColor, sk_sp<SkImageFilter> background, 59 sk_sp<SkImageFilter> foreground, 60 const SkIRect* cropRect = nullptr); 61 62 /** 63 * Create a filter that blurs its input by the separate X and Y sigmas. The provided tile mode 64 * is used when the blur kernel goes outside the input image. 65 * @param sigmaX The Gaussian sigma value for blurring along the X axis. 66 * @param sigmaY The Gaussian sigma value for blurring along the Y axis. 67 * @param tileMode The tile mode applied at edges . 68 * TODO (michaelludwig) - kMirror is not supported yet 69 * @param input The input filter that is blurred, uses source bitmap if this is null. 70 * @param cropRect Optional rectangle that crops the input and output. 71 */ 72 static sk_sp<SkImageFilter> Blur(SkScalar sigmaX, SkScalar sigmaY, SkTileMode tileMode, 73 sk_sp<SkImageFilter> input, const SkIRect* cropRect = nullptr); 74 // As above, but defaults to the decal tile mode. 75 static sk_sp<SkImageFilter> Blur(SkScalar sigmaX, SkScalar sigmaY, sk_sp<SkImageFilter> input, 76 const SkIRect* cropRect = nullptr) { 77 return Blur(sigmaX, sigmaY, SkTileMode::kDecal, std::move(input), cropRect); 78 } 79 80 /** 81 * Create a filter that applies the color filter to the input filter results. 82 * @param cf The color filter that transforms the input image. 83 * @param input The input filter, or uses the source bitmap if this is null. 84 * @param cropRect Optional rectangle that crops the input and output. 85 */ 86 static sk_sp<SkImageFilter> ColorFilter(sk_sp<SkColorFilter> cf, sk_sp<SkImageFilter> input, 87 const SkIRect* cropRect = nullptr); 88 89 /** 90 * Create a filter that composes 'inner' with 'outer', such that the results of 'inner' are 91 * treated as the source bitmap passed to 'outer', i.e. result = outer(inner(source)). 92 * @param outer The outer filter that evaluates the results of inner. 93 * @param inner The inner filter that produces the input to outer. 94 */ 95 static sk_sp<SkImageFilter> Compose(sk_sp<SkImageFilter> outer, sk_sp<SkImageFilter> inner); 96 97 /** 98 * Create a filter that moves each pixel in its color input based on an (x,y) vector encoded 99 * in its displacement input filter. Two color components of the displacement image are 100 * mapped into a vector as scale * (color[xChannel], color[yChannel]), where the channel 101 * selectors are one of R, G, B, or A. 102 * @param xChannelSelector RGBA channel that encodes the x displacement per pixel. 103 * @param yChannelSelector RGBA channel that encodes the y displacement per pixel. 104 * @param scale Scale applied to displacement extracted from image. 105 * @param displacement The filter defining the displacement image, or null to use source. 106 * @param color The filter providing the color pixels to be displaced. 107 * @param cropRect Optional rectangle that crops the color input and output. 108 */ 109 static sk_sp<SkImageFilter> DisplacementMap(SkColorChannel xChannelSelector, 110 SkColorChannel yChannelSelector, 111 SkScalar scale, sk_sp<SkImageFilter> displacement, 112 sk_sp<SkImageFilter> color, 113 const SkIRect* cropRect = nullptr); 114 115 /** 116 * Create a filter that draws a drop shadow under the input content. This filter produces an 117 * image that includes the inputs' content. 118 * @param dx The X offset of the shadow. 119 * @param dy The Y offset of the shadow. 120 * @param sigmaX The blur radius for the shadow, along the X axis. 121 * @param sigmaY The blur radius for the shadow, along the Y axis. 122 * @param color The color of the drop shadow. 123 * @param input The input filter, or will use the source bitmap if this is null. 124 * @param cropRect Optional rectangle that crops the input and output. 125 */ 126 static sk_sp<SkImageFilter> DropShadow(SkScalar dx, SkScalar dy, 127 SkScalar sigmaX, SkScalar sigmaY, 128 SkColor color, sk_sp<SkImageFilter> input, 129 const SkIRect* cropRect = nullptr); 130 /** 131 * Create a filter that renders a drop shadow, in exactly the same manner as ::DropShadow, 132 * except that the resulting image does not include the input content. This allows the shadow 133 * and input to be composed by a filter DAG in a more flexible manner. 134 * @param dx The X offset of the shadow. 135 * @param dy The Y offset of the shadow. 136 * @param sigmaX The blur radius for the shadow, along the X axis. 137 * @param sigmaY The blur radius for the shadow, along the Y axis. 138 * @param color The color of the drop shadow. 139 * @param input The input filter, or will use the source bitmap if this is null. 140 * @param cropRect Optional rectangle that crops the input and output. 141 */ 142 static sk_sp<SkImageFilter> DropShadowOnly(SkScalar dx, SkScalar dy, 143 SkScalar sigmaX, SkScalar sigmaY, 144 SkColor color, sk_sp<SkImageFilter> input, 145 const SkIRect* cropRect = nullptr); 146 147 /** 148 * Create a filter that draws the 'srcRect' portion of image into 'dstRect' using the given 149 * filter quality. Similar to SkCanvas::drawImageRect. Returns null if 'image' is null. 150 * @param image The image that is output by the filter, subset by 'srcRect'. 151 * @param srcRect The source pixels sampled into 'dstRect' 152 * @param dstRect The local rectangle to draw the image into. 153 * @param filterQuality The filter quality that is used when sampling the image. 154 */ 155 static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image, const SkRect& srcRect, 156 const SkRect& dstRect, SkFilterQuality filterQuality); 157 /** 158 * Create a filter that produces the image contents. 159 * @param image The image that is output by the filter. 160 */ Image(sk_sp<SkImage> image)161 static sk_sp<SkImageFilter> Image(sk_sp<SkImage> image) { 162 // Defaults to kHigh_SkFilterQuality because the dstRect of the image filter will be mapped 163 // by the layer matrix set during filtering. If that has a scale factor, then the image 164 // will not be drawn at a 1-to-1 pixel scale, even that is what this appears to create here. 165 SkRect r = image ? SkRect::MakeWH(image->width(), image->height()) : SkRect::MakeEmpty(); 166 return Image(std::move(image), r, r, kHigh_SkFilterQuality); 167 } 168 169 /** 170 * Create a filter that mimics a zoom/magnifying lens effect. 171 * @param srcRect 172 * @param inset 173 * @param input The input filter that is magnified, if null the source bitmap is used. 174 * @param cropRect Optional rectangle that crops the input and output. 175 */ 176 static sk_sp<SkImageFilter> Magnifier(const SkRect& srcRect, SkScalar inset, 177 sk_sp<SkImageFilter> input, 178 const SkIRect* cropRect = nullptr); 179 180 /** 181 * Create a filter that applies an NxM image processing kernel to the input image. This can be 182 * used to produce effects such as sharpening, blurring, edge detection, etc. 183 * @param kernelSize The kernel size in pixels, in each dimension (N by M). 184 * @param kernel The image processing kernel. Must contain N * M elements, in row order. 185 * @param gain A scale factor applied to each pixel after convolution. This can be 186 * used to normalize the kernel, if it does not already sum to 1. 187 * @param bias A bias factor added to each pixel after convolution. 188 * @param kernelOffset An offset applied to each pixel coordinate before convolution. 189 * This can be used to center the kernel over the image 190 * (e.g., a 3x3 kernel should have an offset of {1, 1}). 191 * @param tileMode How accesses outside the image are treated. 192 * TODO (michaelludwig) - kMirror is not supported yet 193 * @param convolveAlpha If true, all channels are convolved. If false, only the RGB channels 194 * are convolved, and alpha is copied from the source image. 195 * @param input The input image filter, if null the source bitmap is used instead. 196 * @param cropRect Optional rectangle to which the output processing will be limited. 197 */ 198 static sk_sp<SkImageFilter> MatrixConvolution(const SkISize& kernelSize, 199 const SkScalar kernel[], SkScalar gain, 200 SkScalar bias, const SkIPoint& kernelOffset, 201 SkTileMode tileMode, bool convolveAlpha, 202 sk_sp<SkImageFilter> input, 203 const SkIRect* cropRect = nullptr); 204 205 /** 206 * Create a filter that transforms the input image by 'matrix'. This matrix transforms the 207 * local space, which means it effectively happens prior to any transformation coming from the 208 * SkCanvas initiating the filtering. 209 * @param matrix The matrix to apply to the original content. 210 * @param filterQuality The filter quality to use when sampling the input image. 211 * @param input The image filter to transform, or null to use the source image. 212 */ 213 static sk_sp<SkImageFilter> MatrixTransform(const SkMatrix& matrix, 214 SkFilterQuality filterQuality, 215 sk_sp<SkImageFilter> input); 216 217 /** 218 * Create a filter that merges the 'count' filters together by drawing their results in order 219 * with src-over blending. 220 * @param filters The input filter array to merge, which must have 'count' elements. Any null 221 * filter pointers will use the source bitmap instead. 222 * @param count The number of input filters to be merged. 223 * @param cropRect Optional rectangle that crops all input filters and the output. 224 */ 225 static sk_sp<SkImageFilter> Merge(sk_sp<SkImageFilter>* const filters, int count, 226 const SkIRect* cropRect = nullptr); 227 /** 228 * Create a filter that merges the results of the two filters together with src-over blending. 229 * @param first The first input filter, or the source bitmap if this is null. 230 * @param second The second input filter, or the source bitmap if this null. 231 * @param cropRect Optional rectangle that crops the inputs and output. 232 */ 233 static sk_sp<SkImageFilter> Merge(sk_sp<SkImageFilter> first, sk_sp<SkImageFilter> second, 234 const SkIRect* cropRect = nullptr) { 235 sk_sp<SkImageFilter> array[] = { std::move(first), std::move(second) }; 236 return Merge(array, 2, cropRect); 237 } 238 239 /** 240 * Create a filter that offsets the input filter by the given vector. 241 * @param dx The x offset in local space that the image is shifted. 242 * @param dy The y offset in local space that the image is shifted. 243 * @param input The input that will be moved, if null the source bitmap is used instead. 244 * @param cropRect Optional rectangle to crop the input and output. 245 */ 246 static sk_sp<SkImageFilter> Offset(SkScalar dx, SkScalar dy, sk_sp<SkImageFilter> input, 247 const SkIRect* cropRect = nullptr); 248 249 /** 250 * Create a filter that fills the output with the given paint. 251 * @param paint The paint to fill 252 * @param cropRect Optional rectangle that will be filled. If null, the source bitmap's bounds 253 * are filled even though the source bitmap itself is not used. 254 */ 255 static sk_sp<SkImageFilter> Paint(const SkPaint& paint, const SkIRect* cropRect = nullptr); 256 257 /** 258 * Create a filter that produces the SkPicture as its output, drawn into targetRect. Note that 259 * the targetRect is not the same as the SkIRect cropRect that many filters accept. Returns 260 * null if 'pic' is null. 261 * @param pic The picture that is drawn for the filter output. 262 * @param targetRect The drawing region for the picture. 263 */ 264 static sk_sp<SkImageFilter> Picture(sk_sp<SkPicture> pic, const SkRect& targetRect); 265 // As above, but uses SkPicture::cullRect for the drawing region. Picture(sk_sp<SkPicture> pic)266 static sk_sp<SkImageFilter> Picture(sk_sp<SkPicture> pic) { 267 SkRect target = pic ? pic->cullRect() : SkRect::MakeEmpty(); 268 return Picture(std::move(pic), target); 269 } 270 271 /** 272 * Create a tile image filter. 273 * @param src Defines the pixels to tile 274 * @param dst Defines the pixel region that the tiles will be drawn to 275 * @param input The input that will be tiled, if null the source bitmap is used instead. 276 */ 277 static sk_sp<SkImageFilter> Tile(const SkRect& src, const SkRect& dst, 278 sk_sp<SkImageFilter> input); 279 280 /** 281 * This filter takes an SkBlendMode and uses it to composite the two filters together. 282 * @param background The Dst pixels used in blending, if null the source bitmap is used. 283 * @param foreground The Src pixels used in blending, if null the source bitmap is used. 284 * @cropRect Optional rectangle to crop input and output. 285 */ 286 static sk_sp<SkImageFilter> Xfermode(SkBlendMode, sk_sp<SkImageFilter> background, 287 sk_sp<SkImageFilter> foreground = nullptr, 288 const SkIRect* cropRect = nullptr); 289 290 // Morphology filter effects 291 292 /** 293 * Create a filter that dilates each input pixel's channel values to the max value within the 294 * given radii along the x and y axes. 295 * @param radiusX The distance to dilate along the x axis to either side of each pixel. 296 * @param radiusY The distance to dilate along the y axis to either side of each pixel. 297 * @param input The image filter that is dilated, using source bitmap if this is null. 298 * @param cropRect Optional rectangle that crops the input and output. 299 */ 300 static sk_sp<SkImageFilter> Dilate(int radiusX, int radiusY, sk_sp<SkImageFilter> input, 301 const SkIRect* cropRect = nullptr); 302 303 /** 304 * Create a filter that erodes each input pixel's channel values to the minimum channel value 305 * within the given radii along the x and y axes. 306 * @param radiusX The distance to erode along the x axis to either side of each pixel. 307 * @param radiusY The distance to erode along the y axis to either side of each pixel. 308 * @param input The image filter that is eroded, using source bitmap if this is null. 309 * @param cropRect Optional rectangle that crops the input and output. 310 */ 311 static sk_sp<SkImageFilter> Erode(int radiusX, int radiusY, sk_sp<SkImageFilter> input, 312 const SkIRect* cropRect = nullptr); 313 314 // Lighting filter effects 315 316 /** 317 * Create a filter that calculates the diffuse illumination from a distant light source, 318 * interpreting the alpha channel of the input as the height profile of the surface (to 319 * approximate normal vectors). 320 * @param direction The direction to the distance light. 321 * @param lightColor The color of the diffuse light source. 322 * @param surfaceScale Scale factor to transform from alpha values to physical height. 323 * @param kd Diffuse reflectance coefficient. 324 * @param input The input filter that defines surface normals (as alpha), or uses the 325 * source bitmap when null. 326 * @param cropRect Optional rectangle that crops the input and output. 327 */ 328 static sk_sp<SkImageFilter> DistantLitDiffuse(const SkPoint3& direction, SkColor lightColor, 329 SkScalar surfaceScale, SkScalar kd, 330 sk_sp<SkImageFilter> input, 331 const SkIRect* cropRect = nullptr); 332 /** 333 * Create a filter that calculates the diffuse illumination from a point light source, using 334 * alpha channel of the input as the height profile of the surface (to approximate normal 335 * vectors). 336 * @param location The location of the point light. 337 * @param lightColor The color of the diffuse light source. 338 * @param surfaceScale Scale factor to transform from alpha values to physical height. 339 * @param kd Diffuse reflectance coefficient. 340 * @param input The input filter that defines surface normals (as alpha), or uses the 341 * source bitmap when null. 342 * @param cropRect Optional rectangle that crops the input and output. 343 */ 344 static sk_sp<SkImageFilter> PointLitDiffuse(const SkPoint3& location, SkColor lightColor, 345 SkScalar surfaceScale, SkScalar kd, 346 sk_sp<SkImageFilter> input, 347 const SkIRect* cropRect = nullptr); 348 /** 349 * Create a filter that calculates the diffuse illumination from a spot light source, using 350 * alpha channel of the input as the height profile of the surface (to approximate normal 351 * vectors). The spot light is restricted to be within 'cutoffAngle' of the vector between 352 * the location and target. 353 * @param location The location of the spot light. 354 * @param target The location that the spot light is point towards 355 * @param falloffExponent Exponential falloff parameter for illumination outside of cutoffAngle 356 * @param cutoffAngle Maximum angle from lighting direction that receives full light 357 * @param lightColor The color of the diffuse light source. 358 * @param surfaceScale Scale factor to transform from alpha values to physical height. 359 * @param kd Diffuse reflectance coefficient. 360 * @param input The input filter that defines surface normals (as alpha), or uses the 361 * source bitmap when null. 362 * @param cropRect Optional rectangle that crops the input and output. 363 */ 364 static sk_sp<SkImageFilter> SpotLitDiffuse(const SkPoint3& location, const SkPoint3& target, 365 SkScalar falloffExponent, SkScalar cutoffAngle, 366 SkColor lightColor, SkScalar surfaceScale, 367 SkScalar kd, sk_sp<SkImageFilter> input, 368 const SkIRect* cropRect = nullptr); 369 370 /** 371 * Create a filter that calculates the specular illumination from a distant light source, 372 * interpreting the alpha channel of the input as the height profile of the surface (to 373 * approximate normal vectors). 374 * @param direction The direction to the distance light. 375 * @param lightColor The color of the specular light source. 376 * @param surfaceScale Scale factor to transform from alpha values to physical height. 377 * @param ks Specular reflectance coefficient. 378 * @param shininess The specular exponent determining how shiny the surface is. 379 * @param input The input filter that defines surface normals (as alpha), or uses the 380 * source bitmap when null. 381 * @param cropRect Optional rectangle that crops the input and output. 382 */ 383 static sk_sp<SkImageFilter> DistantLitSpecular(const SkPoint3& direction, SkColor lightColor, 384 SkScalar surfaceScale, SkScalar ks, 385 SkScalar shininess, sk_sp<SkImageFilter> input, 386 const SkIRect* cropRect = nullptr); 387 /** 388 * Create a filter that calculates the specular illumination from a point light source, using 389 * alpha channel of the input as the height profile of the surface (to approximate normal 390 * vectors). 391 * @param location The location of the point light. 392 * @param lightColor The color of the specular light source. 393 * @param surfaceScale Scale factor to transform from alpha values to physical height. 394 * @param ks Specular reflectance coefficient. 395 * @param shininess The specular exponent determining how shiny the surface is. 396 * @param input The input filter that defines surface normals (as alpha), or uses the 397 * source bitmap when null. 398 * @param cropRect Optional rectangle that crops the input and output. 399 */ 400 static sk_sp<SkImageFilter> PointLitSpecular(const SkPoint3& location, SkColor lightColor, 401 SkScalar surfaceScale, SkScalar ks, 402 SkScalar shininess, sk_sp<SkImageFilter> input, 403 const SkIRect* cropRect = nullptr); 404 /** 405 * Create a filter that calculates the specular illumination from a spot light source, using 406 * alpha channel of the input as the height profile of the surface (to approximate normal 407 * vectors). The spot light is restricted to be within 'cutoffAngle' of the vector between 408 * the location and target. 409 * @param location The location of the spot light. 410 * @param target The location that the spot light is point towards 411 * @param falloffExponent Exponential falloff parameter for illumination outside of cutoffAngle 412 * @param cutoffAngle Maximum angle from lighting direction that receives full light 413 * @param lightColor The color of the specular light source. 414 * @param surfaceScale Scale factor to transform from alpha values to physical height. 415 * @param ks Specular reflectance coefficient. 416 * @param shininess The specular exponent determining how shiny the surface is. 417 * @param input The input filter that defines surface normals (as alpha), or uses the 418 * source bitmap when null. 419 * @param cropRect Optional rectangle that crops the input and output. 420 */ 421 static sk_sp<SkImageFilter> SpotLitSpecular(const SkPoint3& location, const SkPoint3& target, 422 SkScalar falloffExponent, SkScalar cutoffAngle, 423 SkColor lightColor, SkScalar surfaceScale, 424 SkScalar ks, SkScalar shininess, 425 sk_sp<SkImageFilter> input, 426 const SkIRect* cropRect = nullptr); 427 428 static void RegisterFlattenables(); 429 430 private: 431 SkImageFilters() = delete; 432 }; 433 434 #endif // SkImageFilters_DEFINED 435