程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> BMP圖像旋轉----C++實現

BMP圖像旋轉----C++實現

編輯:C++入門知識

如果前面幾個實驗都做過了的,做這個應該很簡單,今天也是看到圖像相關的文章,所以也就復習了一遍,以前也就是知道原理,沒編過,這次就都完成了吧。。下面我做的是一個BMP圖像旋轉的實驗。(我選的是180,相對來說比較簡單)。

我的代碼:

 #include<iostream>  
#include <Windows.h>  
 
using namespace std; 
 
 
void main() 
{ 
     
    FILE* stream=fopen("D:\\3.bmp","rb"); 
    if(stream==NULL) 
    { 
        cout<<"文件不存在"<<endl; 
        return; 
    } 
     
    int sizeFileHeader=sizeof(BITMAPFILEHEADER); 
    int sizeInfoHeader=sizeof(BITMAPINFOHEADER); 
     
    BITMAPFILEHEADER* bitmapFileHeader=new BITMAPFILEHEADER[sizeFileHeader+1]; 
     
    BITMAPINFOHEADER* bitmapInfoHeader=new BITMAPINFOHEADER[sizeInfoHeader+1]; 
     
    memset(bitmapFileHeader,0,sizeFileHeader+1); 
    memset(bitmapInfoHeader,0,sizeInfoHeader+1); 
    fread(bitmapFileHeader,sizeof(char),sizeFileHeader,stream); 
    fseek(stream,sizeFileHeader,0); 
    fread(bitmapInfoHeader,sizeof(char),sizeInfoHeader,stream); 
    int srcImageLineByteCount=(((bitmapInfoHeader->biWidth*24)+31)/32)*4; 
    fseek(stream,sizeFileHeader+sizeInfoHeader,0); 
 
    //讀取圖像數據  
    int count=srcImageLineByteCount-bitmapInfoHeader->biWidth*(bitmapInfoHeader->biBitCount/8); 
    BYTE* tempData=new BYTE[count]; 
    BYTE*** oldImageData=new BYTE**[bitmapInfoHeader->biHeight]; 
    for(int i=0;i<bitmapInfoHeader->biHeight;i++) 
    { 
        oldImageData[i]=new BYTE*[bitmapInfoHeader->biWidth]; 
        for (int j=0;j<bitmapInfoHeader->biWidth;j++) 
        { 
            oldImageData[i][j]=new BYTE[3]; 
            for(int k=0;k<3;k++) 
            { 
                fread(&oldImageData[i][j][k],sizeof(BYTE),1,stream); 
            } 
        } 
         
        for(int m=0;m<count;m++) 
        { 
            fread(&tempData[m],sizeof(BYTE),1,stream); 
        } 
    } 
     
 
    fclose(stream); 
     
    //得到數據  
     
    BYTE*** newImageData=new BYTE**[bitmapInfoHeader->biHeight]; 
     
    for(int i=0;i<bitmapInfoHeader->biHeight;i++) 
    { 
        newImageData[i]=new BYTE*[bitmapInfoHeader->biWidth]; 
        for (int j=0;j<bitmapInfoHeader->biWidth;j++) 
        { 
            newImageData[i][j]=new BYTE[3]; 
            for (int k=0;k<3;k++) 
            { 
                newImageData[i][j][k]=oldImageData[bitmapInfoHeader->biHeight-i-1][bitmapInfoHeader->biWidth-j-1][k]; 
            } 
        } 
         
    } 
 
 
    //寫數據  
    FILE* fileWrite=fopen("D:\\7.bmp","a+"); 
    fwrite(bitmapFileHeader,sizeof(char),sizeof(BITMAPFILEHEADER),fileWrite); 
    fwrite(bitmapInfoHeader,sizeof(char),sizeof(BITMAPINFOHEADER),fileWrite); 
    for(int i=0;i<bitmapInfoHeader->biHeight;i++) 
    { 
        for(int j=0;j<bitmapInfoHeader->biWidth;j++) 
        { 
            for(int k=0;k<3;k++) 
            { 
                fwrite(&newImageData[i][j][k],sizeof(BYTE),1,fileWrite); 
            } 
             
        } 
        for (int s=0;s<count;s++) 
        { 
            fwrite(&tempData[s],sizeof(BYTE),1,fileWrite); 
        } 
 
    } 
    fclose(fileWrite); 
    delete newImageData; 
    delete oldImageData; 
 
    cout<<"success"<<endl; 
} 

#include<iostream>
#include <Windows.h>

using namespace std;


