Cimg代码初探
Cimg代码初探
程序设计最为激动人心的地方,在于丰富的并且容易被查阅到资料。比如对于图像处理,固然有Opencv等较为丰富、被广泛知晓的类库;也有其他很多具有一定特色的类库。在这段时间里面,我对CImg图像处理库进行了初步研究,并且做小结如下:
一、类库总体情况
总体感觉,CImg是一个“小家碧玉”类型的类库。这里的“小”,不仅体现在代码结构上、体现在代码数量上,我觉得很大程度上也体现在代码内容上:比如代码的缩进都是采用最节省空间的方法,
大量采用了连续处理的方法,其实现的功能也是比较有“趣味”,但不是解决实际问题的方法
,
再比如,已经将许多图片程序以“硬编码”的方式编入了类库,这些都体现了程序设置者的“偏执”,或者叫做“个性”,但是并不能将CImg变成一个更有用的类库。
但是反过来说,CImg实现的许多效果,的确是匠心独运,简直可以说是"so COOL"
炫动的菜单背景
非常适合做帮助的flag
光怪陆离的效果
游戏
3D效果
鱼眼
可视化的Gamma矫正
足球轨迹。
二、研究思路和计划
1)对前面提出来的几个部分进行分别研究,并且分割复用其中部分为自己所用,关键是理解思路;
2
)将类库中全部的文件和其应该发挥的作用搞明白;
3
)登录官网,查看理解这个类库的发展、讨论和现状;
4
)反思在图像处理领域应该如何做下去。
[2016年4月7日15:34:25]
首先理解CImg类库的类库特点和代码结构;而后对背景动画进行分析。所有的结果都需要能够独立出来并且方便被复用。
能够直接绘制出"
plasma
"纹理的界面
动态的圆的界面主要还是来自于随机数
#
include
"CImg_demo.h"
// Include CImg library header.
# include "CImg.h"
using namespace cimg_library;
#undef min
#undef max
void main()
{
cimg : :info();
//各类RGB定值
const unsigned char
white[] = { 255, 255, 255 }, black[] = { 0, 0, 0 }, red[] = { 120, 50, 80 },
yellow[] = { 200, 155, 0 }, green[] = { 30, 200, 70 }, purple[] = { 175, 32, 186 },
blue[] = { 55, 140, 185 }, grey[] = { 127, 127, 127 };
float
rx = 0, ry = 0, t = 0, gamma = 0, vgamma = 0, T = 0. 9f,
nrx = ( float)( 2 *cimg : :crand()),
nry = ( float)( 2 *cimg : :crand());
int y0 = 2 * 13;
//图像显示
CImg < unsigned char > back( 1, 2, 1, 3, 10), fore, text, img; //back fore text img都是界面背景
back.fillC( 0, 1, 0, 10, 10, 235).resize( 640, 480, 1, 3, 3).get_shared_channel( 2).noise( 10, 1).draw_plasma(); //绿宝石界面
fore.assign(back.width(), 50, 1, 1, 0).draw_text( 20,y0 - 5, "** CImg %u.%u.%u Samples **",grey, 0, 1, 24,
cimg_version / 100,(cimg_version / 10) % 10,cimg_version % 10);
(fore +=fore.get_dilate( 3).dilate( 3)).resize( - 100, - 100, 1, 3);
cimg_forXY(fore,x,y)
if (fore(x,y) == 127) fore(x,y, 0) = fore(x,y, 1) = fore(x,y, 2) = 1;
else if (fore(x,y)) {
const float val = cimg : :min( 255.0f, 7.0f *(y - 3));
fore(x,y, 0) = ( unsigned char)(val / 1. 5f);
fore(x,y, 1) = ( unsigned char)val;
fore(x,y, 2) = ( unsigned char)(val / 1. 1f);
}
fore.resize(back, 0).draw_image( 20,y0 + 2 * 13,text |=text.get_dilate( 3) >> 4);
//创建显示的窗体
CImgDisplay disp(back, "CImg Library Samples", 0, false, true);
disp.move((disp.screen_width() -disp.window_width()) / 2,(disp.screen_height() -disp.window_height()) / 2);
img = back; back *= 0. 15f;
for (y0 += 2 * 13; !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC(); ) {
while ( !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC()) {
img *= 0. 85f; img +=back;
for ( int i = 0; i < 60; ++i) {
const float
mx = ( float)(img.width() / 2 +(img.width() / 2 - 30) *(( 1 -gamma) *std : :cos( 3 *t +rx *i * 18.0f *cimg : :PI / 180) +
gamma *std : :cos( 3 *t +nrx *i * 18.0f *cimg : :PI / 180))),
my = ( float)(img.height() / 2 +(img.height() / 2 - 30) *(( 1 -gamma) *std : :sin( 4 *t +ry *i * 18.0f *cimg : :PI / 180) +
gamma *std : :sin( 4 *t +nry *i * 18.0f *cimg : :PI / 180))),
mz = ( float)( 1. 3f + 1. 2f *(( 1 -gamma) *std : :sin( 2 *t +(rx +ry) *i * 20 *cimg : :PI / 180) +
gamma *std : :sin( 2 *t +(nrx +nry) *i * 20 *cimg : :PI / 180)));
const int j = i % 5;
//具体画圆
img.draw_circle(( int)mx,( int)my,( int)( 10 *mz),j != 0 ?(j != 1 ?(j != 2 ?(j != 3 ?green :red) :yellow) :purple) :blue, 0. 2f).
draw_circle(( int)(mx + 4 *mz),( int)(my - 4),( int)( 3 *mz),white, 0. 1f).
draw_circle(( int)mx,( int)my,( int)( 10 *mz),black, 0. 2f, ~0U);
}
const unsigned char *ptrs = fore.data();
cimg_for(img,ptrd, unsigned char)
{
const unsigned char val = *(ptrs ++);
if (val) *ptrd = val;
}
//显示菜单条
int y = disp.mouse_y();
if (y > =y0 && y <y0 + 27 * 13) {
y = (y / 13) * 13 + 7;
for ( int yy = y - 7; yy < =y + 6; ++yy) img.draw_rectangle( 0,yy, 0, 1,img.width() - 1,yy, 0, 1,( unsigned char)( 130 - 15 *cimg : :abs(yy -y)));
img.draw_triangle( 2,y - 4, 2,y + 4, 8,y,yellow).draw_triangle(img.width() - 2,y - 4,img.width() - 2,y + 4,img.width() - 8,y,yellow);
}
gamma +=vgamma;
if (gamma > 1)
{
gamma = vgamma = 0;
rx = nrx;
ry = nry;
nrx =( float)( 2 *cimg : :crand());
nry =( float)( 2 *cimg : :crand());
}
t += 0. 006f; T += 0. 005f; if (T > 1) { T -=( float)( 1 +cimg : :crand()); vgamma = 0. 03f; }
disp.resize(disp, false).display(img).wait( 25);
}
}
getchar();
}
// Include CImg library header.
# include "CImg.h"
using namespace cimg_library;
#undef min
#undef max
void main()
{
cimg : :info();
//各类RGB定值
const unsigned char
white[] = { 255, 255, 255 }, black[] = { 0, 0, 0 }, red[] = { 120, 50, 80 },
yellow[] = { 200, 155, 0 }, green[] = { 30, 200, 70 }, purple[] = { 175, 32, 186 },
blue[] = { 55, 140, 185 }, grey[] = { 127, 127, 127 };
float
rx = 0, ry = 0, t = 0, gamma = 0, vgamma = 0, T = 0. 9f,
nrx = ( float)( 2 *cimg : :crand()),
nry = ( float)( 2 *cimg : :crand());
int y0 = 2 * 13;
//图像显示
CImg < unsigned char > back( 1, 2, 1, 3, 10), fore, text, img; //back fore text img都是界面背景
back.fillC( 0, 1, 0, 10, 10, 235).resize( 640, 480, 1, 3, 3).get_shared_channel( 2).noise( 10, 1).draw_plasma(); //绿宝石界面
fore.assign(back.width(), 50, 1, 1, 0).draw_text( 20,y0 - 5, "** CImg %u.%u.%u Samples **",grey, 0, 1, 24,
cimg_version / 100,(cimg_version / 10) % 10,cimg_version % 10);
(fore +=fore.get_dilate( 3).dilate( 3)).resize( - 100, - 100, 1, 3);
cimg_forXY(fore,x,y)
if (fore(x,y) == 127) fore(x,y, 0) = fore(x,y, 1) = fore(x,y, 2) = 1;
else if (fore(x,y)) {
const float val = cimg : :min( 255.0f, 7.0f *(y - 3));
fore(x,y, 0) = ( unsigned char)(val / 1. 5f);
fore(x,y, 1) = ( unsigned char)val;
fore(x,y, 2) = ( unsigned char)(val / 1. 1f);
}
fore.resize(back, 0).draw_image( 20,y0 + 2 * 13,text |=text.get_dilate( 3) >> 4);
//创建显示的窗体
CImgDisplay disp(back, "CImg Library Samples", 0, false, true);
disp.move((disp.screen_width() -disp.window_width()) / 2,(disp.screen_height() -disp.window_height()) / 2);
img = back; back *= 0. 15f;
for (y0 += 2 * 13; !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC(); ) {
while ( !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC()) {
img *= 0. 85f; img +=back;
for ( int i = 0; i < 60; ++i) {
const float
mx = ( float)(img.width() / 2 +(img.width() / 2 - 30) *(( 1 -gamma) *std : :cos( 3 *t +rx *i * 18.0f *cimg : :PI / 180) +
gamma *std : :cos( 3 *t +nrx *i * 18.0f *cimg : :PI / 180))),
my = ( float)(img.height() / 2 +(img.height() / 2 - 30) *(( 1 -gamma) *std : :sin( 4 *t +ry *i * 18.0f *cimg : :PI / 180) +
gamma *std : :sin( 4 *t +nry *i * 18.0f *cimg : :PI / 180))),
mz = ( float)( 1. 3f + 1. 2f *(( 1 -gamma) *std : :sin( 2 *t +(rx +ry) *i * 20 *cimg : :PI / 180) +
gamma *std : :sin( 2 *t +(nrx +nry) *i * 20 *cimg : :PI / 180)));
const int j = i % 5;
//具体画圆
img.draw_circle(( int)mx,( int)my,( int)( 10 *mz),j != 0 ?(j != 1 ?(j != 2 ?(j != 3 ?green :red) :yellow) :purple) :blue, 0. 2f).
draw_circle(( int)(mx + 4 *mz),( int)(my - 4),( int)( 3 *mz),white, 0. 1f).
draw_circle(( int)mx,( int)my,( int)( 10 *mz),black, 0. 2f, ~0U);
}
const unsigned char *ptrs = fore.data();
cimg_for(img,ptrd, unsigned char)
{
const unsigned char val = *(ptrs ++);
if (val) *ptrd = val;
}
//显示菜单条
int y = disp.mouse_y();
if (y > =y0 && y <y0 + 27 * 13) {
y = (y / 13) * 13 + 7;
for ( int yy = y - 7; yy < =y + 6; ++yy) img.draw_rectangle( 0,yy, 0, 1,img.width() - 1,yy, 0, 1,( unsigned char)( 130 - 15 *cimg : :abs(yy -y)));
img.draw_triangle( 2,y - 4, 2,y + 4, 8,y,yellow).draw_triangle(img.width() - 2,y - 4,img.width() - 2,y + 4,img.width() - 8,y,yellow);
}
gamma +=vgamma;
if (gamma > 1)
{
gamma = vgamma = 0;
rx = nrx;
ry = nry;
nrx =( float)( 2 *cimg : :crand());
nry =( float)( 2 *cimg : :crand());
}
t += 0. 006f; T += 0. 005f; if (T > 1) { T -=( float)( 1 +cimg : :crand()); vgamma = 0. 03f; }
disp.resize(disp, false).display(img).wait( 25);
}
}
getchar();
}
使用opencv进行重写
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!