您的位置:首页 > 其它

Cimage类处理图像像素(数据)的3种方式(转)

2016-11-02 09:53 477 查看
这里只讨论对图像像素的处理,cimage类的具体用法查相关资料
#include <atlimage.h> //VS2010以后不用加这个
……………………
CImage m_Image; //或CImage* m_Image; 下面例子程序我用的CImage m_Image; 只是一个用成员选择符,一个用指针操作,效率上可能有所差异

下面是3种方法:

一、用Cimage类的成员函数进行处理

这里假设你已经加载了图像位图,并与CImage对象m_Image相关联。相关成员函数主要有:

GetPixel 返回像素颜色

SetPixel 设置像素颜色

如:m_Image.SetPixel( i-1, j-1, RGB(rr,gg,bb));

SetPixelRGB 设置像素的红绿蓝

如:m_Image.SetPixelRGB(x,y,avg,avg,avg);

SetColorTable 设置调色板颜色分量(红、绿、蓝)值

GetWidth 宽度(以像素为单位)

GetHeight 高度

1、程序示例

1)一个双线性插值放大程序。

[cpp] view plain copy







if (m_Image.IsNull())

return;

// 创建对话框

DlgInterpolation TranPara;

//显示对话框,提示用户设定量

if (TranPara.DoModal() != IDOK)

return;

int k=TranPara.m_inter;

BeginWaitCursor();

CImage m_Image1;

if (! m_Image1.IsNull())

{

m_Image1.Destroy();

}

m_Image1.Create( m_Image.GetWidth()*k, m_Image.GetHeight()*k, 24,0);

// 四个最临近象素的坐标

int x1, x2;

int y1, y2;

// 四个最临近象素值

unsigned char f1, f2, f3, f4;

// 二个插值中间值

unsigned char f12, f34;

//计算结果

int fr,fb,fg;

double epsilon = 0.001;

COLORREF pixel11,pixel12,pixel21,pixel22;

int nHeight1 = m_Image1.GetHeight();

int nWidth1 = m_Image1.GetWidth();

int nHeight = m_Image.GetHeight();

int nWidth = m_Image.GetWidth();

double m=((double)nWidth1-1)/((double)nWidth-1);

for (int i=0; i<nWidth1; i++)

{

for (int j=0; j<nHeight1; j++)

{

double x=double((double)i/m);

double y=double((double)j/m);

//计算四个最临近象素的坐标,+1向右下方移动

x1 = (int) x;

x2 = x1 + 1;

y1 = (int) y;

y2 = y1 + 1;

if( (x < 0) || (x > nWidth - 1) || (y < 0) || (y > nHeight - 1))

{

//要计算的点不在源图范围内,返回-1

continue;

}

else

{

if (fabs(x - nWidth + 1) <= epsilon )

{

// 要计算的点在图像右边缘上

if (fabs(y -nHeight + 1) <= epsilon)

{

// 要计算的点正好是图像最右下角那一个象素,直接返回该点象素值

pixel11 = m_Image.GetPixel(x1,y1);

f1 = (unsigned char)GetRValue(pixel11);

fr=(int)f1;

f1 = (unsigned char)GetGValue(pixel11);

fg=(int)f1;

f1 = (unsigned char)GetBValue(pixel11);

fb=(int)f1;

}

else

{

// 在图像右边缘上且不是最后一点,直接一次插值即可

pixel11 = m_Image.GetPixel(x1,y1);

pixel12 = m_Image.GetPixel(x1,y2);

f1 = (unsigned char)GetRValue(pixel11);

f3 = (unsigned char)GetRValue(pixel12);

fr= (int) (f1 + (y -y1) * (f3 - f1));

f1 = (unsigned char)GetGValue(pixel11);

f3 = (unsigned char)GetGValue(pixel12);

fg= (int) (f1 + (y -y1) * (f3 - f1));

f1 = (unsigned char)GetBValue(pixel11);

f3 = (unsigned char)GetBValue(pixel12);

fb= (int) (f1 + (y -y1) * (f3 - f1));

}

}

else if (fabs(y - nHeight + 1) <= epsilon)

{

// 要计算的点在图像下边缘上且不是最后一点,直接一次插值即可

pixel11 = m_Image.GetPixel(x1,y1);

pixel21 = m_Image.GetPixel(x2,y1);

f1 = (unsigned char)GetRValue(pixel11);

f2 = (unsigned char)GetRValue(pixel21);

fr=(int) (f1 + (x -x1) * (f2 - f1));

f1 = (unsigned char)GetGValue(pixel11);

f2 = (unsigned char)GetGValue(pixel21);

fg=(int) (f1 + (x -x1) * (f2 - f1));

f1 = (unsigned char)GetBValue(pixel11);

f2 = (unsigned char)GetBValue(pixel21);

fb=(int) (f1 + (x -x1) * (f2 - f1));

}

else

{

pixel11 = m_Image.GetPixel(x1,y1);

pixel12 = m_Image.GetPixel(x1,y2);

pixel21 = m_Image.GetPixel(x2,y1);

pixel22 = m_Image.GetPixel(x2,y2);

// 计算四个最临近象素值

f1 = (unsigned char)GetRValue(pixel11);

f2 = (unsigned char)GetRValue(pixel21);

f3 = (unsigned char)GetRValue(pixel12);

f4 = (unsigned char)GetRValue(pixel22);

f12 = (unsigned char) (f1 + (x - x1) * (f2 - f1));

f34 = (unsigned char) (f3 + (x - x1) * (f4 - f3));

fr= (int) (f12 + (y -y1) * (f34 - f12));

f1 = (unsigned char)GetGValue(pixel11);

f2 = (unsigned char)GetGValue(pixel21);

f3 = (unsigned char)GetGValue(pixel12);

f4 = (unsigned char)GetGValue(pixel22);

f12 = (unsigned char) (f1 + (x - x1) * (f2 - f1));

f34 = (unsigned char) (f3 + (x - x1) * (f4 - f3));

fg= (int) (f12 + (y -y1) * (f34 - f12));

f1 = (unsigned char)GetBValue(pixel11);

f2 = (unsigned char)GetBValue(pixel21);

f3 = (unsigned char)GetBValue(pixel12);

f4 = (unsigned char)GetBValue(pixel22);

f12 = (unsigned char) (f1 + (x - x1) * (f2 - f1));

f34 = (unsigned char) (f3 + (x - x1) * (f4 - f3));

fb= (int) (f12 + (y -y1) * (f34 - f12));

}

}

m_Image1.SetPixel(i,j, RGB(fr,fg,fb));

}

}

m_Image.Destroy();

m_Image.Create( m_Image1.GetWidth(), m_Image1.GetHeight(), 24, 0);

COLORREF pixel;

for (int i=0; i<nWidth1; i++)

{

for (int j=0; j<nHeight1; j++)

{

pixel = m_Image1.GetPixel(i,j);

int y=GetRValue(pixel);

int p=GetGValue(pixel);

int b=GetBValue(pixel);

m_Image.SetPixelRGB(i,j,GetRValue(pixel),GetGValue(pixel),GetBValue(pixel));

}

}

m_Image1.Destroy();

Invalidate();

EndWaitCursor();

2)处理视频帧

[cpp] view plain copy







……

Defog(imageprosses, nimgWidth, nimgheigt);/*我加的一个雾天图像增强的动态库,imageprosses是视频的一帧,输入imageprosses处理,并输出imageprosses*/

int rr = 0, gg = 0, bb = 0;

for (int i = 0; i < nimgWidth; i++)

{

for (int j = 1; j <= nimgheigt; j++)

{

bb=(int)imageprosses[3*i*j];

gg=(int)imageprosses[3*i*j+1];

rr=(int)imageprosses[3*i*j+2];

m_Image.SetPixel(i, j-1, RGB(rr,gg,bb));/*设置一帧图像的像素值用来显示*/

}

}

……

2、比较:非常慢。一个图像数据一般很大的,函数调用、参数传递会更加耗时。

二、直接对内存进行操作

相关成员函数:

GetPitch 行距

GetBPP 每像素位数,用时记得GetBPP()/8

GetBits 返回图像像素数据指针

1、程序示例

[cpp] view plain copy







……

Defog(imageprosses, nimgWidth, nimgheigt);

//调用cimage类

if (m_Image.IsNull())

m_Image.Create( nimgWidth, nimgheigt, 24,0);

//地址访问方式

byte* pRealData;

//首地址

pRealData=(byte*)m_Image.GetBits();

//行距

int pit=m_Image.GetPitch();

for (int i = 0; i <nimgWidth; i++)

