如果前面幾個實驗都做過了的,做這個應該很簡單,今天也是看到圖像相關的文章,所以也就復習了一遍,以前也就是知道原理,沒編過,這次就都完成了吧。。下面我做的是一個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了。。。睡覺。。。悲劇的一天,全部花在了各種蛋疼的調試。
我的效果:
原圖:
旋轉後的圖: