2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
23 ==============================================================================
29 ImageConvolutionKernel::ImageConvolutionKernel (int sizeToUse
)
30 : values ((size_t) (sizeToUse
* sizeToUse
)),
36 ImageConvolutionKernel::~ImageConvolutionKernel()
40 //==============================================================================
41 float ImageConvolutionKernel::getKernelValue (const int x
, const int y
) const noexcept
43 if (isPositiveAndBelow (x
, size
) && isPositiveAndBelow (y
, size
))
44 return values
[x
+ y
* size
];
50 void ImageConvolutionKernel::setKernelValue (const int x
, const int y
, const float value
) noexcept
52 if (isPositiveAndBelow (x
, size
) && isPositiveAndBelow (y
, size
))
54 values
[x
+ y
* size
] = value
;
62 void ImageConvolutionKernel::clear()
64 for (int i
= size
* size
; --i
>= 0;)
68 void ImageConvolutionKernel::setOverallSum (const float desiredTotalSum
)
70 double currentTotal
= 0.0;
72 for (int i
= size
* size
; --i
>= 0;)
73 currentTotal
+= values
[i
];
75 rescaleAllValues ((float) (desiredTotalSum
/ currentTotal
));
78 void ImageConvolutionKernel::rescaleAllValues (const float multiplier
)
80 for (int i
= size
* size
; --i
>= 0;)
81 values
[i
] *= multiplier
;
84 //==============================================================================
85 void ImageConvolutionKernel::createGaussianBlur (const float radius
)
87 const double radiusFactor
= -1.0 / (radius
* radius
* 2);
88 const int centre
= size
>> 1;
90 for (int y
= size
; --y
>= 0;)
92 for (int x
= size
; --x
>= 0;)
97 values
[x
+ y
* size
] = (float) std::exp (radiusFactor
* (cx
* cx
+ cy
* cy
));
101 setOverallSum (1.0f
);
104 //==============================================================================
105 void ImageConvolutionKernel::applyToImage (Image
& destImage
,
106 const Image
& sourceImage
,
107 const Rectangle
<int>& destinationArea
) const
109 if (sourceImage
== destImage
)
111 destImage
.duplicateIfShared();
115 if (sourceImage
.getWidth() != destImage
.getWidth()
116 || sourceImage
.getHeight() != destImage
.getHeight()
117 || sourceImage
.getFormat() != destImage
.getFormat())
124 auto area
= destinationArea
.getIntersection (destImage
.getBounds());
129 auto right
= area
.getRight();
130 auto bottom
= area
.getBottom();
132 const Image::BitmapData
destData (destImage
, area
.getX(), area
.getY(), area
.getWidth(), area
.getHeight(),
133 Image::BitmapData::writeOnly
);
134 uint8
* line
= destData
.data
;
136 const Image::BitmapData
srcData (sourceImage
, Image::BitmapData::readOnly
);
138 if (destData
.pixelStride
== 4)
140 for (int y
= area
.getY(); y
< bottom
; ++y
)
143 line
+= destData
.lineStride
;
145 for (int x
= area
.getX(); x
< right
; ++x
)
152 for (int yy
= 0; yy
< size
; ++yy
)
154 const int sy
= y
+ yy
- (size
>> 1);
156 if (sy
>= srcData
.height
)
161 int sx
= x
- (size
>> 1);
162 const uint8
* src
= srcData
.getPixelPointer (sx
, sy
);
164 for (int xx
= 0; xx
< size
; ++xx
)
166 if (sx
>= srcData
.width
)
171 const float kernelMult
= values
[xx
+ yy
* size
];
172 c1
+= kernelMult
* *src
++;
173 c2
+= kernelMult
* *src
++;
174 c3
+= kernelMult
* *src
++;
175 c4
+= kernelMult
* *src
++;
187 *dest
++ = (uint8
) jmin (0xff, roundToInt (c1
));
188 *dest
++ = (uint8
) jmin (0xff, roundToInt (c2
));
189 *dest
++ = (uint8
) jmin (0xff, roundToInt (c3
));
190 *dest
++ = (uint8
) jmin (0xff, roundToInt (c4
));
194 else if (destData
.pixelStride
== 3)
196 for (int y
= area
.getY(); y
< bottom
; ++y
)
199 line
+= destData
.lineStride
;
201 for (int x
= area
.getX(); x
< right
; ++x
)
207 for (int yy
= 0; yy
< size
; ++yy
)
209 const int sy
= y
+ yy
- (size
>> 1);
211 if (sy
>= srcData
.height
)
216 int sx
= x
- (size
>> 1);
217 const uint8
* src
= srcData
.getPixelPointer (sx
, sy
);
219 for (int xx
= 0; xx
< size
; ++xx
)
221 if (sx
>= srcData
.width
)
226 const float kernelMult
= values
[xx
+ yy
* size
];
227 c1
+= kernelMult
* *src
++;
228 c2
+= kernelMult
* *src
++;
229 c3
+= kernelMult
* *src
++;
241 *dest
++ = (uint8
) roundToInt (c1
);
242 *dest
++ = (uint8
) roundToInt (c2
);
243 *dest
++ = (uint8
) roundToInt (c3
);
247 else if (destData
.pixelStride
== 1)
249 for (int y
= area
.getY(); y
< bottom
; ++y
)
252 line
+= destData
.lineStride
;
254 for (int x
= area
.getX(); x
< right
; ++x
)
258 for (int yy
= 0; yy
< size
; ++yy
)
260 const int sy
= y
+ yy
- (size
>> 1);
262 if (sy
>= srcData
.height
)
267 int sx
= x
- (size
>> 1);
268 const uint8
* src
= srcData
.getPixelPointer (sx
, sy
);
270 for (int xx
= 0; xx
< size
; ++xx
)
272 if (sx
>= srcData
.width
)
277 const float kernelMult
= values
[xx
+ yy
* size
];
278 c1
+= kernelMult
* *src
++;
290 *dest
++ = (uint8
) roundToInt (c1
);