{

for (int j = 0; j < nimgheigt; j++)

{

*(pRealData + pit*j+ i*3)=(int)imageprosses[3*(nimgheigt-1-j)*nimgWidth+3*i];

*(pRealData + pit*j +i*3 +1)=(int)imageprosses[3*(nimgheigt-1-j)*nimgWidth+3*i+1];

*(pRealData + pit*j + i*3 +2)=(int)imageprosses[3*(nimgheigt-1-j)*nimgWidth+3*i+2];

}

}

m_Image.Draw(pDC->m_hDC,0,0,nWidth,nheigt);

……

2、比较: 对地址直接操作最快,不需要多余的转换。

三、用数组进行处理

如果处理比较复杂的话,可把所有点颜色全部读到一个二维数组里面,然后对这个数组进行读写和处理。 再把处理后的图像显示出来。最方便的是可以进行一些自己需要的预处理,比如我是这样做的。

首先定义一个相关头文件和源文件处理相关内存操作

//MYIMAGE.h

[cpp] view plain copy







#if !defined(MyIMAGE)

#define MyIMAGE

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

#include "windows.h"

// 灰度图

typedef byte **MYIMAGE;/*二维数组的数组名就是一个指向指针的指针,a的作用相当于**a,而a->[0],相当于a[0][0]*/

//彩色图

typedef struct MYCOLORIMAGESTRUCT

{

MYIMAGE r, g, b;

}MYCOLORIMAGE;

////// 8bit图像操作

// 8bit图像分配

MYIMAGE MyImageAlloc(int height,int width);

// 8bit图像释放

void MyImageFree(MYIMAGE a, int height);

// 8bit图像拷贝

bool MyImageCopy(MYIMAGE dest, MYIMAGE source, int width, int height);

// 8bit图像设置

void MyImageSet(MYIMAGE a, int value, int width, int height);

////// 24bit图像操作

// 24bit图像分配

MYCOLORIMAGE MyColorImageAlloc(int height,int width);

// 24bit图像释放

void MyColorImageFree(MYCOLORIMAGE a, int height);

// 24bit图像拷贝

bool MyColorImageCopy(MYCOLORIMAGE dest, MYCOLORIMAGE source, int width, int height);

// 24bit图像设置

void MyColorImagSet(MYCOLORIMAGE a, int value, int width, int height);

// 彩色图像转灰度图象

bool MyColorToGray(MYIMAGE outGrayImg, MYCOLORIMAGE inColorImg, int width, int Height);

#endif MyIMAGE

//MYIMAGE.cpp

[cpp] view plain copy







#include "StdAfx.h"

#include "MYIMAGE.h"

//灰度图像

/**************my分配内存空间***************/

MYIMAGE MyImageAlloc(int height,int width)

{

MYIMAGE a = (MYIMAGE) new MYIMAGE*[height];//数组指针

int i;

byte* pTemp;

pTemp = new UCHAR[height*width];

for(i = 0; i < height; i++)

{

a[i] = pTemp + width * i;

}

return a;

}

/*********释放内存空间***************/

void MyImageFree(MYIMAGE a, int height)

{

delete[] a[0];

delete a;

}

/*******拷贝************/

bool MyImageCopy(MYIMAGE dest, MYIMAGE source, int width, int height)

{

if(dest == NULL || source == NULL || width <= 0 || height <= 0)

return false;

int i = 0;

for(i = 0; i < height; i++)

{

memcpy(dest[i], source[i], sizeof(UCHAR) * width);

}

return true;

}

/*******赋值*******/

void MyImageSet(MYIMAGE a, int value, int width, int height)

{

int i;

for(i = 0; i < height; i++)

{

memset(a[i], value, sizeof(UCHAR) * width);

}

}

//彩色图像

/**************my彩色图像分配内存空间**********************/

MYCOLORIMAGE MyColorImageAlloc(int height,int width)

{

//MYCOLORIMAGE a = (MYCOLORIMAGE) new char[sizeof(MYIMAGE) * 3];

MYCOLORIMAGE a;

a.r = MyImageAlloc(height,width);

a.g = MyImageAlloc(height,width);

a.b = MyImageAlloc(height,width);

return a;

}

/****************my彩色图像空间内存释放*********************/

void MyColorImageFree(MYCOLORIMAGE a, int height)

{

/*

MyImageFree(a->r, height);

MyImageFree(a->g, height);

MyImageFree(a->b, height);

delete a;

*/

MyImageFree(a.r, height);

MyImageFree(a.g, height);

MyImageFree(a.b, height);

}

