C语言程序设计基础--位图缩放

位图图像文件缩放

涉及知识点:文件读写、结构体定义、内存管理、基本图像处理算法、命令行参数
要求:
编写一个程序,可以在命令行输入参数,完成指定文件的缩放,并存储到新文件,命令行参数如下
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号同邮箱

  • 4
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怡人蝶梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值