void main()
{
 
 FILE* stream=fopen("D:\\3.bmp","rb");
 if(stream==NULL)
 {
  cout<<"文件不存在"<<endl;
  return;
 }
 
 int sizeFileHeader=sizeof(BITMAPFILEHEADER);
 int sizeInfoHeader=sizeof(BITMAPINFOHEADER);
 
 BITMAPFILEHEADER* bitmapFileHeader=new BITMAPFILEHEADER[sizeFileHeader+1];
 
 BITMAPINFOHEADER* bitmapInfoHeader=new BITMAPINFOHEADER[sizeInfoHeader+1];
 
 memset(bitmapFileHeader,0,sizeFileHeader+1);
 memset(bitmapInfoHeader,0,sizeInfoHeader+1);
 fread(bitmapFileHeader,sizeof(char),sizeFileHeader,stream);
 fseek(stream,sizeFileHeader,0);
 fread(bitmapInfoHeader,sizeof(char),sizeInfoHeader,stream);
 int srcImageLineByteCount=(((bitmapInfoHeader->biWidth*24)+31)/32)*4;
 fseek(stream,sizeFileHeader+sizeInfoHeader,0);

 //讀取圖像數據
 int count=srcImageLineByteCount-bitmapInfoHeader->biWidth*(bitmapInfoHeader->biBitCount/8);
 BYTE* tempData=new BYTE[count];
 BYTE*** oldImageData=new BYTE**[bitmapInfoHeader->biHeight];
 for(int i=0;i<bitmapInfoHeader->biHeight;i++)
 {
  oldImageData[i]=new BYTE*[bitmapInfoHeader->biWidth];
  for (int j=0;j<bitmapInfoHeader->biWidth;j++)
  {
   oldImageData[i][j]=new BYTE[3];
   for(int k=0;k<3;k++)
   {
    fread(&oldImageData[i][j][k],sizeof(BYTE),1,stream);
   }
  }
  
  for(int m=0;m<count;m++)
  {
   fread(&tempData[m],sizeof(BYTE),1,stream);
  }
 }
 

 fclose(stream);
 
 //得到數據
 
 BYTE*** newImageData=new BYTE**[bitmapInfoHeader->biHeight];
 
 for(int i=0;i<bitmapInfoHeader->biHeight;i++)
 {
  newImageData[i]=new BYTE*[bitmapInfoHeader->biWidth];
  for (int j=0;j<bitmapInfoHeader->biWidth;j++)
  {
   newImageData[i][j]=new BYTE[3];
   for (int k=0;k<3;k++)
   {
    newImageData[i][j][k]=oldImageData[bitmapInfoHeader->biHeight-i-1][bitmapInfoHeader->biWidth-j-1][k];
   }
  }
  
 }


 //寫數據
 FILE* fileWrite=fopen("D:\\7.bmp","a+");
 fwrite(bitmapFileHeader,sizeof(char),sizeof(BITMAPFILEHEADER),fileWrite);
 fwrite(bitmapInfoHeader,sizeof(char),sizeof(BITMAPINFOHEADER),fileWrite);
 for(int i=0;i<bitmapInfoHeader->biHeight;i++)
 {
  for(int j=0;j<bitmapInfoHeader->biWidth;j++)
  {
   for(int k=0;k<3;k++)
   {
    fwrite(&newImageData[i][j][k],sizeof(BYTE),1,fileWrite);
   }
   
  }
  for (int s=0;s<count;s++)
  {
   fwrite(&tempData[s],sizeof(BYTE),1,fileWrite);
  }

 }
 fclose(fileWrite);
 delete newImageData;
 delete oldImageData;

 cout<<"success"<<endl;
}

代碼分析:其實這裡有個很關鍵的問題:那就是內存對齊的那段內存,我們在讀取數據的時候,必須把它刪除,但是在我們向文件裡寫數據的時候,我們必須把它給補上,因為那些補齊的內存數據就是00 00 00所以我就用了一個數組把它存起來(其實在讀取文件的時候,我是通過讀取的方式填充這個數組,而不是直接給它賦值,大家從代碼中可以看出來。。我在這裡只是強調一下)。

int count=srcImageLineByteCount-bitmapInfoHeader->biWidth*(bitmapInfoHeader->biBitCount/8);
BYTE* tempData=new BYTE[count];


這裡的count是指那段補齊的內存字節多少,這裡我測試的是3,(我的寬度是407,24位)。

不懂為什麼這樣寫的參看前面幾章的內容,也可以留言。。

再說一下我保存數據的那個三維指針(也不知道是不是這樣稱呼的,暫且這樣說吧,大家都懂的。。)

BYTE*** oldImageData=new BYTE**[bitmapInfoHeader->biHeight];


BYTE*** newImageData=new BYTE**[bitmapInfoHeader->biHeight];


我的思路是:所有的數據=高度*寬度*像素所占字節數。我的是:407*360*3。我逐行遍歷,再逐像素(像素間)遍歷,然後在像素的內部遍歷。

好了,這個程序就OK了。。。睡覺。。。悲劇的一天,全部花在了各種蛋疼的調試。

我的效果:

原圖:

 

\

旋轉後的圖:

 \
 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved