Fork me on GitHub
开源库CImg 数据格式存储

开源库CImg 数据格式存储

 

CImg为开源图像处理库,仅有一个头文件CImg.h便包含了对图像的所有处理函数,函数操作简单,编程方便,但国内使用者较少

其homepage:http://cimg.sourceforge.net/

通常windows的CImage 或nokia的QT中的Qimage 对图片的存储均为按照每个像素的RGB循序:

例如:像素点(0,0)(0,1)(0,2) 在内存中存储顺序为R1 G1 B1 R2 G2 B2 R3 G3 B3

但是CImg中的存储却不同像素点(0,0)(0,1)(0,2) 在内存中存储顺序为R1 R2 R3 G1 G2 G3 B1 B2 B3

 

 

 

 

复制代码
#include <iostream>
using namespace std;
#include "CImg.h"
using namespace cimg_library; 
#include <iomanip>
int main()
{
    CImg<unsigned char> image("car.bmp"); 
    int rgb_leng = image.width()*image.height();    
    unsigned char *ptr = image.data(0,0);
    unsigned char *ptest = new unsigned char[rgb_leng*3];
    int width = image.width();
    int height = image.height();
    for(int i=0;i<height;i++)
    {
        for(int j=0;j<width;j++)
        {
            ptest[i*width+j]=ptr[i*width+j];
            ptest[i*width+j+rgb_leng]=ptr[i*width+j+rgb_leng];
            ptest[i*width+j+rgb_leng*2]=ptr[i*width+j+rgb_leng*2];
        }        
    }
    
    
    CImg<unsigned char> imtest(ptest,width,height,1,3);
    cout<<"size of iamge"<<image.size()<<endl;
    cout<<"size of copy iamge"<<imtest.size()<<endl;
    imtest.save("test.bmp");
    image.display("test");    
    return 0;
}
复制代码

 

由于CImg库刚刚看了一天,难免会误解其中含义,以上仅代表个人观点。

 

 
 

总结C++中取成员函数地址的几种方法

 

  这里, 我整理了4种C++中取成员函数地址的方法, 第1,2,4种整理于网上的方法, 第3种cdecl_cast是我自己想到的.
  其中, 第4种(汇编)的方法不能在VC6上编译通过. 推荐使用第1,2种方法(pointer_cast 和 union_cast).
  至于:为什么要取成员函数的地址? 因为可以通过一定的手段 让成员函数作为回调函数, 而不再使用全局的静态函数.
  天气热,话不多说, 使用方法见最后.

方法1: pointer_cast - 通过静态转换

复制代码
template<typename dst_type,typename src_type>
dst_type pointer_cast(src_type src)
{
    return *static_cast<dst_type*>(static_cast<void*>(&src));
}
复制代码

其实, 我并不明白这个方法为什么成功了, 而且要使用两个static_cast, 一个不行. 而且函数里面使用的&src, 
但我传入参数的时候还需要以&ClassName::MemFunc的形式, 不然就是错误的, 为什么?

方法2: union_cast - 通过联合体的共享储存机制

复制代码
template<typename dst_type,typename src_type>
dst_type union_cast(src_type src)
{
    union{
        src_type s;
        dst_type d;
    }u;
    u.s = src;
    return u.d;
}
复制代码

这种方法是最常规, 也是最好理解的一种方法了, 巧妙地利用了联合体的优点. 当然, 模板的使用恰到好处. 同时,传入参数时注意数据类型大小一致.

方法3: cdecl_cast - 通过C语言的可变参数不检测参数类型

复制代码
__declspec(naked) void* __cdecl cdecl_cast(...)
{
    __asm{
        mov eax,dword ptr[esp+4]
        ret
    }
}
复制代码

  注:在Windows上函数返回值通过eax返回, 所以只需要这么两条汇编语句就行了. 只用于32位平台, 若用于64位, 需要修改一下寄存器.
虽然使用了三个点形式的参数, 但是参数只需传入一个.

方法4: asm_cast - 通过汇编的offset语句取成员函数偏移得到地址

复制代码
#define asm_cast(var,addr)  \
{                           \
    __asm{                  \
        mov var,offset addr \
    }                       \
}    
复制代码

注:这个方法也比较巧妙, 不过貌似在VC6上编译不过. VS2012没问题.


使用方法及测试代码:

复制代码
#include <iostream>

using namespace std;

class A
{
public:
    void fn(){}
};


int main(void)
{
    void* p1 = pointer_cast<void*>(&A::fn);
    void* p2 = union_cast<void*>(&A::fn);
    void* p3 = cdecl_cast(&A::fn);
    void* p4 = 0; asm_cast(p4,A::fn);
    
    cout<<p1<<endl<<p2<<endl<<p3<<endl<<p4<<endl;
    
    return 0;
}
复制代码

 


女孩不哭 @ 2013-08-17 10:47:34 @ http://www.cnblogs.com/nbsofer


作者:女孩不哭(点我发送QQ消息) 
出处:http://www.cnblogs.com/nbsofer/ 
说明:您的支持是我最大的动力, 欢迎发表对本文的看法! 

 
分类: C++
 
posted on 2013-08-19 13:15  HackerVirus  阅读(974)  评论(0编辑  收藏  举报