improve performance of blur algorithm
This commit is contained in:
parent
18481b97ee
commit
ca9e597e37
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Image Processor Algorithm Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -551,54 +551,64 @@ namespace detail
|
||||
{
|
||||
void process(pixel_buffer& pixbuf, const nana::rectangle& area, std::size_t u_radius) const
|
||||
{
|
||||
int radius = static_cast<int>(u_radius);
|
||||
int w = area.width;
|
||||
int h = area.height;
|
||||
int wm = w - 1;
|
||||
int hm = h - 1;
|
||||
int wh = w * h;
|
||||
int div = (radius << 1) + 1;
|
||||
const int radius = static_cast<int>(u_radius);
|
||||
const int safe_radius = std::min(radius, static_cast<int>(area.height) - 2);
|
||||
const int radius_plus_one = radius + 1;
|
||||
|
||||
int large_edge = (w > h ? w : h);
|
||||
const int div_256 = div * 256;
|
||||
const int width_3times = static_cast<int>(area.width * 3);
|
||||
const int wm = area.width - 1;
|
||||
const int hm = area.height - 1;
|
||||
const int wh = area.width * area.height;
|
||||
const int div = (radius << 1) + 1;
|
||||
|
||||
std::unique_ptr<int[]> table_rgb(new int[(wh << 1) + wh + (large_edge << 1) + div_256]);
|
||||
const int large_edge = std::max(area.width, area.height);
|
||||
|
||||
std::unique_ptr<int[]> table_rgb(new int[wh * 3 + (large_edge << 1) + div * 256]);
|
||||
|
||||
int * tbl_r = table_rgb.get();
|
||||
int * tbl_g = tbl_r + wh;
|
||||
int * tbl_b = tbl_g + wh;
|
||||
|
||||
int * vmin = tbl_b + wh;
|
||||
int * vmax = vmin + large_edge;
|
||||
int * tbl_rgb = table_rgb.get();
|
||||
int * const vmin = tbl_rgb + 3 * wh;
|
||||
|
||||
int * const vmax = vmin + large_edge;
|
||||
int * dv = vmax + large_edge;
|
||||
const int end_div = div - 1;
|
||||
for(int i = 0, *dv_block = dv; i < 256; ++i)
|
||||
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
for(int u = 0; u < end_div; u += 2)
|
||||
dv[0] = i;
|
||||
for (int u = 1; u < div; u += 2)
|
||||
{
|
||||
dv_block[u] = i;
|
||||
dv_block[u + 1] = i;
|
||||
dv[u] = i;
|
||||
dv[u + 1] = i;
|
||||
}
|
||||
dv_block[div - 1] = i;
|
||||
dv_block += div;
|
||||
dv += div;
|
||||
}
|
||||
|
||||
dv = vmax + large_edge;
|
||||
|
||||
auto linepix = pixbuf.raw_ptr(area.y) + area.x;
|
||||
|
||||
int yi = 0;
|
||||
for(int y = 0; y < h; ++y)
|
||||
for(int x = 0; x < static_cast<int>(area.width); ++x)
|
||||
{
|
||||
vmin[x] = std::min(x + radius_plus_one, wm);
|
||||
vmax[x] = std::max(x - radius, 0);
|
||||
}
|
||||
|
||||
for(int y = 0; y < static_cast<int>(area.height); ++y)
|
||||
{
|
||||
int sum_r = 0, sum_g = 0, sum_b = 0;
|
||||
if(radius <= wm)
|
||||
{
|
||||
for(int i = - radius; i <= radius; ++i)
|
||||
auto px = linepix;
|
||||
|
||||
sum_r = int(px->element.red) * radius_plus_one;
|
||||
sum_g = int(px->element.blue) * radius_plus_one;
|
||||
sum_b = int(px->element.blue) * radius_plus_one;
|
||||
|
||||
auto radius_px_end = px + radius_plus_one;
|
||||
for (++px; px < radius_px_end; ++px)
|
||||
{
|
||||
auto px = linepix[(i > 0 ? i : 0)];
|
||||
sum_r += px.element.red;
|
||||
sum_g += px.element.green;
|
||||
sum_b += px.element.blue;
|
||||
sum_r += px->element.red;
|
||||
sum_g += px->element.green;
|
||||
sum_b += px->element.blue;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -612,75 +622,62 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
for(int x = 0; x < w; ++x)
|
||||
for(int x = 0; x < static_cast<int>(area.width); ++x)
|
||||
{
|
||||
tbl_r[yi] = dv[sum_r];
|
||||
tbl_g[yi] = dv[sum_g];
|
||||
tbl_b[yi] = dv[sum_b];
|
||||
tbl_rgb[0] = dv[sum_r];
|
||||
tbl_rgb[1] = dv[sum_g];
|
||||
tbl_rgb[2] = dv[sum_b];
|
||||
tbl_rgb += 3;
|
||||
|
||||
if(0 == y)
|
||||
{
|
||||
vmin[x] = std::min(x + radius + 1, wm);
|
||||
vmax[x] = std::max(x - radius, 0);
|
||||
}
|
||||
|
||||
auto p1 = linepix[vmin[x]];
|
||||
auto p2 = linepix[vmax[x]];
|
||||
auto& p1 = linepix[vmin[x]];
|
||||
auto& p2 = linepix[vmax[x]];
|
||||
|
||||
sum_r += p1.element.red - p2.element.red;
|
||||
sum_g += p1.element.green - p2.element.green;
|
||||
sum_b += p1.element.blue - p2.element.blue;
|
||||
++yi;
|
||||
}
|
||||
linepix = pixbuf.raw_ptr(area.y + y) + area.x;
|
||||
}
|
||||
|
||||
const int yp_init = -radius * w;
|
||||
|
||||
const std::size_t bytes_pl = pixbuf.bytes_per_line();
|
||||
for(int x = 0; x < w; ++x)
|
||||
{
|
||||
int sum_r = 0, sum_g = 0, sum_b = 0;
|
||||
|
||||
int yp = yp_init;
|
||||
for(int i = -radius; i <= radius; ++i)
|
||||
tbl_rgb = table_rgb.get();
|
||||
|
||||
for (int y = 0; y < static_cast<int>(area.height); ++y)
|
||||
{
|
||||
vmin[y] = std::min(y + radius_plus_one, hm) * width_3times;
|
||||
vmax[y] = std::max(y - radius, 0) * width_3times;
|
||||
}
|
||||
|
||||
for(int x = 0; x < static_cast<int>(area.width); ++x)
|
||||
{
|
||||
int sum_r = int(tbl_rgb[0]) * radius_plus_one;
|
||||
int sum_g = int(tbl_rgb[1]) * radius_plus_one;
|
||||
int sum_b = int(tbl_rgb[2]) * radius_plus_one;
|
||||
|
||||
int nextln = width_3times;
|
||||
for (int i = 0; i < safe_radius; ++i)
|
||||
{
|
||||
if(yp < 1)
|
||||
{
|
||||
sum_r += tbl_r[x];
|
||||
sum_g += tbl_g[x];
|
||||
sum_b += tbl_b[x];
|
||||
}
|
||||
else
|
||||
{
|
||||
int yi = yp + x;
|
||||
sum_r += tbl_r[yi];
|
||||
sum_g += tbl_g[yi];
|
||||
sum_b += tbl_b[yi];
|
||||
}
|
||||
yp += w;
|
||||
sum_r += tbl_rgb[nextln];
|
||||
sum_g += tbl_rgb[nextln + 1];
|
||||
sum_b += tbl_rgb[nextln + 2];
|
||||
nextln += width_3times;
|
||||
}
|
||||
|
||||
linepix = pixbuf.raw_ptr(area.y) + x + area.x;
|
||||
|
||||
for(int y = 0; y < h; ++y)
|
||||
for(int y = 0; y < static_cast<int>(area.height); ++y)
|
||||
{
|
||||
linepix->value = 0xFF000000 | (dv[sum_r] << 16) | (dv[sum_g] << 8) | dv[sum_b];
|
||||
if(x == 0)
|
||||
{
|
||||
vmin[y] = std::min(y + radius + 1, hm) * w;
|
||||
vmax[y] = std::max(y - radius, 0) * w;
|
||||
}
|
||||
|
||||
int pt1 = x + vmin[y];
|
||||
int pt2 = x + vmax[y];
|
||||
|
||||
sum_r += tbl_r[pt1] - tbl_r[pt2];
|
||||
sum_g += tbl_g[pt1] - tbl_g[pt2];
|
||||
sum_b += tbl_b[pt1] - tbl_b[pt2];
|
||||
int pt1 = vmin[y];
|
||||
int pt2 = vmax[y];
|
||||
|
||||
sum_r += tbl_rgb[pt1] - tbl_rgb[pt2];
|
||||
sum_g += tbl_rgb[pt1 + 1] - tbl_rgb[pt2 + 1];
|
||||
sum_b += tbl_rgb[pt1 + 2] - tbl_rgb[pt2 + 2];
|
||||
linepix = pixel_at(linepix, bytes_pl);
|
||||
}
|
||||
tbl_rgb += 3;
|
||||
}
|
||||
}
|
||||
};//end class superfast_blur
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user