您的位置:首页 > 其它

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库内部算法以满足各种需求的方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: