一、运行环境介绍
Linux系统: Redhat6.3 (32位)
gcc 版本 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
二、功能介绍
打开一张BMP图片,实现顺时针90°旋转后生成一张新的图片。
三、核心代码
可以传入任意尺寸的BMP图片进行生成旋转。
#include <stdio.h> #include <string.h> #include <stdlib.h> #pragma pack(1) //强制1个字节对齐 //BMP的文件头 struct _BMP_HEAD { char type[2]; //图片的类型 "BM" unsigned int size; //文件大小 unsigned short r1; //保留1 unsigned short r2; //保留2 unsigned int seek; //数据偏移字节(真实像素点数据) }; //BMP的参数信息 struct _BMP_INFO { unsigned int size; //当前结构体大小 unsigned int w; //宽度 unsigned int h; //高度 unsigned short flag; //固定为1 unsigned short bit; //像素点的位数 unsigned int r1; //压缩方式 0 unsigned int r2; //水平分辨率 unsigned int r3; //垂直分辨率 unsigned int r4; //垂直分辨率 unsigned int r5; //引用色彩 unsigned int r6; //关键色彩 }; int main(int argc,char **argv) { int cnt; if(argc!=3) { printf("传入的参数格式: ./a.out <原图片的名称> <新图片的名称>\n"); return 0; } /*1. 打开原图片*/ FILE *src_fp=fopen(argv[1],"rb"); if(src_fp==NULL) { printf("%s 图片打开失败.\n",argv[1]); return 0; } /*2. 读取图片的头信息*/ struct _BMP_HEAD src_bmp_head; cnt=fread(&src_bmp_head,1,sizeof(struct _BMP_HEAD),src_fp); printf("原图片头读取%d字节.\n",cnt); printf("原图片类型:%c%c.\n",src_bmp_head.type[0],src_bmp_head.type[1]); printf("原文件大小:%d.\n",src_bmp_head.size); printf("原文件的数据偏移量:%d.\n",src_bmp_head.seek); /*3. 读取图片的参数信息*/ struct _BMP_INFO src_bmp_info; cnt=fread(&src_bmp_info,1,sizeof(struct _BMP_INFO),src_fp); printf("原图片参数结构读取%d字节.\n",cnt); printf("原图片宽:%d\n",src_bmp_info.w); printf("原图片高:%d\n",src_bmp_info.h); printf("原图片像素位:%d\n",src_bmp_info.bit); /*4. 创建一张新的BMP图片*/ FILE *new_fp=fopen(argv[2],"wb"); if(new_fp==NULL) { printf("%s 文件创建失败.\n",argv[2]); return 0; } /*5. 创建BMP的文件头*/ struct _BMP_HEAD new_bmp_head; memset(&new_bmp_head,0,sizeof(struct _BMP_HEAD)); //图片的类型 new_bmp_head.type[0]='B'; new_bmp_head.type[1]='M'; //文件大小 new_bmp_head.size=54+src_bmp_info.w*src_bmp_info.h*3; //数据偏移量 new_bmp_head.seek=54; //写文件头 cnt=fwrite(&new_bmp_head,1,sizeof(struct _BMP_HEAD),new_fp); printf("新图片头成功写入:%d 字节.\n",cnt); /*6. 写文件参数信息*/ struct _BMP_INFO new_bmp_info; memset(&new_bmp_info,0,sizeof(struct _BMP_INFO)); //当前结构体大小 new_bmp_info.size=sizeof(struct _BMP_INFO); //图片的宽度和高度 new_bmp_info.w=src_bmp_info.h; new_bmp_info.h=src_bmp_info.w; //图片的颜色位数 new_bmp_info.bit=24; //标志位 new_bmp_info.flag=1; //写入文件参数信息 cnt=fwrite(&new_bmp_info,1,sizeof(struct _BMP_INFO),new_fp); printf("新图片的参数结构成功写入:%d 字节.\n",cnt); //计算原图片宽度是否是4的倍数 int one_line_byte=src_bmp_info.w*3; while(one_line_byte%4!=0)one_line_byte++; int val_byte=one_line_byte-src_bmp_info.w*3; //相差的字节数 printf("原图片的宽度补齐%d字节.\n",val_byte); //计算新图片宽度是否是4的倍数 int new_one_line_byte=new_bmp_info.w*3; while(new_one_line_byte%4!=0)new_one_line_byte++; int new_val_byte=new_one_line_byte-new_bmp_info.w*3; //相差的字节数 printf("新图片的宽度补齐%d字节.\n",new_val_byte); /*7. 写入位图数据*/ int w,h; int seek=0; int c=0; for(w=0;w<src_bmp_info.w;w++) { for(h=src_bmp_info.h;h>0;h--) { seek=h*one_line_byte+54-one_line_byte+w*3; //从头开始偏移 fseek(src_fp,seek,SEEK_SET); fread(&c,1,3,src_fp); //读取图片数据 fwrite(&c,1,3,new_fp); //写数据 } if(new_val_byte)fwrite(&c,1,new_val_byte,new_fp); //如果需要补齐,就写补齐数据 } /*8. 关闭文件*/ fclose(new_fp); fclose(src_fp); return 0; }
四、运行效果
原图片:
旋转之后的图片: