精华内容
下载资源
问答
  • DDB与DIB位图编程

    2012-04-23 16:06:28
    DDB与DIB位图编程,讲的比较好~值得学习
  • CDib封装DIB位图的类

    2012-03-27 14:54:33
    CDib封装DIB位图的类
  • DIB位图显示图像

    2018-02-12 11:45:22
    一、DIB位图结构及注意点:1.DIB结构:一个完整的DIB由两部分组成:一个BITMAPINFO结构和一个存储像素阵列的数组:typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1]; //...

    一、DIB位图结构及注意点:

    1.DIB结构:

    一个完整的DIB由两部分组成:一个BITMAPINFO结构和一个存储像素阵列的数组:

    1. typedef struct tagBITMAPINFO {   
    2.             BITMAPINFOHEADER bmiHeader;   
    3.             RGBQUAD bmiColors[1]; //颜色表  
    4.             } BITMAPINFO;  

    由此可见BITMAPINFO结构包含两个部分,BITMAPINFOHEADER结构和RGBQUAD结构,其中两个结构定义如下:

    1. typedef struct tagBITMAPINFOHEADER{   
    2.             DWORD biSize; //该结构的大小  
    3.             LONG biWidth; //位图的宽度(以像素为单位)  
    4.             LONG biHeight; //位图的高度(以像素为单位)  
    5.             WORD biPlanes; //必须为1  
    6.             WORD biBitCount //每个像素的位数(1、4、8、16、24或32)  
    7.             DWORD biCompression; //压缩方式,一般为0或BI_RGB (未压缩)  
    8.             DWORD biSizeImage; //以字节为单位的图象大小(仅用于压缩位图)  
    9.             LONG biXPelsPerMeter; //以目标设备每米的像素数来说明位图的水平分辨率  
    10.             LONG biYPelsPerMeter; //以目标设备每米的像素数来说明位图的垂直分辨率  
    11.             DWORD biClrUsed; /*颜色表的颜色数,若为0则位图使用由biBitCount指定的最大颜色数*/  
    12.             DWORD biClrImportant; //重要颜色的数目,若该值为0则所有颜色都重要  
    13.             } BITMAPINFOHEADER;  
    1. typedef struct tagRGBQUAD {  
    2.             BYTE rgbBlue; //蓝色的强度  
    3.             BYTE rgbGreen; //绿色的强度  
    4.             BYTE rgbRed; //红色的强度  
    5.             BYTE rgbReserved; //保留字节,为0  
    6.             } RGBQUAD;  
    7. //注意,RGBQUAD结构中的颜色顺序是BGR,而不是平常的RGB。  
    由此可知,BITMAPINFO结构是由图像的基本信息和调色板组成,对于彩色图,没有调色板,所以BITMAPINFO只包含图像的基本信息结构BITMAPINFOHEADER:

                                                              灰度图                                                            彩色图

    BITMAPINFO包含:         BITMAPINFOHEADER   + RGBQUAD         BITMAPINFOHEADER 
    2.DIB注意点:

    <1>DIB位图每行数据必须是32bit(4个字节)的整数倍,如果图像数据为Byte型(0~255),即每个像素为一个字节(8bit),这样图像每行的宽必须是4的整数倍,不足4的整数倍的部分,以0补充。

    <2>DIB数据存储顺序是:自左到右,自下到上,逆序存储。即:图像的第一行数据,存在DIB数据部分最后一行,最后一行存在第一行,因为显示的时候,DIB位图是,自下而上显示的,即读取的第一行数据,会显示在界面的最后一行,然后,第二行显示在界面倒数第二行。

    <3>调色板顺序为BGR而不是RGB

    二、DIB结构赋值及显示:

    1.先看一下显示函数:

    1. int StretchDIBits(HDC hdc, int XDest , int YDest , int nDestWidth, int nDestHeight,   
    2. int XSrc, int Ysrc, int nSrcWidth, int nSrcHeight,   
    3. CONST VOID *lpBits, CONST BITMAPINFO * lpBitsInfo,   
    4.   
    5. hdc:指向目标设备环境的句柄。  
    6. XDest:指定目标矩形左上角位置的X轴坐标,按逻辑单位来表示坐标。  
    7. YDest:指定目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。  
    8. nDestWidth:指定目标矩形的宽度。  
    9. nDestHeight:指定目标矩形的高度。  
    10. XSrc:指定DIB中源矩形(左上角)的X轴坐标,坐标以像素点表示。  
    11. YSrc:指定DIB中源矩形(左上角)的Y轴坐标,坐标以像素点表示。  
    12. nSrcWidth:按像素点指定DIB中源矩形的宽度。  
    13. nSrcHeight:按像素点指定DIB中源矩形的高度。  
    14. lpBits:指向DIB位的指针,这些位的值按字节类型数组存储,有关更多的信息,参考下面的备注一节。  
    15. lpBitsInfo:指向BITMAPINFO结构的指针,该结构包含有关DIB方面的信息。  
    16. iUsage:表示是否提供了BITMAPINFO结构中的成员bmiColors,如果提供了,那么该bmiColors是否包含了明确的RGB值或索引。参数iUsage必须取下列值,这些值的含义如下:  
    17. DIB_PAL_COLORS:表示该数组包含对源设备环境的逻辑调色板进行索引的16位索引值。  
    18. DIB_RGB_COLORS:表示该颜色表包含原义的RGB值,若想了解更多的信息,请参考下面备注一节。  
    19. dwRop:指定源像素点、目标设备环境的当前刷子和目标像素点是如何组合形成新的图像。若想了解更多信息,请参考下面的备注一节。  
    20. 返回值:如果函数执行成功,那么返回值是拷贝的扫描线数目,如果函数执行失败,那么返回值是GDI_ERROR。UINT iUsage, DWORD dwRop);
    由此可知:只要对BITMAPINFO结构和像素阵列的数组赋值即可:

    2.DIB赋值:

    <1>在 ***Doc.h中定义BITMAPINFO结构和像素阵列的数组变量:

    1. public:  
    2.     BITMAPINFO *m_pBmInfo; //位图信息头  
    3.     unsigned char *m_pImageData; //位图数据  
    4.     void InitialDIB(unsigned char **InData8); //初始化位图信息头与数据  

    <2>在***Doc.cpp中对变量赋值:

    1. void C***Doc::InitialDIB(unsigned char **InData8) //InData8 包含图像数据数组  
    2. {  
    3.     int i,row,col,tIND,ImgIdx;  
    4.     if(m_nAllBandNum == 1) //如果图像只有一个波段,按灰度图显示  
    5.     {  
    6.         m_pBmInfo = (BITMAPINFO *) new BYTE[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*255];  
    7.                                       //开辟BITMAPINFO结构大小  
    8.         for (i=0; i<256; i++)  
    9.         {  
    10.             m_pBmInfo->bmiColors[i].rgbRed = i;  
    11.             m_pBmInfo->bmiColors[i].rgbGreen = i;  
    12.             m_pBmInfo->bmiColors[i].rgbBlue = i;           
    13.         }         
    14.         m_pBmInfo->bmiHeader.biBitCount = 8;   
    15.     }  
    16.     else //如果大于一个波段,按彩色图显示  
    17.     {  
    18.         m_pBmInfo = (BITMAPINFO *) new BYTE[sizeof(BITMAPINFOHEADER)];  
    19.         m_pBmInfo->bmiHeader.biBitCount = 24; //也可以是32,如果是32下面对彩色图赋值将不同,下面再说  
    20.     }  
    21.       
    22.     //设置图像基本信息  
    23.     m_pBmInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);    
    24.     m_pBmInfo->bmiHeader.biWidth = m_nImageWidth;  
    25.     m_pBmInfo->bmiHeader.biHeight =m_nImageHeight;  
    26.   
    27.     m_pBmInfo->bmiHeader.biCompression = BI_RGB;  
    28.     m_pBmInfo->bmiHeader.biPlanes = 1;  
    29.     m_pBmInfo->bmiHeader.biClrUsed = 0;  
    30.     m_pBmInfo->bmiHeader.biClrImportant = 0;  
    31.     m_pBmInfo->bmiHeader.biSizeImage = 4*((m_nImageWidth*m_pBmInfo->bmiHeader.biBitCount+31)/32)*m_nImageHeight;  
    32.     int nWideBytes = 4*((m_pBmInfo->bmiHeader.biWidth*m_pBmInfo->bmiHeader.biBitCount+31)/32);  
    33.     m_pImageData = new BYTE[nWideBytes * m_nImageHeight];   //开辟数据缓存      
    34.   
    35.     if(m_nAllBandNum == 1)  //灰度图:对图像数据数组赋值  
    36.     {  
    37.         for(row = 0;row<m_nImageHeight; row++)  
    38.         {  
    39.             for(col=0; col<m_nImageWidth; col++)  
    40.             {  
    41.                 ImgIdx = m_nImageWidth * row + col;  
    42.                 tIND = nWideBytes * (m_nImageHeight - row - 1) + col;  
    43.                 m_pImageData[tIND] = InData8[0][ImgIdx];  
    44.             }  
    45.         }  
    46.     }  
    47.     else //彩色图:  
    48.     {  
    49.         for(row = 0;row<m_nImageHeight; row++)  
    50.         {  
    51.             for(col=0; col<m_nImageWidth; col++)  
    52.             {  
    53.                 ImgIdx =m_nImageWidth * row + col;  
    54.   
    55.                 tIND = nWideBytes * (m_nImageHeight - row - 1) + 3*col;  
    56.   
    57.                 m_pImageData[tIND] = InData8[2][ImgIdx]; //B  
    58.                 tIND += 1;  
    59.                 m_pImageData[tIND] = InData8[1][ImgIdx]; //G  
    60.                 tIND += 1;  
    61.                 m_pImageData[tIND] = InData8[0][ImgIdx]; //R  
    62.   
    63.             }  
    64.         }  
    65.       
    66.     }  
    67. }  
    如果 设置m_pBmInfo->bmiHeader.biBitCount = 32,则彩色图对数据赋值部分要改为:

    1. else //彩色图:  
    2. {  
    3.     for(row = 0;row<m_nImageHeight; row++)  
    4.     {  
    5.         for(col=0; col<m_nImageWidth; col++)  
    6.         {  
    7.             ImgIdx =m_nImageWidth * row + col;  
    8.   
    9.             tIND = nWideBytes * (m_nImageHeight - row - 1) + 4*col;  
    10.   
    11.             m_pImageData[tIND] = InData8[2][ImgIdx]; //B  
    12.             tIND += 1;  
    13.             m_pImageData[tIND] = InData8[1][ImgIdx]; //G  
    14.             tIND += 1;  
    15.             m_pImageData[tIND] = InData8[0][ImgIdx]; //R  
    16.             tIND +=1;  
    17.             m_pImageData[tIND] = 0; //保留字节 rgbReserved  
    18.               
    19.         }  
    20.     }  
    21. }  

    <3>显示图像:

    在***View的OnDraw()函数中调用显示函数:

    1. ::SetStretchBltMode(pDC->m_hDC,STRETCH_HALFTONE); //设置拉伸方式,避免缩小时图像失真  
    2. ::StretchDIBits(pDC->m_hDC,  0, 0, nImgWidth ,  
    3.                 nImgHeight ,0, 0, nImgWidth, nImgHeight,  
    4.                 pDoc->m_pImageData, pDoc->m_pBmInfo, DIB_RGB_COLORS, SRCCOPY) ;  
    可以调整显示区域大小,图像会发生相应的拉伸,具体见StretchDIBits参数。

    注:

    1.如果是对话框,可以OnPaint()中调用。

    2.至于DIB对象的定义、赋值和显示调用位置,根据需要而定。

    3.图像数据的获取,可以参看GDAL类,该类可直接获取图像的基本信息。


    展开全文
  • Windows----DIB位图

    2011-05-06 10:38:30
    我收集的关于DIB位图的资料,详细的讲解了设备相关位图,设备无关位图之间的区别,使用方法。讲解了Windows调色板等。
  • 如何在mfc中进行DIB位图编程,特别是BMP格式如何用DIB进行表示,把他们进行融合起来。
  • 如果我们有一个DIB位图句柄,将它写入位图文件非常简单。你只需根据位图中 的内容填写结构BITMAPINFOHEADER。主要是将该结构中的三个成员设置,将bfType 设为"BM",另外设置bfSize和bfOffBits。...

    如果我们有一个DIB位图句柄,将它写入位图文件非常简单。你只需根据位图中
    的内容填写结构BITMAPINFOHEADER。主要是将该结构中的三个成员设置,将bfType
    设为"BM",另外设置bfSize和bfOffBits。

    如果你想将DDB位图存为位图文件,只需将DDB转为DIB后使用本方法即可。

    // WriteDIB - Writes a DIB to file
    // Returns - TRUE on success
    // szFile - Name of file to write to
    // hDIB - Handle of the DIB
    BOOL WriteDIB( LPTSTR szFile, HANDLE hDIB)
    {
    BITMAPFILEHEADER hdr;
    LPBITMAPINFOHEADER lpbi;

    if (!hDIB)
    return FALSE;

    CFile file;
    if( !file.Open( szFile, CFile::modeWrite|CFile::modeCreate) )
    return FALSE;

    lpbi = (LPBITMAPINFOHEADER)hDIB;

    int nColors = 1 << lpbi->biBitCount;

    // Fill in the fields of the file header
    hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
    hdr.bfSize = GlobalSize (hDIB) + sizeof( hdr );
    hdr.bfReserved1 = 0;
    hdr.bfReserved2 = 0;
    hdr.bfOffBits = (DWORD) (sizeof( hdr ) + lpbi->biSize +
    nColors * sizeof(RGBQUAD));

    // Write the file header
    file.Write( &hdr, sizeof(hdr) );

    // Write the DIB header and the bits
    file.Write( lpbi, GlobalSize(hDIB) );

    return TRUE;
    }

    展开全文
  • 新建一个类,显示DIB位图,串行化,从客户区截取图片,打开和保存BMP格式位图。为测试截图功能,增加了画笔涂鸦功能。
  • 使用VC6.0实现DIB位图图像的特效显示:图像扫描、百叶窗、马赛克等各种特效显示。
  • 本文主要介绍:DIB位图的一些基础知识和在MFC中如何利用DIB位图显示图像。 一、DIB位图结构及注意点: 1.DIB结构: 一个完整的DIB由两部分组成:一个BITMAPINFO结构和一个存储像素阵列的数组: typedef struct ...

    本文主要介绍:DIB位图的一些基础知识和在MFC中如何利用DIB位图显示图像。

    一、DIB位图结构及注意点:

    1.DIB结构:

    一个完整的DIB由两部分组成:一个BITMAPINFO结构和一个存储像素阵列的数组:

    typedef struct tagBITMAPINFO { 
                BITMAPINFOHEADER bmiHeader; 
                RGBQUAD bmiColors[1]; //颜色表
                } BITMAPINFO;
    由此可见BITMAPINFO结构包含两个部分,BITMAPINFOHEADER结构和RGBQUAD结构,其中两个结构定义如下:

    typedef struct tagBITMAPINFOHEADER{ 
                DWORD biSize; //该结构的大小
                LONG biWidth; //位图的宽度(以像素为单位)
                LONG biHeight; //位图的高度(以像素为单位)
                WORD biPlanes; //必须为1
                WORD biBitCount //每个像素的位数(1、4、8、16、24或32)
                DWORD biCompression; //压缩方式,一般为0或BI_RGB (未压缩)
                DWORD biSizeImage; //以字节为单位的图象大小(仅用于压缩位图)
                LONG biXPelsPerMeter; //以目标设备每米的像素数来说明位图的水平分辨率
                LONG biYPelsPerMeter; //以目标设备每米的像素数来说明位图的垂直分辨率
                DWORD biClrUsed; /*颜色表的颜色数,若为0则位图使用由biBitCount指定的最大颜色数*/
                DWORD biClrImportant; //重要颜色的数目,若该值为0则所有颜色都重要
                } BITMAPINFOHEADER;

    typedef struct tagRGBQUAD {
                BYTE rgbBlue; //蓝色的强度
                BYTE rgbGreen; //绿色的强度
                BYTE rgbRed; //红色的强度
                BYTE rgbReserved; //保留字节,为0
                } RGBQUAD;
    //注意,RGBQUAD结构中的颜色顺序是BGR,而不是平常的RGB。
    由此可知,BITMAPINFO结构是由图像的基本信息和调色板组成,对于彩色图,没有调色板,所以BITMAPINFO只包含图像的基本信息结构BITMAPINFOHEADER:

                                                              灰度图                                                            彩色图

    BITMAPINFO包含:         BITMAPINFOHEADER   + RGBQUAD         BITMAPINFOHEADER 
    2.DIB注意点:

    <1>DIB位图每行数据必须是32bit(4个字节)的整数倍,如果图像数据为Byte型(0~255),即每个像素为一个字节(8bit),这样图像每行的宽必须是4的整数倍,不足4的整数倍的部分,以0补充。

    <2>DIB数据存储顺序是:自左到右,自下到上,逆序存储。即:图像的第一行数据,存在DIB数据部分最后一行,最后一行存在第一行,因为显示的时候,DIB位图是,自下而上显示的,即读取的第一行数据,会显示在界面的最后一行,然后,第二行显示在界面倒数第二行。

    <3>调色板顺序为BGR而不是RGB

    二、DIB结构赋值及显示:

    1.先看一下显示函数:

    int StretchDIBits(HDC hdc, int XDest , int YDest , int nDestWidth, int nDestHeight, 
    int XSrc, int Ysrc, int nSrcWidth, int nSrcHeight, 
    CONST VOID *lpBits, CONST BITMAPINFO * lpBitsInfo, 
    
    hdc:指向目标设备环境的句柄。
    XDest:指定目标矩形左上角位置的X轴坐标,按逻辑单位来表示坐标。
    YDest:指定目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。
    nDestWidth:指定目标矩形的宽度。
    nDestHeight:指定目标矩形的高度。
    XSrc:指定DIB中源矩形(左上角)的X轴坐标,坐标以像素点表示。
    YSrc:指定DIB中源矩形(左上角)的Y轴坐标,坐标以像素点表示。
    nSrcWidth:按像素点指定DIB中源矩形的宽度。
    nSrcHeight:按像素点指定DIB中源矩形的高度。
    lpBits:指向DIB位的指针,这些位的值按字节类型数组存储,有关更多的信息,参考下面的备注一节。
    lpBitsInfo:指向BITMAPINFO结构的指针,该结构包含有关DIB方面的信息。
    iUsage:表示是否提供了BITMAPINFO结构中的成员bmiColors,如果提供了,那么该bmiColors是否包含了明确的RGB值或索引。参数iUsage必须取下列值,这些值的含义如下:
    DIB_PAL_COLORS:表示该数组包含对源设备环境的逻辑调色板进行索引的16位索引值。
    DIB_RGB_COLORS:表示该颜色表包含原义的RGB值,若想了解更多的信息,请参考下面备注一节。
    dwRop:指定源像素点、目标设备环境的当前刷子和目标像素点是如何组合形成新的图像。若想了解更多信息,请参考下面的备注一节。
    返回值:如果函数执行成功,那么返回值是拷贝的扫描线数目,如果函数执行失败,那么返回值是GDI_ERROR。UINT iUsage, DWORD dwRop);
    由此可知:只要对BITMAPINFO结构和像素阵列的数组赋值即可:

    2.DIB赋值:

    <1>在 ***Doc.h中定义BITMAPINFO结构和像素阵列的数组变量:

    public:
    	BITMAPINFO *m_pBmInfo; //位图信息头
    	unsigned char *m_pImageData; //位图数据
    	void InitialDIB(unsigned char **InData8); //初始化位图信息头与数据
    <2>在***Doc.cpp中对变量赋值:

    void C***Doc::InitialDIB(unsigned char **InData8) //InData8 包含图像数据数组
    {
    	int i,row,col,tIND,ImgIdx;
    	if(m_nAllBandNum == 1) //如果图像只有一个波段,按灰度图显示
    	{
    		m_pBmInfo = (BITMAPINFO *) new BYTE[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*255];
    	                                  //开辟BITMAPINFO结构大小
    		for (i=0; i<256; i++)
    		{
    			m_pBmInfo->bmiColors[i].rgbRed = i;
    			m_pBmInfo->bmiColors[i].rgbGreen = i;
    			m_pBmInfo->bmiColors[i].rgbBlue = i;			
    		}		
    		m_pBmInfo->bmiHeader.biBitCount = 8; 
    	}
    	else //如果大于一个波段,按彩色图显示
    	{
    		m_pBmInfo = (BITMAPINFO *) new BYTE[sizeof(BITMAPINFOHEADER)];
    		m_pBmInfo->bmiHeader.biBitCount = 24; //也可以是32,如果是32下面对彩色图赋值将不同,下面再说
    	}
        
    	//设置图像基本信息
    	m_pBmInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);	
    	m_pBmInfo->bmiHeader.biWidth = m_nImageWidth;
    	m_pBmInfo->bmiHeader.biHeight =m_nImageHeight;
    
    	m_pBmInfo->bmiHeader.biCompression = BI_RGB;
    	m_pBmInfo->bmiHeader.biPlanes = 1;
    	m_pBmInfo->bmiHeader.biClrUsed = 0;
    	m_pBmInfo->bmiHeader.biClrImportant = 0;
    	m_pBmInfo->bmiHeader.biSizeImage = 4*((m_nImageWidth*m_pBmInfo->bmiHeader.biBitCount+31)/32)*m_nImageHeight;
    	int nWideBytes = 4*((m_pBmInfo->bmiHeader.biWidth*m_pBmInfo->bmiHeader.biBitCount+31)/32);
    	m_pImageData = new BYTE[nWideBytes * m_nImageHeight];	//开辟数据缓存	
    
    	if(m_nAllBandNum == 1)  //灰度图:对图像数据数组赋值
    	{
    		for(row = 0;row<m_nImageHeight; row++)
    		{
    			for(col=0; col<m_nImageWidth; col++)
    			{
    				ImgIdx = m_nImageWidth * row + col;
    				tIND = nWideBytes * (m_nImageHeight - row - 1) + col;
    				m_pImageData[tIND] = InData8[0][ImgIdx];
    			}
    		}
    	}
    	else //彩色图:
    	{
    		for(row = 0;row<m_nImageHeight; row++)
    		{
    			for(col=0; col<m_nImageWidth; col++)
    			{
    				ImgIdx =m_nImageWidth * row + col;
    
    				tIND = nWideBytes * (m_nImageHeight - row - 1) + 3*col;
    
    				m_pImageData[tIND] = InData8[2][ImgIdx]; //B
    				tIND += 1;
    				m_pImageData[tIND] = InData8[1][ImgIdx]; //G
    				tIND += 1;
    				m_pImageData[tIND] = InData8[0][ImgIdx]; //R
    
    			}
    		}
    	
    	}
    }
    如果 设置m_pBmInfo->bmiHeader.biBitCount = 32,则彩色图对数据赋值部分要改为:

    	else //彩色图:
    	{
    		for(row = 0;row<m_nImageHeight; row++)
    		{
    			for(col=0; col<m_nImageWidth; col++)
    			{
    				ImgIdx =m_nImageWidth * row + col;
    
    				tIND = nWideBytes * (m_nImageHeight - row - 1) + 4*col;
    
    				m_pImageData[tIND] = InData8[2][ImgIdx]; //B
    				tIND += 1;
    				m_pImageData[tIND] = InData8[1][ImgIdx]; //G
    				tIND += 1;
    				m_pImageData[tIND] = InData8[0][ImgIdx]; //R
    				tIND +=1;
    				m_pImageData[tIND] = 0; //保留字节 rgbReserved
    				
    			}
    		}
    	}

    <3>显示图像:

    在***View的OnDraw()函数中调用显示函数:

    	::SetStretchBltMode(pDC->m_hDC,STRETCH_HALFTONE); //设置拉伸方式,避免缩小时图像失真
    	::StretchDIBits(pDC->m_hDC,	0, 0, nImgWidth ,
    					nImgHeight ,0, 0, nImgWidth, nImgHeight,
    					pDoc->m_pImageData, pDoc->m_pBmInfo, DIB_RGB_COLORS, SRCCOPY) ;
    可以调整显示区域大小,图像会发生相应的拉伸,具体见StretchDIBits参数。

    注:

    1.如果是对话框,可以OnPaint()中调用。

    2.至于DIB对象的定义、赋值和显示调用位置,根据需要而定。

    3.图像数据的获取,可以参看GDAL类,该类可直接获取图像的基本信息。

    展开全文
  • DIB位图(Bitmap)的读取和保存 设备无关位图(Device Independent Bitmap)是可以保存在磁盘的位图文件,可以从磁盘读取到内存或者从内存保存到磁盘上。它的文件结构是标准化的,可以在Windows/...

    DIB位图(Bitmap)的读取和保存

    设备无关位图(Device Independent Bitmap)是可以保存在磁盘的位图文件,可以从磁盘读取到内存或者从内存保存到磁盘上。它的文件结构是标准化的,可以在Windows/Linux/Unix等平台上显示相同的效果。本文主要介绍了

    1. 如果将位图文件从磁盘读到内存中
    2. 在内存中对位图文件进行操作后,如何将位图保存到磁盘

    1 读取位图到内存中

    1.1 DIB文件结构

    要将位图文件(.bmp)从磁盘读取到内存,首先要了解其文件结构。DIB的文件组成有以下4个部分:

    1. 文件表头,主要包含了文件的类型(必须是BM),文件的大小(所占用的字节数)和位图的像素矩阵的便宜量。
    2. 信息表头,包含了两部分内容:位图的相关信息(位图的大小、位深度、位面数、压缩和编码等)和指向RGB颜色表(调色盘)的指针。
    3. RGB色彩对照表,也就是调色板,不一定会有。16位及以上直接使用RGB通道表示颜色,一般不需要调色板。
    4. 位图的像素信息矩阵,表示具体的像素。1,4,8位颜色,保存的是调色板的索引,具体的颜色根据索引在调色板中查找;16位及其以上不使用调色板,直接使用RGB组成像素颜色。

    1.2 在Windows下DIB的内存结构

    要将DIB数据读取到内存,就需要在内存中分配相应的空间。Windows提供了几种结构体,结构体中的字段对应着DIB文件的各个信息值,具体如下
    alter

    引用自 http://blog.csdn.net/wenzhou1219/article/details/26162869

    将DIB读取到内存只需要将磁盘数据填充到相应到结构体即可。在磁盘上DIB需要连续的结构存储,在内存中则不需要连续的存储空间,可以分段将数据读取到相应的结构体中。
    读取DIB到内存的具体步骤:

    1. 将文件头信息读取到BITMAPFILEHEADER结构体中。
    2. 将位图头信息读取到BITMAPINFOHEADER结构体中。
    3. 如果有调色板,则将其信息读取到RGBQUAD中。
    4. 读取位图像素信息到像素矩阵中。
    fp.Read(&bmfileHeader, sizeof(BITMAPFILEHEADER)); // 读取BMP文件头 
    ...
    //读取文件信息头
    ret = fp.Read(&bmHeader, sizeof(BITMAPINFOHEADER)); 
    ...
    fp.Read(m_dibBits, GetBodySize());  //读取像素信息 

    1.3 结构体各字段信息

    BITMAPFILEHEADER

    代表文件头信息的结构体BITMAPFILEHEADER的声明如下:

    typedef struct tagBITMAPFILEHEADER {
            WORD    bfType;
            DWORD   bfSize;
            WORD    bfReserved1;
            WORD    bfReserved2;
            DWORD   bfOffBits;
    } BITMAPFILEHEADER  

    其中,

    • bfType是文件类型,该字段必须是BM,如果不是则说明该文件不是DIB。
    • bfSize是位图文件的大小(字节数)
    • bfReserved1和bfReserved2 是保留字段
    • bfOffBits 从BITMAPFILEHEADER的起始位置到位图像素的字节偏移量。

      BITMAPINFO
      在上面提到,位图信息和位图的调色板是存放在同一个结构体中的,该结构体就是BITMAPINFO,其声明如下
    typedef struct tagBITMAPINFO {
      BITMAPINFOHEADER bmiHeader;
      RGBQUAD          bmiColors[1];
    } BITMAPINFO, *PBITMAPINFO;

    bmiHeader是位图头信息
    bmiColors是调色板

    BITMAPINFOHEADER

    位图的头信息结构BITMAPINFOHEADER,该结构包含了DIB的尺寸和颜色格式等信息,声明如下

    typedef struct tagBITMAPINFOHEADER{
            DWORD      biSize;
            LONG       biWidth;
            LONG       biHeight;
            WORD       biPlanes;
            WORD       biBitCount;
            DWORD      biCompression;
            DWORD      biSizeImage;
            LONG       biXPelsPerMeter;
            LONG       biYPelsPerMeter;
            DWORD      biClrUsed;
            DWORD      biClrImportant;
    } BITMAPINFOHEADER  

    其中,

    • biSize是该结构体所占用的字节说
    • biWidth DIB的宽(以像素为单位),如果biCompression是BI_JPEG或者BI_PNG,则biWidth是解压缩后JPEG或者PNG图像的宽度。
    • biHeight,DIB的高(以像素为单位)。
      • 如果biHeight是正的,则DIB的像素是按照从下往上(bottom-up,也就是像素数组的第一行保存的实际是DIB的最后一行像素值),图像源点在左下角。
      • 如果biHeight是负的,则DIB的像素是按照从上往下保存的(up-bottom),而且像素的数据是不能被压缩的其biCompression必须是BI_RGB或者BI_FIELDS
      • 如果biCompression是BI_JPEG或者BI_PNG,则biHeight是解压缩后JPEG或者PNG的高
    • biPlanes 目标设备的平面数,总是设为1.
    • biBitCount,每个像素所占用的位数。0,表示JPEG或者PNG指定每个像素所占用的位数。还可以是1,4,8,16,24,32。
    • biCompression,数据的压缩方法(up-down的DIB不能被压缩),可以是以下值:
      • BI_RGB / BI_FIELDS未被压缩
      • BI_RLE4 / BI_RLE8 使用游程长度编码 (RLE,run-length encode)
      • BI_JPEG / BI_PNG 指示该图像是JPEG或者PNG图像。
    • biSizeImage 图像的字节数,对于BI_RGB的DIB其值为0.
    • biXPelsPerMeter / biYPelsPerMeter 显示该DIB的目标设备所需的分辨率(单位是像素每米)
    • biClrUsed DIB实际使用调色板中的颜色个数,通常为0表示使用调色板中的全部颜色。
    • biClrImportant 显示DIB所必须的颜色个数,通常为0表示全部颜色都是必须的。

      详细的解释参见 https://msdn.microsoft.com/en-us/library/dd183376(v=vs.85).aspx

    RGBQUAD
    typedef struct tagRGBQUAD {
      BYTE rgbBlue;
      BYTE rgbGreen;
      BYTE rgbRed;
      BYTE rgbReserved;
    } RGBQUAD;

    注意,其存储顺序是BGR。

    1.3 DIB的结构实例


    是一幅宽和高都是32的位图(放大后,可以看到表示像素的一个个方块),其有16种颜色。下面是该图像的16进制数据

    • 首先是文件的头信息 BITMAPFILEINFO 共有14个字节(0x00-0x0D),其起始的两个字节为0x4d42(大端存储,高位在前)表示文件类型为BM,最后4个字节 0x0076是位图的像素信息相对于文件头的偏移量,也就是从0x0076为图像的像素信息。
    • 下面是位图的头信息 BITMAPINFOHEADER共有40个字节(0x0E-0x35),起始的4个字节是0x0028就是该结构体的大小,紧接着的4个字节是图像的宽0x0020
    • 跟着是图像的调色板,0x36 - 0x75。调色板共有16种颜色,也就是说有调色板中有16个RGBQUAD,其大小为16 * 4.
    • 最后是位图的数据 0x76-0x275

    1.4 读取

        CFile fp(dibName, CFile::modeRead | CFile::typeBinary);
        BITMAPFILEHEADER bmfileHeader;
        BITMAPINFOHEADER bmHeader;
        ULONGLONG headpos;
        int paletteSize = 0;
        int ret, cbHeaderSize;
        headpos = fp.GetPosition(); // 获取文件指针的位置
        ret = fp.Read(&bmfileHeader, sizeof(BITMAPFILEHEADER)); // 读取BMP文件头
        if (bmfileHeader.bfType != 0x4d42) //判断文件类型标头是不是x4d42,表示该文件为BMP类型文件
        {
            AfxMessageBox(_T("文件不是bmp!"));
            return;
        }
        //读取文件信息头
        ret = fp.Read(&bmHeader, sizeof(BITMAPINFOHEADER));
        // 计算RGBQUAD的大小
        switch (bmHeader.biBitCount)
        {
        case 1:
            paletteSize = 2;
            break;
        case 4:
            paletteSize = 16;
            break;
        case 8:
            paletteSize = 256;
            break;
        }
        // 为BITMAPINFO分配存储空间
        cbHeaderSize = sizeof(BITMAPINFOHEADER)+paletteSize * sizeof(RGBQUAD);
        m_dibInfo = (BITMAPINFO*) new char[cbHeaderSize];
        m_dibInfo->bmiHeader = bmHeader;
        if (paletteSize) //是否有调色板
        {
            ret = fp.Read(&(m_dibInfo->bmiColors[0]), paletteSize * sizeof(RGBQUAD));
            if (ret != int(paletteSize * sizeof(RGBQUAD) ) )
            {
                delete[] m_dibInfo;
                m_dibInfo = NULL;
                return;
            }
        }
        //为像素数组分配存储空间,大小由GetBodySize决定
        m_dibBits = (void*) new char[GetBodySize()];
        fp.Seek(headpos + bmfileHeader.bfOffBits, CFile::begin); // 将文件指针移动到DIB像素数组
        ret = fp.Read(m_dibBits, GetBodySize());
        if (ret != int(GetBodySize()))
        {
            delete[] m_dibInfo;
            delete[] m_dibBits;
            m_dibInfo = NULL;
            m_dibBits = NULL;
        }
        fp.Close();  

    知道了DIB的文件结构后,读取其到内存还是挺简单的,需要注意的是DIB的像素数组的大小。由于DIB的宽度需要时4的倍数,不是的话需要填充0将其凑成4的倍数,所以其像素数组的大小不能简单的width * height * biBitCount / 8,其中biBitCount是每个像素占用的位数。其具体的计算方法如下

    1. 首先计算一行所占用的字节数 bytesPerLine
      bytesPerLine = ((m_dibInfo->bmiHeader.biWidth * m_dibInfo->bmiHeader.biBitCount + 31) / 32 ) * 4
    2. 将bytesPerLine乘以图像的高
      bytesPerLine * m_dibInfo->bmiHeader.biHeight

    1.5 总结

    本文主要对DIB的文件结构以及其对应的内存中的结构体做了一个总结,并对一个具体的DIB16进制数据结构进行分析,最后实现了如何将一个DIB数据读取到内存中。

    一直对位图结构不是很了解,趁着在公司实习没有具体的工作安排,对DIB的结构作了个总结。至于如何将处理后的位图数据写回磁盘文件,在知道位图结构的情况下,只需要填充相应的结构字段就行了,需要注意的还是位图的宽需要是4的倍数,不是的话要用0补齐。本来想写个DEMO的但是太累,明天再说吧。

     


    如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
    posted @ 2018-09-04 13:09 史D芬周 阅读(...) 评论(...) 编辑 收藏
    展开全文
  • GDI位图和DIB位图是两种不同的Windows位图,GDI位图是MFC的CBitmap类表示的,在CBitmap类的对象中,包含了一种和Windows的GDI模块有关的Windows数据结构BITMAP,该结果是与设备有关的,应用程序可以得到GDI位图数据...
  • MFC图像处理-DIB位图之CDib类

    千次阅读 2013-07-03 09:41:05
    位图处理是图像处理中很重要的一个知识点,本章是编写一个基本的DIB位图信息处理的类CDib类,在此之前必须了解DIB位图的文件结构,建议大家先找资料学一下。  首先在你要编写CDib类的工程的ClassView中右击工程名称...
  • 【标 题】:Visual C++中DDB与DIB位图编程全攻略 【关键字】:Visual,C++,DDB,DIB 【来 源】:http://blog.csdn.net/byxdaz/archive/2006/03/10/620476.aspxVisual C++中DDB与DIB位图编程全攻略...
  • Visual C++中DDB与DIB位图编程全攻略(转) 1. 基本概念 先来用通俗的语句讲解位图和调色板的概念。  我们知道,自然界中的所有颜 色都可以由红、绿、蓝(R,G,B)三基色组合而成。针对含有红、绿、蓝色...
  • 这是用IJG的jpeg库编写的一段压缩DIB位图的程序,程序运行没问题,结果图形色彩却出现了严重的失真: jpeg_compress_struct jpeg; jpeg_error_mgr jerr; jpeg.err = jpeg_std_error(&jerr); //错误输出在...
  • Visual C++中DDB与DIB位图编程全攻略  1. 基本概念  先来用通俗的语句讲解位图和调色板的概念。  我们知道,自然界中的所有颜色都可以由红、绿、蓝(R,G,B)三基色组合而成。针对含有红、绿、蓝色...
  • 4. DIB位图编程 4.1位图文件格式 先来分析DIB位图文件的格式。位图文件分为四部分: (1)位图文件头BITMAPFILEHEADER 位图文件头BITMAPFILEHEADER是一个结构体,长度为14字节,定义为:
  • 4. DIB位图编程 4.1位图文件格式 先来分析DIB位图文件的格式。位图文件分为四部分: (1)位图文件头BITMAPFILEHEADER 位图文件头BITMAPFILEHEADER是一个结构体,长度为14字节,定义为: typedef struct ...
  • DIB位图alpha通道问题

    2016-10-08 17:56:54
    发现有渐进效果,但是只要rgb设置了任何常数字都有问题,最后查找各种资料才明白原来dib位图在gdi绘制时alpha通道要进行RGB预乘的 最后就是上面代码的效果,正弦的透明渐进效果
  • 设备无关位图(Device Independent Bitmap)是可以保存在磁盘的位图文件,可以从磁盘读取到内存或者从内存保存到磁盘上。它的文件结构是标准化的,可以在Windows/Linux/Unix等平台上...1.1 DIB文件结构 要将位图文件
  • GDI位图和DIB位图

    2009-08-04 17:02:00
    http://www.51cto.com/art/200708/54823.htm

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 983
精华内容 393
关键字:

dib位图