/***************my彩色图像拷贝******************/

bool MyColorImageCopy(MYCOLORIMAGE dest, MYCOLORIMAGE source, int width, int height)

{

/*

if(dest == NULL || source == NULL || width <= 0 || height <= 0)

return false;

int i = 0;

for(i = 0; i < height; i++)

{

memcpy(dest->r[i], source->r[i], sizeof(UCHAR) * width);

memcpy(dest->g[i], source->g[i], sizeof(UCHAR) * width);

memcpy(dest->b[i], source->b[i], sizeof(UCHAR) * width);

}

return true;

*/

if(dest.r == NULL || source.r == NULL || width <= 0 || height <= 0)

return false;

for(int i = 0; i < height; i++)

{

memcpy(dest.r[i], source.r[i], sizeof(UCHAR) * width);

memcpy(dest.g[i], source.g[i], sizeof(UCHAR) * width);

memcpy(dest.b[i], source.b[i], sizeof(UCHAR) * width);

}

return true;

}

/**********my彩色图像赋值*****************/

void MyColorImagSet(MYCOLORIMAGE a, int value, int width, int height)

{

int i;

for(i = 0; i < height; i++)

{

memset(a.r[i], value, sizeof(UCHAR) * width);

memset(a.g[i], value, sizeof(UCHAR) * width);

memset(a.b[i], value, sizeof(UCHAR) * width);

}

}

/**********my彩色图转为灰度图**************/

bool MyColorToGray(MYIMAGE outGrayImg, MYCOLORIMAGE inColorImg, int width, int Height)

{

if(outGrayImg == NULL || inColorImg.r == NULL || width <= 0 || Height <= 0)

return false;

for(int j = 0; j < Height; j++)

{

for(int i = 0; i < width; i++)

{

outGrayImg[j][i] = (int)(0.3 * inColorImg.r[j][i] + 0.59 * inColorImg.g[j][i] + 0.11 * inColorImg.b[j][i]);

}

}

return TRUE;

}

然后一些预处理操作,如格式间转换:

//ImageTransform.h

[cpp] view plain copy







#if !defined(ImageTransform)

#define ImageTransform

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

//#include "ximage.h"

#include "MYIMAGE.h"

#include "atlimage.h"

//CImage到MYIMAGE之间的格式转换

//灰度

// CImage转换成MYIMAGE

BOOL CxImageToMYIMAGE(MYIMAGE destpImgbuf, CImage& sourpCxImage, int nImgWidth, int nImgHeight);

// MYIMAGE转换成CImage

BOOL MYIMAGEToCxImage(CImage& destpCxImage, MYIMAGE sourpImgbuf, int nImgWidth, int nImgHeight);

//彩色

// CImage转换成MYCOLORIMAGE

BOOL CxxImageToMYIMAGE(MYCOLORIMAGE destpImgbuf, CImage& sourpCxImage, int nImgWidth, int nImgHeight);

// MYCOLORIMAGE转换成CImage

BOOL MYIMAGEToCxxImage(CImage& destpCxImage, MYCOLORIMAGE sourpImgbuf, int nImgWidth, int nImgHeight);

#endif ImageTransform

//ImageTransform.cpp

[cpp] view plain copy







#include "StdAfx.h"

#include "ImageTransform.h"

//灰度

// CImage转换成MYIMAGE

BOOL CxImageToMYIMAGE(MYIMAGE destpImgbuf, CImage& sourpCxImage, int nImgWidth, int nImgHeight)

{

// 参数检查

if(destpImgbuf == NULL || sourpCxImage == NULL || nImgWidth <= 0 || nImgHeight <= 0)

return FALSE;

int i, j;

COLORREF rgb;

//8位灰度图转存为8位灰度图

if(sourpCxImage.GetBPP()/8 ==1)

{

for(j = 0; j < nImgHeight; j++)

{

for(i = 0; i < nImgWidth; i++)

{

destpImgbuf[j][i] = (byte)sourpCxImage.GetPixel(i, j);

}

}

}

//24位灰度图象转换为8位灰度图

else if(sourpCxImage.GetBPP()/8==3)

{

for(j = 0; j < nImgHeight; j++)

{

for(i = 0; i < nImgWidth; i++)

{

rgb = sourpCxImage.GetPixel(i, j);

destpImgbuf[j][i] = GetRValue(rgb);

}

}

}

return TRUE;

}

// MYIMAGE转换成CImage

BOOL MYIMAGEToCxImage(CImage& destpCxImage, MYIMAGE sourpImgbuf, int nImgWidth, int nImgHeight)

{

// 参数检查

if(destpCxImage == NULL || sourpImgbuf == NULL || nImgWidth <= 0 || nImgHeight <= 0)

return FALSE;

int i, j;

//8位灰度图转换为24位灰度图

for(j = 0; j < nImgHeight; j++)

{

for(i = 0; i < nImgWidth; i++)

{

destpCxImage.SetPixelRGB(i, j, sourpImgbuf[j][i],sourpImgbuf[j][i],sourpImgbuf[j][i]);

}

}

return TRUE;

}

//24位真彩色

//CImage转换成MYCOLORIMAGE

BOOL CxxImageToMYIMAGE(MYCOLORIMAGE destpImgbuf, CImage& sourpCxImage, int nImgWidth, int nImgHeight)

{

// 参数检查

if(destpImgbuf.r == NULL || sourpCxImage == NULL || nImgWidth <= 0 || nImgHeight <= 0)

return FALSE;

int i, j;

COLORREF rgb;

//24位转换为24位存储

for(j = 0; j < nImgHeight; j++)

{

for(i = 0; i < nImgWidth; i++)

{

rgb=sourpCxImage.GetPixel(i, j);

destpImgbuf.r[j][i] = GetRValue(rgb);

destpImgbuf.g[j][i] = GetGValue(rgb) ;

destpImgbuf.b[j][i] = GetBValue(rgb) ;

}

}

return TRUE;

}

//MYCOLORIMAGE转换成CImage

BOOL MYIMAGEToCxxImage(CImage& destpCxImage, MYCOLORIMAGE sourpImgbuf, int nImgWidth, int nImgHeight)

{

// 参数检查

if(destpCxImage == NULL || sourpImgbuf.r == NULL || nImgWidth <= 0 || nImgHeight <= 0)

return FALSE;

int i, j;

//24位转换为24位存储

for(j = 0; j < nImgHeight; j++)

{

for(i = 0; i < nImgWidth; i++)

{

destpCxImage.SetPixelRGB(i, j,sourpImgbuf.r[j][i],sourpImgbuf.g[j][i],sourpImgbuf.b[j][i]);

}

}

return TRUE;

}

1、程序示例,一个Laplacian算子进行锐化的例子。

[cpp] view plain copy







//模版系数取1

if (m_Image.IsNull())

return;

BeginWaitCursor();

if (!m_Img.IsNull())

m_Img.Destroy();

m_Img.Create( m_Image.GetWidth(), m_Image.GetHeight(), 24,0);

int nWidth = m_Image.GetWidth();

int nHeight = m_Image.GetHeight();

MYIMAGE RData=NULL;

MYIMAGE GData=NULL;

MYIMAGE BData=NULL;

RData=MyImageAlloc(nHeight,nWidth);

GData=MyImageAlloc(nHeight,nWidth);

BData=MyImageAlloc(nHeight,nWidth);

COLORREF color ;

for(int j = 0;j<nWidth;j++)

for(int i = 0;i<nHeight; i++)

{

color = m_Image.GetPixel(j,i);

RData[i][j]= GetRValue(color);

GData[i][j]= GetGValue(color);

BData[i][j]= GetBValue(color);

}

int templ[9] = {0,-1,0,-1,4,-1,0,-1,0};

for (int i = 1; i < nWidth-1; i++)

{

for (int j = 1; j < nHeight-1; j++)

{

int r = 0, g= 0, b = 0;

int index = 0;

//模版1

for (int col = -1; col <= 1; col++)

{

for (int row = -1; row <= 1; row++)

{

r+= RData[j+row][i+col] * templ[index];

g+= GData[j+row][i+col] * templ[index];

b+= BData[j+row][i+col] * templ[index];

index++;

}

}

if ( r < 0 ) r = -r;

else if ( r > 255 ) r = 255;

if ( g < 0 ) g = -g;

else if ( g > 255 ) g = 255;

if ( b < 0 ) b = -b;

else if ( b > 255 ) b = 255;

m_Img.SetPixelRGB(i,j,r,g,b);

}

}

MyImageFree(RData, nHeight);

MyImageFree(GData, nHeight);

MyImageFree(BData, nHeight);

Invalidate();

EndWaitCursor();

2、比较:比较方便也比较快
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: