bmp文件MFC中翻转、保存和解析代码

最近把位图的打开、保存、翻转代码给大家贴出来,供大家参考:
再本文中处理1位和24位bmp文件,其他的可以自行研究、、、
首先,你要做好准备工作,在View类中设置好对应的变量和函数:
private:     CFile cFile;                     //文件打开
              BITMAPINFOHEADER bmih;      //位图信息头
              BITMAPFILEHEADER bmfh;      //位图文件头
              LPBITMAPINFO bmif;                //位图信息,其中包括位图信息头和色彩信息(主要针对有调色板的Bmp,如24位真彩没有色彩信息,即位图信息就等于位图信息头)如果你对这位图方面的东西海不是很了解的话可以看我的MFC中DDB (DEVICE-DEPENDENT BITMAP)详解
              byte * bmData;                             //用来存放位图像素数据的数组指针。
              void OnView();                           //用来显示调用
              void Oneddy(bool bLeft);           //对24位的左右90度翻转,其中true 向左
              void Ontrun(bool bLeftRight);    //对24位的上下,左右镜面,true 左右对称
              void OneddyOne(bool bLeft);           //对1位的左右90度翻转,其中true 向左
              void OntrunOne(bool bLeftRight); //对1位的上下,左右镜面,true 左右对称
下来我们看一下文件的打开:
void CMFCView :: OnFileOpen ()
{
         char * pFilter =" 位图 (*.bmp)|*.bmp|/0";
         CFileDialog openFile ( TRUE ,"*.bmp", NULL ,
                  OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT , pFilter );
         if ( IDOK != openFile . DoModal ())
                   return ;
         oPenFileOk = true ;
         CString bitmapOpenPath = openFile . GetPathName ();
         oPenFileOk = true ;
         cFile . Open ( bitmapOpenPath , CFile :: modeRead );
         cFile . SeekToBegin ();
         // 读取文件头
         cFile . Read (& bmfh , sizeof ( bmfh ));
         // 读取文件信息头
         cFile . Read (& bmih , sizeof ( bmih ));
         // 读取文件信息
         cFile . SeekToBegin (); // 返回到文件开始位置
         cFile . Read (& bmfh , sizeof ( bmfh ));
         UINT uBmpInfoLen =( UINT ) bmfh . bfOffBits - sizeof ( BITMAPFILEHEADER );
         bmif =( LPBITMAPINFO ) new BYTE [ uBmpInfoLen ];
         cFile . Read (( LPVOID ) bmif , uBmpInfoLen );
         // 读取数据
         DWORD dwBitlen = bmfh . bfSize - bmfh . bfOffBits ;
         bmData = new byte [ dwBitlen ];
         cFile . Read ( bmData , dwBitlen );
         cFile . Close ();
         HBITMAP hBitmap ;
         CBitmap cBitmap ;
         hBitmap = :: CreateDIBitmap ( GetDC ()-> m_hDC ,& bmih , CBM_INIT , bmData , bmif , DIB_RGB_COLORS );
         cBitmap . Attach ( hBitmap );
         CDC dcMemory ;
         dcMemory . CreateCompatibleDC ( GetDC ());
         CBitmap * cUsedBitmap = dcMemory . SelectObject (& cBitmap );
         HWND safeHwnd = GetSafeHwnd ();
         RECT windowRect ;
         :: GetClientRect ( safeHwnd ,& windowRect );
         POINT paintPoint ;
         paintPoint . x = ( windowRect . right - bmif -> bmiHeader . biWidth )/2;
         paintPoint . y = ( windowRect . bottom - bmif -> bmiHeader . biHeight )/2;
         GetDC ()-> BitBlt ( paintPoint . x , paintPoint . y , bmif -> bmiHeader . biWidth , bmif -> bmiHeader . biHeight ,& dcMemory ,0,0, SRCCOPY );
         dcMemory . SelectObject ( cUsedBitmap );
         cBitmap . Detach ();
 
}
文件的保存:
void CMFCView :: OnFileSave ()
{
         if ( ! oPenFileOk )
         {
                  AfxMessageBox ("Place select one BitMap!");
                   return ;
         }
         char * pFilter =" 位图 (*.bmp)|*.bmp||";
         CFileDialog saveFile ( FALSE ,"*.bmp", NULL , NULL , pFilter );
         if ( IDOK != saveFile . DoModal ())
                   return ;
         CString bitmapSavePath = saveFile . GetPathName ();
         CFile cf ;
         cf . Open ( bitmapSavePath , CFile :: modeCreate | CFile :: modeReadWrite );
         cf . Write (& bmfh , sizeof ( bmfh ));
         if ( bmih . biBitCount ==1) // 判断是否为一位,来去定是否要写调色板信息
                  cf . Write ( bmif ,( UINT ) bmfh . bfOffBits - sizeof ( BITMAPFILEHEADER ));
         else
                  cf . Write (& bmif -> bmiHeader ,( UINT ) bmfh . bfOffBits - sizeof ( BITMAPFILEHEADER ));
         cf . Write ( bmData , bmfh . bfSize - bmfh . bfOffBits );
         cf . Close ();
}
对24 位的左右90 度翻转,其中true 向左
void CMFCView :: Oneddy ( bool bLeft )
{
         byte * bEddyData ;
         int byteCount = bmif -> bmiHeader . biBitCount /8;
         int iAddLineData = (4-( bmif -> bmiHeader . biHeight * byteCount )%4)%4;
         int eddySize =( bmif -> bmiHeader . biHeight * byteCount + iAddLineData )* bmif -> bmiHeader . biWidth ;
         bEddyData = new byte [ eddySize ];
         int iBmpAddLineData = (4- bmif -> bmiHeader . biWidth * byteCount %4)%4;
         // 对数据进行操作
         int iImageSize = ( bmif -> bmiHeader . biWidth * byteCount + iBmpAddLineData )* bmif -> bmiHeader . biHeight ;
         int bEddyDataRowCount = bmif -> bmiHeader . biHeight * byteCount + iAddLineData ;
         for ( int i =0; i < bmif -> bmiHeader . biHeight ; i ++)
         {
                   int m =0;
                   for ( int j =0; j < bmif -> bmiHeader . biWidth * byteCount ; j += byteCount )
                   {
                            int bmDataIndex ;
                            int bEddyDataRowIndex ;
                            int bEddyDataColIndex ;
                            int locIndex ;
                            if ( bLeft )
                            {
                                     bmDataIndex = ( bmif -> bmiHeader . biWidth * byteCount + iBmpAddLineData )* i ;
                                     bEddyDataRowIndex =         ( bmif -> bmiHeader . biWidth -1-( m ))*( bmif -> bmiHeader . biHeight * byteCount + iAddLineData );
                                     bEddyDataColIndex = i * byteCount ;
                                     locIndex = bEddyDataRowIndex + bEddyDataColIndex ;
                            }
                            else
                            {
                                     bmDataIndex = ( bmif -> bmiHeader . biWidth * byteCount + iBmpAddLineData )* i ;
                                     bEddyDataRowIndex =         m *( bmif -> bmiHeader . biHeight * byteCount + iAddLineData );
                                     bEddyDataColIndex = ( bmif -> bmiHeader . biHeight -1- i )* byteCount ;
                                     locIndex = bEddyDataRowIndex + bEddyDataColIndex ;
                                    
                            }
                            bEddyData [ locIndex ] = bmData [ j + bmDataIndex ];               //B
                            bEddyData [ locIndex +1] = bmData [ j + bmDataIndex +1];  //G
                            bEddyData [ locIndex +2] = bmData [ j + bmDataIndex +2];  //R
                            m ++;
 
                   }
         }
         byte * bTemp = bmData ;
         bmData = bEddyData ;
         // 删除临时信息
         delete bTemp ;
         更改头文件信息
         bmfh . bfSize = bmfh . bfOffBits + eddySize ;
         int iTemp ;
         iTemp = bmif -> bmiHeader . biHeight ;
         bmif -> bmiHeader . biHeight = bmif -> bmiHeader . biWidth ;
         bmif -> bmiHeader . biWidth = iTemp ;
         OnView ();
 
}
对24 位的上下,左右镜面,true 左右对称
void CMFCView :: Ontrun ( bool bLeftRight )
{
         byte * bEddyData ;
         int byteCount ;
         byteCount = bmif -> bmiHeader . biBitCount /8;
         bEddyData = new byte [ bmfh . bfSize - bmfh . bfOffBits ];
         int iBmpAddLineData = (4- bmif -> bmiHeader . biWidth * byteCount %4)%4;
         // 对数据进行操作
         int iImageSize = ( bmif -> bmiHeader . biWidth * byteCount + iBmpAddLineData )* bmif -> bmiHeader . biHeight ;
         for ( int i =0; i < bmif -> bmiHeader . biHeight ; i ++)
         {
                   int m =0;
                   for ( int j =0; j < bmif -> bmiHeader . biWidth * byteCount ; j += byteCount )
                   {
                            int bmDataIndex ;
                            int bEddyDataRowIndex ;
                            int bEddyDataColIndex ;
                            int locIndex ;
                            if ( bLeftRight )
                            {
                                     bmDataIndex = ( bmif -> bmiHeader . biWidth * byteCount + iBmpAddLineData )* i ;
                                     bEddyDataRowIndex =         i *(( bmfh . bfSize - bmfh . bfOffBits )/ bmif -> bmiHeader . biHeight );
                                     bEddyDataColIndex = ( bmif -> bmiHeader . biWidth -1- m )* byteCount ;
                                     locIndex = bEddyDataRowIndex + bEddyDataColIndex ;
                            }
                            else
                            {
                                     bmDataIndex = ( bmif -> bmiHeader . biWidth * byteCount + iBmpAddLineData )* i ;
                                     bEddyDataRowIndex =         ( bmif -> bmiHeader . biHeight -1- i )*(( bmfh . bfSize - bmfh . bfOffBits )/ bmif -> bmiHeader . biHeight );
                                     bEddyDataColIndex = ( m )* byteCount ;
                                     locIndex = bEddyDataRowIndex + bEddyDataColIndex ;
                            }
                            bEddyData [ locIndex ] = bmData [ j + bmDataIndex ];               //B
                            bEddyData [ locIndex +1] = bmData [ j + bmDataIndex +1];  //G
                            bEddyData [ locIndex +2] = bmData [ j + bmDataIndex +2];  //R
                            m ++;
                   }
         }
         byte * bTemp = bmData ;
         bmData = bEddyData ;
         // 删除临时信息
         delete bTemp ;
         更改头文件信息
         OnView ();
}
对1 位的左右90 度翻转,其中true 向左
void CMFCView :: OneddyOne ( bool bLeft )
{
          
         int bmLineSizeByte =( bmif -> bmiHeader . biWidth +((32 - ( bmif -> bmiHeader . biWidth %32)))%32)/8;
         int edyLineSizeByte = ( bmif -> bmiHeader . biHeight +(32 -( bmif -> bmiHeader . biHeight %32))%32)/8;
         int iAddLineData = (32 - bmif -> bmiHeader . biHeight %32)%32;
         int eddySize =( bmif -> bmiHeader . biHeight + iAddLineData )* bmif -> bmiHeader . biWidth ;
         //int x= bmfh.bfSize - bmfh.bfOffBits;
         byte * bEddyData = new byte [ eddySize * bmif -> bmiHeader . biWidth /8];
         for ( int iSetZero = 0; iSetZero < eddySize * bmif -> bmiHeader . biWidth /8; iSetZero ++)
                  bEddyData [ iSetZero ] = 0;
         for ( int i =0; i < bmif -> bmiHeader . biHeight ; i ++)
         {
                   for ( int j =0; j < bmif -> bmiHeader . biWidth ; j ++)
                   {
                           
                            if ( bLeft )
                            {
                                     changeBit (& bEddyData [( bmif -> bmiHeader . biWidth - j -1)* edyLineSizeByte + i /8],7- i %8,& bmData [ i * bmLineSizeByte + j /8],7- j %8);
                            }
                            else
                            {
                                     changeBit (& bEddyData [ j * edyLineSizeByte +( bmif -> bmiHeader . biHeight -1- i )/8],7-( bmif -> bmiHeader . biHeight -1- i )%8,& bmData [ i * bmLineSizeByte + j /8],7- j %8);
                            }
                   }
         }
         byte * bTemp = bmData ;
         bmData = bEddyData ;
         // 删除临时信息
         delete bTemp ;
         更改头文件信息
         bmfh . bfSize = bmfh . bfOffBits + eddySize /8;
         int iTemp ;
         iTemp = bmif -> bmiHeader . biHeight ;
         bmif -> bmiHeader . biHeight = bmif -> bmiHeader . biWidth ;
         bmif -> bmiHeader . biWidth = iTemp ;
         OnView ();
}
对1 位的上下,左右镜面,true 左右对称
void CTest8_MFCView :: OntrunOne ( bool bLeftRight )
{
         int bmLineSizeByte =( bmif -> bmiHeader . biWidth +(32 - ( bmif -> bmiHeader . biWidth %32))%32)/8;
         int x = bmfh . bfSize - bmfh . bfOffBits ;
         byte * bEddyData = new byte [ bmLineSizeByte * bmif -> bmiHeader . biHeight ];
         if ( bLeftRight )
         {
                   for ( int j =0; j < bmif -> bmiHeader . biHeight ; j ++)
                   {
                            int iToPos =0, iFromPos = bmif -> bmiHeader . biWidth %8?8- bmif -> bmiHeader . biWidth %8:0;
                            iToPos = 7;
                            int iByteToPos = 0;
                            int iByteFromPos = bmif -> bmiHeader . biWidth %8?( bmif -> bmiHeader . biWidth /8):( bmif -> bmiHeader . biWidth /8-1);
                            for ( int i =0; i < bmif -> bmiHeader . biWidth ; i ++ )
                            {
                                     if ( iToPos ==7 )
                                     {
                                              bEddyData [ bmLineSizeByte * j + iByteToPos ] = 0;
                                     }
                                     changeBit ( & bEddyData [ bmLineSizeByte * j + iByteToPos ], iToPos ,& bmData [ bmLineSizeByte * j + iByteFromPos ], iFromPos );
                                     iToPos --;
                                     iFromPos ++;                           
                                     if ( iToPos == -1 )
                                     {
                                              iToPos =7;
                                              iByteToPos ++;
                                     }
                                     if ( iFromPos == 8 )
                                     {
                                              iFromPos = 0;
                                              iByteFromPos --;
                                     }
                            }
                   }
         }
         else
         {
                   for ( int j =0; j < bmif -> bmiHeader . biHeight ; j ++)
                   {
                            for ( int i =0; i < bmLineSizeByte ; i ++ )
                            {
                                    
                                     byte x =0;
                                     bEddyData [( bmif -> bmiHeader . biHeight -1- j )* bmLineSizeByte + i ]&= x ;
                                     bEddyData [( bmif -> bmiHeader . biHeight -1- j )* bmLineSizeByte + i ]|= bmData [ j * bmLineSizeByte + i ];
                            }
                   }
         }
         byte * bTemp = bmData ;
         bmData = bEddyData ;
         // 删除临时信息
         delete bTemp ;
         OnView ();
}
最后你要用到一个函数用来对指定的两个字节的木一位进行赋值,代码如下:
void changeBit ( byte * byteTo , int iToPos , byte * byteFrom , int iFromPos )
{
         int iToPos2 = iToPos ;
         int m =1;
         m = m << iFromPos ;
         m = m &(* byteFrom );
         if ( iToPos > iFromPos )
         {
                   m = m <<( iToPos2 - iFromPos );
         }
         else
         {
                   m = m >>( iFromPos - iToPos2 );
         }
         * byteTo = (* byteTo )| m ;
}
在过程中你要明白位图的数据真正的存放格式,比如数据首先保存的是位图最下放数据的最右边的像素,然后向左到头 -> 向上 -> 向左到头 -> 向上、、、
还要明白每一行数据都必须有 32 位,不足的要补足 32 位,哪怕是一位图像长只有一个像素点,那么它也要占用 32bit ,也就是 4 byte 来存放一行。如果你还有什么不懂,你可以留言我或是把代码发给你。
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
MFC是微软的一种图形用户界面编程框架,用于开发Windows应用程序。下面是打开和保存一幅BMP图片的编程流程: 打开图片: 1. 创建一个CFileDialog对象,设置其属性为打开文件对话框,指定文件类型为BMP图片。 2. 调用CFileDialog对象的DoModal()方法显示文件对话框并等待用户选择文件。 3. 如果用户选择了文件并点击了打开按钮,可以通过调用CFileDialog对象的GetPathName()方法获取选择的文件路径。 4. 创建一个CImage对象,调用其Load()方法并传入文件路径,即可将图片加载到内存保存图片: 1. 创建一个CFileDialog对象,设置其属性为保存文件对话框,指定文件类型为BMP图片。 2. 调用CFileDialog对象的DoModal()方法显示文件对话框并等待用户选择保存路径。 3. 如果用户选择了保存路径并点击了保存按钮,可以通过调用CFileDialog对象的GetPathName()方法获取保存文件路径。 4. 创建一个CImage对象,调用其Save()方法并传入保存路径,即可将图片保存到指定路径。 以上是基本的流程,具体的代码实现可以参考以下示例: 打开图片的示例代码: ```cpp CFileDialog fileDlg(TRUE, _T("bmp"), NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, _T("BMP Files(*.bmp)|*.bmp||"), NULL); if (fileDlg.DoModal() == IDOK) { CString filePath = fileDlg.GetPathName(); CImage image; image.Load(filePath); } ``` 保存图片的示例代码: ```cpp CFileDialog fileDlg(FALSE, _T("bmp"), NULL, OFN_OVERWRITEPROMPT, _T("BMP Files(*.bmp)|*.bmp||"), NULL); if (fileDlg.DoModal() == IDOK) { CString filePath = fileDlg.GetPathName(); // 假设有一个名为image的CImage对象保存了待保存的图片 image.Save(filePath); } ``` 以上示例代码仅供参考,具体的实现需要根据具体需求和业务逻辑进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值