实在抱歉,上一篇发错位置了
既然如此,就说一说吧。
一般来说,图象数据是用二维矩阵表示的,每个象素是二维矩阵
的一个元素。而能显示的图象,应该是每个象素的值都在0~255
之间。在图象处理中,经常会将图象处理为其它范围,所以,显
示时第一步就是将图象数据规一化到0~255。这个规一化可以是
线性的( (val-min)*255/(max-min) ),也可以是非线性的,
如先取log。使用何种规一化函数就看实际数据了。如果变化范围
相当大,则取log等非线性规一化比较好,否则线性规一化效果好。
规一化之后的数据要存放在BYTE类型的二维矩阵中,只有这种二维
矩阵才可以被显示出来。另外,由于WIN32GDI在处理数据时要求图
象每行的字节宽度为4的整数倍,所以,如果原始数据的宽度不适合
的化,要注意先将行调整到合适的宽度。
然后就是用这个二维矩阵创建一个HBITMAP的句柄了。上面的方法
转换出来的是灰度图象,所以还要为其生成一个调色板。
下面是我用来画图的函数:
//---------------------------------------------------------------------------
//辅助函数:如果图象的宽度不是4的倍数,则将其对齐到4的倍数
//输入参数data为BYTE型的图象,宽度w,高度h
//返回的缓冲区内存放了对齐后的图象。注意,在NT4上面,用
//new分配的内存和用GlobalAlloc分配的内存是有区别的!!
//如果较大的图象存放在用new分配的内存中,则系统显示不出来,但
//不会返回任何错误信息!!
void *ExpandLine(void *data,int w,int h)
{
int linebytes = w;
int linew = (linebytes+3)&(~3);
char *buf = GlobalAlloc(GMEM_FIXED,linew*h);
for(int i=0;i<h;i++)
{
memcpy(buf+linew*i,((char*)data)+linebytes*i,linebytes);
}
return buf;
}
//---------------------------------------------------------------------------
//这个结构由于创建HBITMAP,其pals成员就是调色板
struct TGrayBMPHeader
{
BITMAPINFOHEADER header;
RGBQUAD pals[256];
TGrayBMPHeader();
void SetInfo(int w,int h)
{
header.biWidth = w;
header.biHeight = -h;
}
};
//---------------------------------------------------------------------------
TGrayBMPHeader::TGrayBMPHeader()
{
header.biSize = sizeof(header);
header.biPlanes = 1;
header.biBitCount = 8;
header.biCompression = BI_RGB;
header.biSizeImage = 0;
header.biXPelsPerMeter = 120;
header.biYPelsPerMeter = 120;
header.biClrUsed = 0;
header.biClrImportant = 0;
for(int i=0;i<256;i++)
{
pals
.rgbBlue = (unsigned char)i;
pals.rgbGreen = (unsigned char)i;
pals.rgbRed = (unsigned char)i;
pals.rgbReserved = 0;
}
}
//---------------------------------------------------------------------------
//真正的函数在这里,data是BYTE型图象,宽度w,高度h
//返回的句柄可以用其它WIN32函数显示,但记得释放哦
HBITMAP CreateBMP(void *y,int w,int h)
{
assert;
void *ty = NULL;
if(w&3) //测试4字节对齐
{
ty = ExpandLine(y,w,h,1);
}
TGrayBMPHeader header;
header.SetInfo(w,h);
HDC dc = GetDC(0);//该死的GDI总是要一个DC,虽然创建HBITMAP可以与DC无关。这个DC比较适合于显示,如果想打印的化,应该用别的DC。
assert(dc);
HBITMAP handle = CreateDIBitmap(
dc,&(header.header),CBM_INIT,(ty?ty:y),(BITMAPINFO *)(&header),DIB_RGB_COLORS);
ReleaseDC(0,dc);
if(ty)
GlobalFree(ty);
return handle;
}
//---------------------------------------------------------------------------