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

本文提供了一套完整的位图处理代码,包括位图的打开、保存、翻转等功能,并详细介绍了如何处理1位和24位的BMP文件。通过本文,读者可以了解到位图数据的真实存储格式以及如何实现位图的旋转和镜像。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近把位图的打开、保存、翻转代码给大家贴出来,供大家参考:
再本文中处理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 左右对称
下来我们看一下文件的打开:
voidCMFCView::OnFileOpen()
{
         char* pFilter="位图(*.bmp)|*.bmp|/0";
         CFileDialogopenFile(TRUE,"*.bmp",NULL,
                  OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,pFilter);
         if(IDOK != openFile.DoModal())
                   return;
         oPenFileOk = true ;
         CStringbitmapOpenPath = 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));
         UINTuBmpInfoLen=(UINT) bmfh.bfOffBits-sizeof(BITMAPFILEHEADER);
         bmif =(LPBITMAPINFO) newBYTE[uBmpInfoLen];
         cFile.Read((LPVOID) bmif,uBmpInfoLen);
         //读取数据
         DWORDdwBitlen=bmfh.bfSize - bmfh.bfOffBits;
         bmData = newbyte [dwBitlen];
         cFile.Read(bmData,dwBitlen);
         cFile.Close();
         HBITMAPhBitmap;
         CBitmapcBitmap;
         hBitmap = ::CreateDIBitmap(GetDC()->m_hDC,&bmih,CBM_INIT,bmData,bmif,DIB_RGB_COLORS);
         cBitmap.Attach(hBitmap);
         CDCdcMemory;
         dcMemory.CreateCompatibleDC(GetDC());
         CBitmap * cUsedBitmap = dcMemory.SelectObject(&cBitmap);
         HWNDsafeHwnd =GetSafeHwnd();
         RECTwindowRect;
         ::GetClientRect(safeHwnd,&windowRect);
         POINTpaintPoint;
         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();
 
}
文件的保存:
voidCMFCView::OnFileSave()
{
         if( !oPenFileOk )
         {
                  AfxMessageBox("Place select one BitMap!");
                   return ;
         }
         char* pFilter="位图(*.bmp)|*.bmp||";
         CFileDialogsaveFile(FALSE,"*.bmp",NULL,NULL,pFilter);
         if(IDOK != saveFile.DoModal())
                   return;
         CStringbitmapSavePath = saveFile.GetPathName();
         CFilecf;
         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 向左
voidCMFCView::Oneddy(boolbLeft)
{
         byte * bEddyData ;
         intbyteCount =bmif->bmiHeader.biBitCount/8;
         intiAddLineData = (4-(bmif->bmiHeader.biHeight*byteCount)%4)%4;
         inteddySize =(bmif->bmiHeader.biHeight*byteCount+iAddLineData)*bmif->bmiHeader.biWidth;
         bEddyData = newbyte[eddySize];
         intiBmpAddLineData = (4-bmif->bmiHeader.biWidth*byteCount%4)%4;
         //对数据进行操作
         intiImageSize = (bmif->bmiHeader.biWidth*byteCount+iBmpAddLineData)*bmif->bmiHeader.biHeight;
         intbEddyDataRowCount = bmif->bmiHeader.biHeight*byteCount+iAddLineData;
         for( inti =0;i<bmif->bmiHeader.biHeight ;i++)
         {
                   intm =0;
                   for( intj=0;j<bmif->bmiHeader.biWidth*byteCount;j+=byteCount)
                   {
                            intbmDataIndex;
                            intbEddyDataRowIndex;
                            intbEddyDataColIndex;
                            intlocIndex;
                            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;
         //删除临时信息
         deletebTemp;
         ////更改头文件信息
         bmfh.bfSize = bmfh.bfOffBits +eddySize;
         intiTemp;
         iTemp = bmif->bmiHeader.biHeight;
         bmif->bmiHeader.biHeight = bmif->bmiHeader.biWidth;
         bmif->bmiHeader.biWidth = iTemp;
         OnView();
 
}
对24位的上下,左右镜面,true 左右对称
voidCMFCView::Ontrun(boolbLeftRight)
{
         byte * bEddyData ;
         intbyteCount ;
         byteCount = bmif->bmiHeader.biBitCount/8;
         bEddyData = newbyte[bmfh.bfSize-bmfh.bfOffBits];
         intiBmpAddLineData = (4-bmif->bmiHeader.biWidth*byteCount%4)%4;
         //对数据进行操作
         intiImageSize = (bmif->bmiHeader.biWidth*byteCount+iBmpAddLineData)*bmif->bmiHeader.biHeight;
         for( inti =0;i<bmif->bmiHeader.biHeight ;i++)
         {
                   intm =0;
                   for( intj=0;j<bmif->bmiHeader.biWidth*byteCount;j+=byteCount)
                   {
                            intbmDataIndex;
                            intbEddyDataRowIndex;
                            intbEddyDataColIndex;
                            intlocIndex;
                            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;
         //删除临时信息
         deletebTemp;
         ////更改头文件信息
         OnView();
}
对1位的左右90度翻转,其中true 向左
voidCMFCView::OneddyOne(boolbLeft)
{
          
         intbmLineSizeByte=(bmif->bmiHeader.biWidth+((32 - (bmif->bmiHeader.biWidth%32)))%32)/8;
         intedyLineSizeByte = (bmif->bmiHeader.biHeight+(32 -(bmif->bmiHeader.biHeight%32))%32)/8;
         intiAddLineData = (32 -bmif->bmiHeader.biHeight%32)%32;
         inteddySize =(bmif->bmiHeader.biHeight+iAddLineData)*bmif->bmiHeader.biWidth;
         //int x= bmfh.bfSize - bmfh.bfOffBits;
         byte * bEddyData = newbyte[eddySize*bmif->bmiHeader.biWidth/8];
         for( intiSetZero = 0; iSetZero<eddySize*bmif->bmiHeader.biWidth/8; iSetZero++)
                  bEddyData[iSetZero] = 0;
         for( inti =0;i<bmif->bmiHeader.biHeight ;i++)
         {
                   for( intj=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;
         //删除临时信息
         deletebTemp;
         ////更改头文件信息
         bmfh.bfSize = bmfh.bfOffBits +eddySize/8;
         intiTemp;
         iTemp = bmif->bmiHeader.biHeight;
         bmif->bmiHeader.biHeight = bmif->bmiHeader.biWidth;
         bmif->bmiHeader.biWidth = iTemp;
         OnView();
}
对1位的上下,左右镜面,true 左右对称
voidCTest8_MFCView::OntrunOne(boolbLeftRight)
{
         intbmLineSizeByte=(bmif->bmiHeader.biWidth+(32 - (bmif->bmiHeader.biWidth%32))%32)/8;
         intx= bmfh.bfSize - bmfh.bfOffBits;
         byte * bEddyData = newbyte[bmLineSizeByte*bmif->bmiHeader.biHeight];
         if(bLeftRight)
         {
                   for( intj=0; j<bmif->bmiHeader.biHeight; j++)
                   {
                            intiToPos=0,iFromPos = bmif->bmiHeader.biWidth%8?8-bmif->bmiHeader.biWidth%8:0;
                            iToPos = 7;
                            intiByteToPos = 0;
                            intiByteFromPos = bmif->bmiHeader.biWidth%8?(bmif->bmiHeader.biWidth/8):(bmif->bmiHeader.biWidth/8-1);
                            for(inti =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( intj=0;j<bmif->bmiHeader.biHeight;j++)
                   {
                            for(inti =0;i<bmLineSizeByte ;i++ )
                            {
                                    
                                     bytex=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;
         //删除临时信息
         deletebTemp;
         OnView();
}
最后你要用到一个函数用来对指定的两个字节的木一位进行赋值,代码如下:
voidchangeBit(byte * byteTo,intiToPos,byte * byteFrom ,intiFromPos)
{
         intiToPos2 = iToPos;
         intm =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,也就是4byte来存放一行。如果你还有什么不懂,你可以留言我或是把代码发给你。
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值