位图图像文件缩放
涉及知识点:文件读写、结构体定义、内存管理、基本图像处理算法、命令行参数
要求:
编写一个程序,可以在命令行输入参数,完成指定文件的缩放,并存储到新文件,命令行参数如下
zoom file1.bmp 200 file2.bmp
第一个参数为可执行程序名称,第二个参数为原始图像文件名,第三个参数为缩放比例(百分比),第四个参数为新文件名
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int change_photo(const char *Old, float multiple, const char *New); //图片缩放函数
int main( int argc, char *argv[]) { //命令行参数
float multiple = 0; //用浮点数表示缩放倍数
multiple = ((float)atoi(argv[2])) / 100.0;
change_photo(argv[1], multiple, argv[3]);
}
int change_photo(const char *Old, float multiple, const char *New) { //图片缩放函数
//定义原照片信息结构体,这些结构体来自windows.h
BITMAPFILEHEADER hmp_head;//文件头
BITMAPINFOHEADER hmp_info;//信息头
FILE *fpr1 = fopen(Old, "rb");
FILE *fpw2 = fopen(New, "r+b"); //建立文件指针
if (fpr1 == NULL || fpw2 == NULL) { //错误提示
printf("图片打开失败!\n");
return -2;
}
fread(&hmp_head, sizeof(BITMAPFILEHEADER), 1, fpr1);
fread(&hmp_info, sizeof(BITMAPINFOHEADER), 1, fpr1); //读取原照片的头信息
unsigned int old_width = hmp_info.biWidth; //获取原图片的宽
unsigned int old_height = hmp_info.biHeight; //获取原图片的高
unsigned char *old_data = (unsigned char *)malloc(old_width * old_height * 3); //分配内存
fseek(fpr1, 54, SEEK_SET); //随机定位,以字节数为1开始定位,后54位(前54为头文件)
fread(old_data, old_width * old_height * 3, 1, fpr1 ); //获取原图片的位图数据
unsigned int new_width = (int)(multiple * old_width);
unsigned int new_height = (int)(multiple * old_height); //修改新的照片的宽高
printf("原图片的宽:%d\n新图片的宽:%d\n", old_width, new_width);
printf("原图片的高:%d\n新图片的高:%d\n", old_height, new_height); //打印出原、新图片的宽、高信息
hmp_head.bfSize = new_width * new_height * 3 +
54; //24位图每一个点存放三个字节颜色数据 ,位图文件从第55个字节开始存放位图数据因此加上54.
hmp_info.biWidth = new_width;
hmp_info.biHeight = new_height; //对头信息进行修改
fwrite(&hmp_head, sizeof(BITMAPFILEHEADER), 1, fpw2);
fwrite(&hmp_info, sizeof(BITMAPINFOHEADER), 1, fpw2); //将修改过的头信息写进新照片
int i = 0, j = 0, oldx, oldy;
unsigned char *new_date_place, *old_date_place;
unsigned char *new_data = (unsigned char *)malloc(new_width * new_height * 3); //分配内存
for (i = 0; i < new_height; i++) { //在这个for循环中进行新旧图片位图数据的传递
oldy = (int)(i / multiple);
new_date_place = new_data + i * new_width * 3;//bmp位图数据服从从左下角到右上角,且先从左到右,后从下到上。
old_date_place = old_data + oldy * old_width * 3;
//外部循环确定行位置
for (j = 0; j < new_width; j++) {
oldx = (int)(j / multiple);
memcpy(new_date_place + j * 3, old_date_place + oldx * 3, 3); //确定列位置,并进行数据传递
}
}
fseek(fpw2, 54, SEEK_SET); //随机定位,以字节数为1开始定位,后54位
fwrite(new_data, new_width * new_height * 3, 1, fpw2);
printf("finish!\n");
free(new_data);
free(old_data);//释放空间
fclose(fpr1);
fclose(fpw2);//关闭文件
return 0;
}
这里附赠一张.bmp图片,有需自取
ps:如有错误敬请指正,欢迎评论区交流或者发私信
邮箱1654407501@qq.com,QQ号同邮箱