一、BMP图片顺时针180°镜像
1.2 编译运行过程
[wbyq@wbyq linux_c]$ gcc app.c [wbyq@wbyq linux_c]$ ls 1.bmp 1.c 2.c 666.bmp 888.bmp a.out app.c test.c [wbyq@wbyq linux_c]$ ./a.out 传入的参数格式: ./a.out <原图片的名称> <新图片的名称> [wbyq@wbyq linux_c]$ ./a.out 888.bmp 2.bmp 原图片头读取14字节. 原图片类型:BM. 原文件大小:3529754. 原文件的数据偏移量:54. 原图片参数结构读取40字节. 原图片宽:1566 原图片高:751 原图片像素位:24 新图片头成功写入:14 字节. 新图片的参数结构成功写入:40 字节.
1.3 镜像的效果
1.4 源代码
#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.w; new_bmp_info.h=src_bmp_info.h; //图片的颜色位数 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); /*7. 写入位图数据*/ int w,h; int one_line_byte=src_bmp_info.w*3; //一行的字节数 while(one_line_byte%4!=0)one_line_byte++; //补齐4的倍数 char *one_line_data=malloc(one_line_byte); for(h=src_bmp_info.h-1;h>=0;h--) { //从头开始偏移 fseek(src_fp,one_line_byte*h+54,SEEK_SET); fread(one_line_data,1,one_line_byte,src_fp); //读取图片数据 fwrite(one_line_data,1,one_line_byte,new_fp); //写数据 } /*8. 关闭文件*/ fclose(new_fp); fclose(src_fp); free(one_line_data); return 0; }
二、BMP图片顺时针180°翻转
2.2 编译运行过程
[wbyq@wbyq linux_c]$ gcc app.c [wbyq@wbyq linux_c]$ ./a.out 666.bmp 1.bmp 原图片头读取14字节. 原图片类型:BM. 原文件大小:919254. 原文件的数据偏移量:54. 原图片参数结构读取40字节. 原图片宽:800 原图片高:383 原图片像素位:24 新图片头成功写入:14 字节. 新图片的参数结构成功写入:40 字节. 需要补齐:0字节. [wbyq@wbyq linux_c]$ eog 1.bmp
2.3 翻转后的效果
2.6 代码--支持任意尺寸图片
#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.w; new_bmp_info.h=src_bmp_info.h; //图片的颜色位数 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); 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); /*7. 写入位图数据*/ int w,h; int seek=0; int c=0; for(h=src_bmp_info.h;h>=0;h--) { seek=h*one_line_byte+54; seek-=val_byte; //减去原图片的补齐数据 for(w=0;w<src_bmp_info.w;w++) { seek-=3; //从头开始偏移 fseek(src_fp,seek,SEEK_SET); fread(&c,1,3,src_fp); //读取图片数据 fwrite(&c,1,3,new_fp); //写数据 } if(val_byte)fwrite(&c,1,val_byte,new_fp); //如果需要补齐,就写补齐数据 } /*8. 关闭文件*/ fclose(new_fp); fclose(src_fp); return 0; }