• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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