Nana开发: 图像处理算法接口的介绍
2012-05-16 17:24
369 查看
在0.2.2版本中,Nana C++ Library提供了一个灵活配置图像处理算法的机制。对于一个抽象的算法,可能会有多种实现。例如,Nana C++ Library提供了两个图像缩放算法,他们分别是双线性插值算法(bilinear interoplation)和最邻近插值(proximal interoplation),用户可以根据不同的需求来切换算法。
参考例子:
http://stdex.sourceforge.net/help/paint/image_process_selector.htm
由于跨平台的特性,Nana并没有使用特定的平台指令来实现内部提供的算法,这些代码应该很好地工作在不同的编译器环境中。在需要考虑算法效率的特定情况下,尽管 Nana C++ Library没有提供使用平台指令的算法,但是程序员可以自己实现这样的算法,并配置以供Nana库调用。
现在我们使用MMX指令实现一个图像混合算法。
实现一个可以被Nana库使用的图像混合算法,我们必须使用class blend_interface, 这个类定义在Nana头文件<nana/paint/image_process_interface.hpp>中。
class blend_interface
{
public:
virtual ~blend_interface() = 0;
virtual
void process(nana::paint::drawable_type dw_dst,
const nana::rectangle& r_dst,
const paint::pixel_buffer& s_pixbuf, const nana::point& s_pos,
double fade_rate)
const = 0;
};
dw_dst: 目标对象.
r_dst: 目标混合区域.
s_pixbuf: 源像素缓存.
s_pos: 源坐标.
fade_rate: 混合比率.
目标混合区域总是有效的,由Nana库在计算并验证之后传入到该函数中。因此我们在使用这些数据时不必检测它们是否有效。
该算法的语义:
dw_dst = dw_dst * fade_rate + s_pixbuf *(1 - fade_rate)
现在开始!
#include
<nana/paint/image_process_interface.hpp>
class blend_mmx
: public nana::paint::image_process::blend_interface
{
virtual
void process(nana::paint::drawable_type dw_dst,
const nana::rectangle& r_dst,
const paint::pixel_buffer& s_pixbuf, const nana::point& s_pos,
double fade_rate)
const
{
nana::paint::pixel_buffer d_pixbuf(dw_dst, r_dst.y, r_dst.height);
nana::pixel_rgb_t * d_rgb = d_pixbuf.raw_ptr();
if(d_rgb)
{
d_rgb += r_dst.x;
nana::pixel_rgb_t * s_rgb = s_pixbuf.raw_ptr(s_pos.y) + s_pos.x;
const unsigned rest = r_dst.width &
0x3;
const unsigned length_align4 = r_dst.width - rest;
unsigned d_step_width = d_pixbuf.size().width;
unsigned s_step_width = s_pixbuf.size().width;
unsigned i_d_rate = static_cast<unsigned>(fade_rate * 255);
unsigned i_s_rate = 255 - i_d_rate;
__asm
{
pxor xmm7, xmm7
movd xmm0, i_d_rate
punpcklwd xmm0, xmm0
punpcklwd xmm0, xmm0
punpcklwd xmm0, xmm0
movd xmm1, i_s_rate
punpcklwd xmm1, xmm1
punpcklwd xmm1, xmm1
punpcklwd xmm1, xmm1
}
for(unsigned line = 0; line < r_dst.height; ++line)
{
__asm
{
push eax
push ebx
push edx
mov edx, dword ptr[length_align4]
mov eax, dword ptr[d_rgb]
mov ebx, dword ptr[s_rgb]
lea edx, [edx * 4 + eax]
blend_mmx_3_for_each_pixel_in_line_loop_start:
cmp eax, edx
je blend_mmx_3_for_each_pixel_in_line_loop_end
//eax[0], eax[1]
movq xmm2, qword ptr[eax]
movq xmm3, qword ptr[ebx]
punpcklbw xmm2, xmm7
punpcklbw xmm3, xmm7
pmullw xmm2, xmm0
pmullw xmm3, xmm1
paddw xmm2, xmm3
psrlw xmm2, 8
packuswb xmm2, xmm7
movq qword ptr[eax], xmm2
//eax[2], eax[3]
movq xmm2, qword ptr[eax + 8]
movq xmm3, qword ptr[ebx + 8]
punpcklbw xmm2, xmm7
punpcklbw xmm3, xmm7
pmullw xmm2, xmm0
pmullw xmm3, xmm1
paddw xmm2, xmm3
psrlw xmm2, 8
packuswb xmm2, xmm7
movq qword ptr[eax + 8], xmm2
add eax, 16
add ebx, 16
jmp blend_mmx_3_for_each_pixel_in_line_loop_start
blend_mmx_3_for_each_pixel_in_line_loop_end:
push ecx
mov ecx, dword ptr[rest]
cmp ecx, 0
je blend_mmx_3_for_each_rest_pixel_loop_end
blend_mmx_3_for_each_rest_pixel_loop_start:
movd xmm2, dword ptr[eax]
movd xmm3, dword ptr[ebx]
punpcklbw xmm2, xmm7
punpcklbw xmm3, xmm7
pmullw xmm2, xmm0
pmullw xmm3, xmm1
paddw xmm2, xmm3
psrlw xmm2, 8
packuswb xmm2, xmm7
movd dword ptr[eax], xmm2
add eax, 4
add ebx, 4
loop blend_mmx_3_for_each_rest_pixel_loop_start
blend_mmx_3_for_each_rest_pixel_loop_end:
pop ecx
pop edx
pop ebx
pop eax
}
d_rgb += d_step_width;
s_rgb += s_step_width;
}
__asm emms
nana::rectangle r = r_dst;
r.y = 0;
d_pixbuf.paste(r, dw_dst, r_dst.x, r_dst.y);
}
}
};
应用算法
#include
<nana/gui/wvl.hpp>
#include
<nana/gui/timer.hpp>
#include
<nana/paint/image_process_selector.hpp>
//包含我们先前定义的类blend_mmx的实现
class blend_form
: public nana::gui::form
{
public:
blend_form()
:form(nana::gui::API::make_center(450, 300))
,fade_rate_(0.1), delta_(0.1)
{
this->show();
nana::paint::image img(STR("image01.bmp"));
s_graph_.make(img.size().width, img.size().height);
img.paste(s_graph_, 0, 0);
d_image_.open(STR("image02.bmp"));
d_graph_.make(d_image_.size().width, d_image_.size().height);
timer_.make_tick(nana::make_fun(*this, &tsform::_m_blend));
timer_.interval(10);
//安装blend_mmx并使用它
nana::paint::image_process::selector sl;
sl.add_blend<blend_mmx>("blend_mmx");
//为该算法命名
sl.blend("blend_mmx");
//通过名字来应用它
}
private:
void _m_blend()
{
fade_rate_ += delta_;
if(fade_rate_ > 1)
{
fade_rate_ = 1;
delta_ = -0.01;
}
else
if(fade_rate_ < 0)
{
fade_rate_ = 0;
delta_ = 0.01;
}
d_image_.paste(d_graph_, 0, 0);
//混合操作, 内部将使用blend_mmx
s_graph_.blend(d_graph_, 0, 0, fade_rate_);
nana::gui::drawing drawing(*this);
drawing.clear();
drawing.bitblt(0, 0, 450, 300, d_graph_, 0, 0);
drawing.update();
}
private:
double fade_rate_;
double delta_;
timer timer_;
nana::paint::graphics s_graph_, d_graph_;
nana::paint::image d_image_;
};
本文展示了一个使用外部实现的算法来替换Nana库内部算法以满足各种需求的方法。
参考例子:
http://stdex.sourceforge.net/help/paint/image_process_selector.htm
由于跨平台的特性,Nana并没有使用特定的平台指令来实现内部提供的算法,这些代码应该很好地工作在不同的编译器环境中。在需要考虑算法效率的特定情况下,尽管 Nana C++ Library没有提供使用平台指令的算法,但是程序员可以自己实现这样的算法,并配置以供Nana库调用。
现在我们使用MMX指令实现一个图像混合算法。
实现一个可以被Nana库使用的图像混合算法,我们必须使用class blend_interface, 这个类定义在Nana头文件<nana/paint/image_process_interface.hpp>中。
class blend_interface
{
public:
virtual ~blend_interface() = 0;
virtual
void process(nana::paint::drawable_type dw_dst,
const nana::rectangle& r_dst,
const paint::pixel_buffer& s_pixbuf, const nana::point& s_pos,
double fade_rate)
const = 0;
};
dw_dst: 目标对象.
r_dst: 目标混合区域.
s_pixbuf: 源像素缓存.
s_pos: 源坐标.
fade_rate: 混合比率.
目标混合区域总是有效的,由Nana库在计算并验证之后传入到该函数中。因此我们在使用这些数据时不必检测它们是否有效。
该算法的语义:
dw_dst = dw_dst * fade_rate + s_pixbuf *(1 - fade_rate)
现在开始!
#include
<nana/paint/image_process_interface.hpp>
class blend_mmx
: public nana::paint::image_process::blend_interface
{
virtual
void process(nana::paint::drawable_type dw_dst,
const nana::rectangle& r_dst,
const paint::pixel_buffer& s_pixbuf, const nana::point& s_pos,
double fade_rate)
const
{
nana::paint::pixel_buffer d_pixbuf(dw_dst, r_dst.y, r_dst.height);
nana::pixel_rgb_t * d_rgb = d_pixbuf.raw_ptr();
if(d_rgb)
{
d_rgb += r_dst.x;
nana::pixel_rgb_t * s_rgb = s_pixbuf.raw_ptr(s_pos.y) + s_pos.x;
const unsigned rest = r_dst.width &
0x3;
const unsigned length_align4 = r_dst.width - rest;
unsigned d_step_width = d_pixbuf.size().width;
unsigned s_step_width = s_pixbuf.size().width;
unsigned i_d_rate = static_cast<unsigned>(fade_rate * 255);
unsigned i_s_rate = 255 - i_d_rate;
__asm
{
pxor xmm7, xmm7
movd xmm0, i_d_rate
punpcklwd xmm0, xmm0
punpcklwd xmm0, xmm0
punpcklwd xmm0, xmm0
movd xmm1, i_s_rate
punpcklwd xmm1, xmm1
punpcklwd xmm1, xmm1
punpcklwd xmm1, xmm1
}
for(unsigned line = 0; line < r_dst.height; ++line)
{
__asm
{
push eax
push ebx
push edx
mov edx, dword ptr[length_align4]
mov eax, dword ptr[d_rgb]
mov ebx, dword ptr[s_rgb]
lea edx, [edx * 4 + eax]
blend_mmx_3_for_each_pixel_in_line_loop_start:
cmp eax, edx
je blend_mmx_3_for_each_pixel_in_line_loop_end
//eax[0], eax[1]
movq xmm2, qword ptr[eax]
movq xmm3, qword ptr[ebx]
punpcklbw xmm2, xmm7
punpcklbw xmm3, xmm7
pmullw xmm2, xmm0
pmullw xmm3, xmm1
paddw xmm2, xmm3
psrlw xmm2, 8
packuswb xmm2, xmm7
movq qword ptr[eax], xmm2
//eax[2], eax[3]
movq xmm2, qword ptr[eax + 8]
movq xmm3, qword ptr[ebx + 8]
punpcklbw xmm2, xmm7
punpcklbw xmm3, xmm7
pmullw xmm2, xmm0
pmullw xmm3, xmm1
paddw xmm2, xmm3
psrlw xmm2, 8
packuswb xmm2, xmm7
movq qword ptr[eax + 8], xmm2
add eax, 16
add ebx, 16
jmp blend_mmx_3_for_each_pixel_in_line_loop_start
blend_mmx_3_for_each_pixel_in_line_loop_end:
push ecx
mov ecx, dword ptr[rest]
cmp ecx, 0
je blend_mmx_3_for_each_rest_pixel_loop_end
blend_mmx_3_for_each_rest_pixel_loop_start:
movd xmm2, dword ptr[eax]
movd xmm3, dword ptr[ebx]
punpcklbw xmm2, xmm7
punpcklbw xmm3, xmm7
pmullw xmm2, xmm0
pmullw xmm3, xmm1
paddw xmm2, xmm3
psrlw xmm2, 8
packuswb xmm2, xmm7
movd dword ptr[eax], xmm2
add eax, 4
add ebx, 4
loop blend_mmx_3_for_each_rest_pixel_loop_start
blend_mmx_3_for_each_rest_pixel_loop_end:
pop ecx
pop edx
pop ebx
pop eax
}
d_rgb += d_step_width;
s_rgb += s_step_width;
}
__asm emms
nana::rectangle r = r_dst;
r.y = 0;
d_pixbuf.paste(r, dw_dst, r_dst.x, r_dst.y);
}
}
};
应用算法
#include
<nana/gui/wvl.hpp>
#include
<nana/gui/timer.hpp>
#include
<nana/paint/image_process_selector.hpp>
//包含我们先前定义的类blend_mmx的实现
class blend_form
: public nana::gui::form
{
public:
blend_form()
:form(nana::gui::API::make_center(450, 300))
,fade_rate_(0.1), delta_(0.1)
{
this->show();
nana::paint::image img(STR("image01.bmp"));
s_graph_.make(img.size().width, img.size().height);
img.paste(s_graph_, 0, 0);
d_image_.open(STR("image02.bmp"));
d_graph_.make(d_image_.size().width, d_image_.size().height);
timer_.make_tick(nana::make_fun(*this, &tsform::_m_blend));
timer_.interval(10);
//安装blend_mmx并使用它
nana::paint::image_process::selector sl;
sl.add_blend<blend_mmx>("blend_mmx");
//为该算法命名
sl.blend("blend_mmx");
//通过名字来应用它
}
private:
void _m_blend()
{
fade_rate_ += delta_;
if(fade_rate_ > 1)
{
fade_rate_ = 1;
delta_ = -0.01;
}
else
if(fade_rate_ < 0)
{
fade_rate_ = 0;
delta_ = 0.01;
}
d_image_.paste(d_graph_, 0, 0);
//混合操作, 内部将使用blend_mmx
s_graph_.blend(d_graph_, 0, 0, fade_rate_);
nana::gui::drawing drawing(*this);
drawing.clear();
drawing.bitblt(0, 0, 450, 300, d_graph_, 0, 0);
drawing.update();
}
private:
double fade_rate_;
double delta_;
timer timer_;
nana::paint::graphics s_graph_, d_graph_;
nana::paint::image d_image_;
};
本文展示了一个使用外部实现的算法来替换Nana库内部算法以满足各种需求的方法。
相关文章推荐
- Silverlight C# 游戏开发:资源的处理,图像算法(一)
- 记录我第一次在Android开发图像处理算法的经历
- 【VS开发】【图像处理】自动白平衡(AWB)算法---色温曲线
- Silverlight C# 游戏开发:资源的处理,图像算法(一)
- Silverlight C# 游戏开发:资源的处理,图像算法(二)
- 牛人博客链接--高级算法、智能视频、嵌入式软件、DSP应用开发,algorithem,c++,c,视频处理,图像处理
- 嵌入式开发之davinci--- 8148/8168/8127 中的图像处理算法优化库vlib
- 记录我第一次在Android开发图像处理算法的经历
- iOS开发图片美白处理,图像处理,,磨皮,马赛克基于UIKit下自写算法
- Silverlight C# 游戏开发:资源的处理,图像算法(二)
- 【图像处理】图像算法开发过程
- 【开发日记】C#调用C++图像处理算法(opencv)
- (二)无人机数据处理算法介绍——图像拼接
- 图像处理--图像分割算法介绍
- 【VS开发】【图像处理】相机中白平衡的算法模拟实现
- 图像处理之均值滤波介绍及C算法实现
- 图像处理之3d算法----2d转3d算法介绍
- 各种与视频编解码以及视频图像处理的应用相关的新技术,新方法,各种软件开发相关的算法,思想。
- 【VS开发】【图像处理】基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
- 图像处理之均值滤波介绍及C算法实现