zoukankan      html  css  js  c++  java
  • BMP图像旋转----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;
    }
    


    代码分析:其实这里有个很关键的问题:那就是内存对齐的那段内存,我们在读取数据的时候,必须把它删除,但是在我们向文件里写数据的时候,我们必须把它给补上,因为那些补齐的内存数据就是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了。。。睡觉。。。悲剧的一天,全部花在了各种蛋疼的调试。

    我的效果:

    原图:

    旋转后的图:


  • 相关阅读:
    软工实践1816-第四次作业
    软工实践1816-第三次作业
    软工实践1816-第二次作业
    Alpha 冲刺 (3/10)
    Alpha 冲刺 (2/10)
    Alpha 冲刺 (1/10)
    福大软工 · 第七次作业
    福大软工 · 第八次作业(课堂实战)- 项目UML设计(团队)
    福大软工1816 · 第六次作业
    福大软工1816 · 第五次作业
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3253581.html
Copyright © 2011-2022 走看看