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
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值