mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Draw: GaussianBlur
git-svn-id: svn://ultimatepp.org/upp/trunk@14334 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
53e8512d7a
commit
4e2a511e1e
4 changed files with 148 additions and 2 deletions
|
|
@ -134,8 +134,7 @@ void CoDo_ST(Function<void ()>&& fn)
|
|||
template <typename Fn>
|
||||
void CoFor(int n, Fn iterator)
|
||||
{
|
||||
std::atomic<int> ii;
|
||||
ii = 0;
|
||||
std::atomic<int> ii(0);
|
||||
CoDo([&] {
|
||||
for(int i = ii++; i < n; i = ii++)
|
||||
iterator(i);
|
||||
|
|
|
|||
|
|
@ -952,4 +952,143 @@ Image Dither(const Image& m, int dival)
|
|||
return ib;
|
||||
}
|
||||
|
||||
Image GaussianBlur(const Image& img, int radius, bool co)
|
||||
{
|
||||
// This code is adapted from Ivan Kutskir's fast blur implementation, published under MIT license.
|
||||
// See: http://blog.ivank.net/fastest-gaussian-blur.html
|
||||
|
||||
// An implementation of well known fast box and gaussian blur
|
||||
// approximation algorithms by Wojciech Jarosz and Peter Kovesi.
|
||||
// See: https://elynxsdk.free.fr/ext-docs/Blur/Fast_box_blur.pdf
|
||||
// See: https://www.peterkovesi.com/papers/FastGaussianSmoothing.pdf
|
||||
|
||||
auto ApplyBoxBlur = [&](const Image& src, int r) -> Image
|
||||
{
|
||||
double avg = 1.0 / (r + r + 1);
|
||||
|
||||
Size sz = src.GetSize();
|
||||
|
||||
ImageBuffer tmp(sz);
|
||||
ImageBuffer out(sz);
|
||||
|
||||
auto DoLine = [&](int i) {
|
||||
int ti = 0;
|
||||
int li = ti;
|
||||
int ri = r;
|
||||
const RGBA& fv = src[i][0];
|
||||
const RGBA& lv = src[i][sz.cx - 1];
|
||||
dword rsum = fv.r * (r + 1);
|
||||
dword gsum = fv.g * (r + 1);
|
||||
dword bsum = fv.b * (r + 1);
|
||||
dword asum = fv.a * (r + 1);
|
||||
for(int j = 0; j < r; j++) {
|
||||
const RGBA& p = src[i][j];
|
||||
rsum += p.r;
|
||||
gsum += p.g;
|
||||
bsum += p.b;
|
||||
asum += p.a;
|
||||
}
|
||||
for(int j = 0; j <= r; j++) {
|
||||
const RGBA& p = src[i][ri++];
|
||||
RGBA& q = tmp[i][ti++];
|
||||
q.r = (rsum += p.r - fv.r) * avg;
|
||||
q.g = (gsum += p.g - fv.g) * avg;
|
||||
q.b = (bsum += p.b - fv.b) * avg;
|
||||
q.a = (asum += p.a - fv.a) * avg;
|
||||
}
|
||||
for(int j = r + 1; j < sz.cx - r; j++) {
|
||||
const RGBA& p = src[i][ri++];
|
||||
const RGBA& q = src[i][li++];
|
||||
RGBA& t = tmp[i][ti++];
|
||||
t.r = (rsum += p.r - q.r) * avg;
|
||||
t.g = (gsum += p.g - q.g) * avg;
|
||||
t.b = (bsum += p.b - q.b) * avg;
|
||||
t.a = (asum += p.a - q.a) * avg;
|
||||
}
|
||||
for(int j = sz.cx - r; j < sz.cx ; j++) {
|
||||
const RGBA& p = src[i][li++];
|
||||
RGBA& q = tmp[i][ti++];
|
||||
q.r = (rsum += lv.r - p.r) * avg;
|
||||
q.g = (gsum += lv.g - p.g) * avg;
|
||||
q.b = (bsum += lv.b - p.b) * avg;
|
||||
q.a = (asum += lv.a - p.a) * avg;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if(co)
|
||||
CoFor(sz.cy, [&](int i) { DoLine(i); });
|
||||
else
|
||||
for(int i = 0; i < sz.cy; i++)
|
||||
DoLine(i);
|
||||
|
||||
auto DoColumn = [&](int i) {
|
||||
int ti = 0;
|
||||
int li = ti;
|
||||
int ri = r;
|
||||
const RGBA& fv = tmp[ti][i];
|
||||
const RGBA& lv = tmp[sz.cy - 1][i];
|
||||
dword rsum = fv.r * (r + 1);
|
||||
dword gsum = fv.g * (r + 1);
|
||||
dword bsum = fv.b * (r + 1);
|
||||
dword asum = fv.a * (r + 1);
|
||||
for(int j = 0; j < r; j++) {
|
||||
const RGBA& p = tmp[j][i];
|
||||
rsum += p.r;
|
||||
gsum += p.g;
|
||||
bsum += p.b;
|
||||
asum += p.a;
|
||||
}
|
||||
for(int j = 0; j <= r; j++) {
|
||||
const RGBA& p = tmp[ri++][i];
|
||||
RGBA& q = out[ti++][i];
|
||||
q.r = (rsum += p.r - fv.r) * avg;
|
||||
q.g = (gsum += p.g - fv.g) * avg;
|
||||
q.b = (bsum += p.b - fv.b) * avg;
|
||||
q.a = (asum += p.a - fv.a) * avg;
|
||||
}
|
||||
for(int j = r + 1; j < sz.cy - r; j++) {
|
||||
const RGBA& p = tmp[ri++][i];
|
||||
const RGBA& q = tmp[li++][i];
|
||||
RGBA& t = out[ti++][i];
|
||||
t.r = (rsum += p.r - q.r) * avg;
|
||||
t.g = (gsum += p.g - q.g) * avg;
|
||||
t.b = (bsum += p.b - q.b) * avg;
|
||||
t.a = (asum += p.a - q.a) * avg;
|
||||
}
|
||||
for(int j = sz.cy - r; j < sz.cy; j++) {
|
||||
const RGBA& p = tmp[li++][i];
|
||||
RGBA& q = out[ti++][i];
|
||||
q.r = (rsum += lv.r - p.r) * avg;
|
||||
q.g = (gsum += lv.g - p.g) * avg;
|
||||
q.b = (bsum += lv.b - p.b) * avg;
|
||||
q.a = (asum += lv.a - p.a) * avg;
|
||||
}
|
||||
};
|
||||
|
||||
if(co)
|
||||
CoFor(sz.cx, [&](int i) { DoColumn(i); });
|
||||
else
|
||||
for(int i = 0; i < sz.cx; i++)
|
||||
DoColumn(i);
|
||||
|
||||
out.SetHotSpots(src);
|
||||
out.SetResolution(src.GetResolution());
|
||||
return out;
|
||||
};
|
||||
|
||||
if(radius < 1 || IsNull(img))
|
||||
return img;
|
||||
|
||||
double wl = ffloor(sqrt((12 * sqr(radius) / 3) + 1));
|
||||
if(fmod(wl, 2) == 0) wl--;
|
||||
double wu = wl + 2;
|
||||
double m = fround((12 * sqr(radius) - 3 * sqr(wl) - 4 * 3 * wl - 3 * 3) / (-4 * wl - 4));
|
||||
Vector<int> sizes;
|
||||
Image t = img;
|
||||
for (int i = 0; i < 3; i++)
|
||||
t = ApplyBoxBlur(t, ((i < m ? wl : wu) - 1) / 2);
|
||||
return pick(t);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ void Filter(RasterEncoder& target, Raster& src, ImageFilter9& filter);
|
|||
Image Etched(const Image& img);
|
||||
Image Sharpen(const Image& img, int amount = 100);
|
||||
Image Dither(const Image& m, int dival = 394);
|
||||
Image GaussianBlur(const Image& img, int radius, bool co = false);
|
||||
|
||||
Image RotateClockwise(const Image& img);
|
||||
Image RotateAntiClockwise(const Image& img);
|
||||
|
|
|
|||
|
|
@ -258,6 +258,13 @@ dithering is using for printing on purely monochromatic (without
|
|||
half`-toning support) printers.&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:GaussianBlur`(const Upp`:`:Image`&`,int`): [_^Upp`:`:Image^ Image]_[* Gaussia
|
||||
nBlur]([@(0.0.255) const]_[_^Upp`:`:Image^ Image][@(0.0.255) `&]_[*@3 img],
|
||||
[@(0.0.255) int]_[*@3 radius])&]
|
||||
[s2; [@N An implementation of well known fast box and gaussian blur
|
||||
approximation algorithms by Wojciech Jarosz and Peter Kovesi.]&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Etched`(const Image`&`): [_^Image^ Image]_[* Etched]([@(0.0.255) const]_[_^Image^ Image][@(0.0.255) `&
|
||||
]_[*@3 img])&]
|
||||
[s2;%% `"Etching`" effect.&]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue