原创
图像处理学习系列1:bmp文件的操作1
2009-3-5 14:04
2826
6
6
分类:
软件与OS
bmp文件的操作,在网上有很多例子和资源,相关的理论你可以的帖子:
图像处理编程1.
http://blog.ednchina.com/opencv2008/194349/message.aspx?reload=1
图片格式
http://blog.ednchina.com/opencv2008/194351/message.aspx?reload=1
bmp文件的操作:
http://blog.ednchina.com/opencv2008/194356/message.aspx
天极网图像处理讲座:
http://www.host01.com/article/software/VisualC/20060917183904963.htm
51CTO.COM
http://book.51cto.com/art/200808/84521.htm
还有很多 就不说了
3月2号
我在程序里面主要做了 图像的载入,保存,显示,
之今天为止,发现里面有很多的问题
1.只考虑24位图片的,所以没有考虑调色板的问题
2.库里面应该加入色彩转换以及图像平移的函数
3.图片数据的接口问题还是绝对很不爽,在程序打了之后就觉得很乱
3月5号
修改BMP文件的操作
1.增加函数 m_Palette=CreateBmpPalatte(pbmpinfo);
来创建调色板,里面使用new来开辟Palette空间,没有在外面释放。如果使用MALLOC的话,在调用CREATEPALETTE的
时候会出想错误。如果是24位 则返回空调色板
2.bmp文件操作的时候,使用BITMAPINFO来记录图像信息和颜色表的开始,
但是BITMAPINFO 44个字节 BITMAPFILE 40个字节
读取的时候 直接使用 nreadbyte=(*pbmpfh)->bfOffBits-sizeof(BITMAPFILEHEADER);来记录还要读取的数目
所以没有出现错误
3. 修改bmp读入函数,避免在重复读入数据的时候出现的内存泄漏问题
4. 修改显示函数,可以根据位数来创建调色板。
5. 增加返回颜色数目的函数 GetNumColors(BITMAPINFO *pbmpinfo)
6.修改保存函数可以保存位数不同的图片
3月5号
1.增加24位图转换为灰度图片函数
BOOL Rgb2Gray(BITMAPFILEHEADER **pbmpfh , BITMAPINFO **pbmpinfo , BYTE **pbmpdata)
函数在内部对BITMAPINFO和 PBmpda释放,然后重新分配空间
2/3.其实,BITMAPINFOHEADER和后面的 颜色表以及数据是在一个内存块中的,完全可以通过只传递BITMAPINFO指针
通过地址来查找颜色表和其他数据 要修改的太多了,暂且不动库函数了
/*
输入输出
lpszPathName:路径名
pbmpfh:bmp文件头指针
pbmpinfo:bmp信息头指针
pbmpdata:bmp文件数据
///**************************************************************
整体思路:
读取文件头,利用文件有的信息读取图像信息头数据,利用图像的信息计算图像所需的字节数,开辟空间,
读取文件数据。
×××××××××××××××××××××××××××××××××
开发过程中遇到的问题:在ReadBMPFile()中开辟空间的时候会改变你传递过来的指针的地址,所以使用指针的指针来操做
但是对于savebmp在函数里面并没有开辟空间的事情,只是对传递过来的指针进行操作,不需要使用指针的指针
××××××××××××××××××××××
其他方式载入图片,可以将位图载入到资源中,然后以资源的形式读取文件
××××××××××××××××××××××××××××
//**********************************************
BOOL ReadBMPFile(LPCTSTR lpszPathName,BITMAPFILEHEADER **pbmpfh,BITMAPINFO **pbmpinfo,BYTE **pbmpdata)
{
UINT nbytereaded=0;
if (lpszPathName==NULL)
{
return FALSE;
}
//打开文件
CFile m_file(lpszPathName,CFile::modeRead);
//读取bmp文件头
UINT nreadbyte=sizeof(BITMAPFILEHEADER);
//开辟空间
if (*pbmpfh==NULL)
{
*pbmpfh =(BITMAPFILEHEADER*)malloc(nreadbyte);
if (*pbmpfh==NULL)
{
return FALSE;
}
}
else
{
free(*pbmpfh);
*pbmpfh =(BITMAPFILEHEADER*)malloc(nreadbyte);
if (*pbmpfh==NULL)
{
return FALSE;
}
}
//读取数据
nbytereaded=m_file.Read(*pbmpfh,nreadbyte);
if (nbytereaded!=nreadbyte || (*pbmpfh)==NULL || (*pbmpfh)->bfType != * (WORD *) "BM")
{
AfxMessageBox("读取文件异常1!");
return FALSE;
}
//计算图像信息头+颜色表的信息 的大小
nreadbyte=(*pbmpfh)->bfOffBits-sizeof(BITMAPFILEHEADER);
//开辟空间
if (*pbmpinfo==NULL)
{
*pbmpinfo=(BITMAPINFO*) malloc(nreadbyte);
if (*pbmpinfo==NULL)
{
return FALSE;
}
}
else
{
free(*pbmpinfo);
*pbmpinfo=(BITMAPINFO*) malloc(nreadbyte);
if (*pbmpinfo==NULL)
{
return FALSE;
}
}
//读取数据
nbytereaded=m_file.Read(*pbmpinfo,nreadbyte);
if (nbytereaded!=nreadbyte || *pbmpinfo ==NULL )
{
AfxMessageBox("读取文件异常2!");
return FALSE;
}
//计算图像数据的大小
UINT RowLength = 4 * (((*pbmpinfo)->bmiHeader.biWidth * (*pbmpinfo)->bmiHeader.biBitCount + 31) / 32) ;
nreadbyte=RowLength * (*pbmpinfo)->bmiHeader.biHeight;
//开辟空间
if (*pbmpdata==NULL)
{
*pbmpdata= (BYTE*)malloc(nreadbyte);
if (*pbmpdata==NULL)
{
return FALSE;
}
}
else
{
free(*pbmpdata);
*pbmpdata= (BYTE*)malloc(nreadbyte);
if (*pbmpdata==NULL)
{ return FALSE;
}
}
//读取数据
nbytereaded=m_file.Read(*pbmpdata,nreadbyte);
if (nbytereaded!=nreadbyte || *pbmpdata ==NULL )
{
AfxMessageBox("读取文件异常3!");
return FALSE;
}
m_file.Close();
return TRUE;
}
//***********************************************
BOOL SaveBMPFile(LPCTSTR lpszPathName,BITMAPINFO *pbmpinfo,BYTE *pbmpdata)
{
BITMAPFILEHEADER pbmphdr;
if (pbmpinfo==NULL)
{
return FALSE;
}
if (pbmpdata==NULL)
{
return FALSE;
}
if (pbmpinfo->bmiHeader.biBitCount == 0)
{
pbmphdr.bfType=((WORD) ('M' << 8) | 'B');
pbmphdr.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
pbmphdr.bfReserved1=0;
pbmphdr.bfReserved2=0;
LONG RowLength = 4 * ((pbmpinfo->bmiHeader.biWidth * pbmpinfo->bmiHeader.biBitCount + 31) / 32) ;
LONG imagesize=pbmpinfo->bmiHeader.biHeight * RowLength;
pbmphdr.bfSize=imagesize;
//创建打开文件
CFile m_file(lpszPathName,CFile::modeWrite|CFile::modeCreate);
m_file.Write(&pbmphdr,sizeof(BITMAPFILEHEADER));
m_file.Write(pbmpinfo,sizeof(BITMAPINFOHEADER));
m_file.Write(pbmpdata,pbmphdr.bfSize);
m_file.Close();
}
else
{
int bitcount = pbmpinfo->bmiHeader.biBitCount;
int ColorNum = 1 << bitcount;
RGBQUAD * ColorRGB = new RGBQUAD[ColorNum];
if (bitcount == 8)
{
for ( int i=0 ;i< ColorNum ;i++)
{
ColorRGB.rgbBlue = (BYTE)i;
ColorRGB.rgbGreen = (BYTE)i;
ColorRGB.rgbRed = (BYTE)i;
ColorRGB.rgbReserved=0;
}
}
if (bitcount == 1)
{
for ( int i=0 ;i< ColorNum ;i++)
{
ColorRGB.rgbBlue = (BYTE)(255 * i);
ColorRGB.rgbGreen = (BYTE)(255 * i);
ColorRGB.rgbRed = (BYTE)(255 * i);
ColorRGB.rgbReserved=0;
}
}
if (bitcount == 4)
{
for ( int i=0 ;i< ColorNum ;i++)
{
ColorRGB.rgbBlue = (BYTE)(i << ( 8 - bitcount)) + i;
ColorRGB.rgbGreen = (BYTE)(i << ( 8 - bitcount)) + i;
ColorRGB.rgbRed = (BYTE)(i << ( 8 - bitcount)) + i;
ColorRGB.rgbReserved=0;
}
}
if (bitcount == 2)
{
for ( int i=0 ;i< ColorNum ;i++)
{
ColorRGB.rgbBlue = (BYTE)( 255 / 3 ) * i;
ColorRGB.rgbGreen = (BYTE)( 255 / 3 ) * i;
ColorRGB.rgbRed = (BYTE)( 255 / 3 ) * i;
ColorRGB.rgbReserved=0;
}
}
pbmphdr.bfType=((WORD) ('M' << 8) | 'B');
pbmphdr.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER) + ColorNum * sizeof(RGBQUAD);
pbmphdr.bfReserved1=0;
pbmphdr.bfReserved2=0;
LONG RowLength = 4 * ((pbmpinfo->bmiHeader.biWidth * pbmpinfo->bmiHeader.biBitCount + 31) / 32) ;
LONG imagesize=pbmpinfo->bmiHeader.biHeight * RowLength;
pbmphdr.bfSize=imagesize;
//创建打开文件
CFile m_file(lpszPathName,CFile::modeWrite|CFile::modeCreate);
m_file.Write(&pbmphdr,sizeof(BITMAPFILEHEADER));
m_file.Write(pbmpinfo,sizeof(BITMAPINFOHEADER));
m_file.Write(ColorRGB,ColorNum * sizeof(RGBQUAD));
m_file.Write(pbmpdata,pbmphdr.bfSize);
delete []ColorRGB;
m_file.Close();
}
return TRUE;
}
//*************************************************
//返回调色板色彩数
//如果是24位色彩,返回0
//**************************************************
int GetNumColors(BITMAPINFO *pbmpinfo)
{
if (pbmpinfo==NULL)
{
return NULL;
}
int BitCount=pbmpinfo->bmiHeader.biBitCount;
switch (BitCount)
{
case 0:
return 0;
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
//************************************************
//创建调色板
//pbmpinfo 位图信息
//pPal 调色板数据
//************************************************
CPalette* CreateBmpPalatte(BITMAPINFO *pbmpinfo)
{
//
if (pbmpinfo==NULL)
{
return NULL;
}
CPalette *pPal;
pPal=new CPalette;
LOGPALETTE *pLogPal;
int imagecolor = GetNumColors(pbmpinfo);
//如果是24位 返回
if (imagecolor==0)
{
return NULL;
}
//开辟空间
pLogPal=(LOGPALETTE * )malloc(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * imagecolor);
pLogPal->palVersion=0x300;
pLogPal->palNumEntries=imagecolor;
//颜色数据
for(int i=0 ; i<imagecolor ; i++ )
{
pLogPal->palPalEntry.peRed=pbmpinfo->bmiColors.rgbRed; //初始化为红色
pLogPal->palPalEntry.peGreen=pbmpinfo->bmiColors.rgbGreen;
pLogPal->palPalEntry.peBlue=pbmpinfo->bmiColors.rgbBlue;
pLogPal->palPalEntry.peFlags=0;
}
//创建
if(!pPal->CreatePalette(pLogPal))
AfxMessageBox("Can't create palette!");
return pPal;
}
//**********************************************
/*
hDC: 设备句柄
lpDCRect: 一般从CPOINT(0,0)开始,输出到屏幕的区域
lpDIBRect:图片的大小
pbmpinfo:图片的信息头
pbmpdata:图片数据
*/
//************************************************
BOOL PrintDIB(HDC hDC,LPRECT lpDCRect,LPRECT lpDIBRect,BITMAPINFO *pbmpinfo,BYTE *pbmpdata)
{
BOOL bSuccess=TRUE;
if (lpDCRect->bottom == 0 || lpDCRect->right == 0)
{
return FALSE;
}
if (lpDIBRect->bottom == 0 || lpDIBRect->right == 0)
{
return FALSE;
}
//如果不是24位色彩
HPALETTE temp_pPal;
HPALETTE HPal;
if (GetNumColors(pbmpinfo))
{
CPalette* pPal;
pPal=CreateBmpPalatte(pbmpinfo);
HPal=(HPALETTE)(pPal->m_hObject);
temp_pPal = ::SelectPalette(hDC,HPal,TRUE);
::RealizePalette(hDC);
}
// 设置显示模式
::SetStretchBltMode(hDC, COLORONCOLOR);
/* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
if ((lpDCRect->bottom == lpDIBRect->bottom) && (lpDCRect->right == lpDIBRect->right))
bSuccess = ::SetDIBitsToDevice(hDC, // hDC
lpDCRect->left, // DestX
lpDCRect->top, // DestY
lpDCRect->right, // nDestWidth
lpDCRect->bottom, // nDestHeight
lpDIBRect->left, // SrcX
lpDIBRect->top, // SrcY
0, // nStartScan
lpDIBRect->bottom,
pbmpdata, // lpBits
pbmpinfo, // lpBitsInfo
DIB_RGB_COLORS // wUsage
);
else
bSuccess = ::StretchDIBits(hDC, // hDC
lpDCRect->left, // DestX
lpDCRect->top, // DestY
lpDCRect->right, // nDestWidth
lpDCRect->bottom, // nDestHeight
lpDIBRect->left, // SrcX
lpDIBRect->top, // SrcY
lpDIBRect->right,
lpDIBRect->bottom,
pbmpdata, // lpBits
pbmpinfo, // lpBitsInfo
DIB_RGB_COLORS, // wUsage
SRCCOPY
);
::SelectPalette(hDC,temp_pPal,TRUE);
//delete temp_pPal;
return bSuccess;
}
/****************************************************************************
//彩色图片转换到灰度图片
文章评论(0条评论)
登录后参与讨论