原创 图像处理学习系列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;
}
/****************************************************************************
//彩色图片转换到灰度图片

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /1 下一条