bmp图片尺寸自由修改

程序

/**
 *
 *   file name:bmp图片尺寸自由修改
 *   author   :eon4051@163.com
 *   date     :2024/05/14
 *   brief    :修改bmp图片大小
 *   note     :None
 *
 *   CopyRight (c) 2024    eon4051@163.com    All Right Reseverd
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#pragma pack(1) /* 必须在结构体定义之前使用,这是为了让结构体中各成员按1字节对齐*/
typedef struct tagBITMAPFILEHEADER
{
	unsigned short bfType;		// 保存图片类型。 'BM'
	unsigned long bfSize;		// 位图文件的大小,以字节为单位(3-6字节,低位在前)
	unsigned short bfReserved1; // 位图文件保留字,必须为0(7-8字节)
	unsigned short bfReserved2; // 位图文件保留字,必须为0(9-10字节)
	unsigned long bfOffBits;	// RGB数据偏移地址,位图数据的起始位置,以相对于位图(11-14字节,低位在前)
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER
{
	unsigned long biSize;	   // 本结构所占用字节数(15-18字节)
	unsigned long biWidth;	   // 位图的宽度,以像素为单位(19-22字节)
	unsigned long biHeight;	   // 位图的高度,以像素为单位(23-26字节)
	unsigned short biPlanes;   // 目标设备的级别,必须为1(27-28字节)
	unsigned short biBitCount; // 每个像素所需的位数,必须是1(双色)(29-30字节),4(16色),8(256色)16(高彩色)或24(真彩色)之一

	unsigned long biCompression; // 位图压缩类型,必须是0(不压缩),(31-34字节)
	// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一

	unsigned long biSizeImage; // 位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节)

	unsigned long biXPelsPerMeter; // 位图水平分辨率,每米像素数(39-42字节)
	unsigned long biYPelsPerMeter; // 位图垂直分辨率,每米像素数(43-46字节)
	unsigned long biClrUsed;	   // 位图实际使用的颜色表中的颜色数(47-50字节)
	unsigned long biClrImportant;  // 位图显示过程中重要的颜色数(51-54字节)
} BITMAPINFOHEADER;
#pragma pack()// 取消字节对齐

 /**
 *
 *   func name     :Bmp_Bigger_And_Smaller
 *   brief         :将任意bmp图片的大小重新设置大小生成新的bmp图片
 *   func parameter:
 *                  @path:对应图像文件的路径
 *   return        :None
 *   note          :None
 *   func author   :eon4051@163.com
 *   date          :2024/05/14
 *   version       :V1.1
 */
void Bmp_Bigger_And_Smaller(char *path)
{
	FILE *fpr1 = fopen(path, "rb");
	FILE *fpw2 = fopen("new.bmp", "wb");
	if (fpr1 == NULL || fpw2 == NULL)
	{
		printf("图片打开失败!\n");
		return;
	}
	// 读取原照片的头信息
	struct tagBITMAPFILEHEADER head;
	struct tagBITMAPINFOHEADER info;

	fread(&head, sizeof(BITMAPFILEHEADER), 1, fpr1);
	fread(&info, sizeof(BITMAPINFOHEADER), 1, fpr1);

	unsigned int old_width = info.biWidth;	   // 获取原图片的宽
	unsigned int old_height = info.biHeight;   // 获取原图片的高
	int old_ret = (4 - old_width * 3 % 4) % 4; // 原图片的字节补齐
	// 获取原图片的位图数据
	unsigned char *src_data = malloc(old_width * old_height * 3 + old_ret * old_height);
	fseek(fpr1, 54, SEEK_SET);
	fread(src_data, old_width * old_height * 3 + old_ret * old_height, 1, fpr1);

	printf("原图片的宽:%d\n", old_width);
	printf("原图片的高:%d\n", old_height);
	// printf("原图片的位图文件大小:%d\n", head.bfSize);//测试用
	// printf("原图片的位图大小:%d\n", info.biSizeImage);//测试用
	// 修改原照片的宽高
	unsigned int new_Width, new_Height;
	printf("请输入新图片的宽:\n");
	scanf("%d", &new_Width);
	printf("请输入新图片的高:\n");
	scanf("%d", &new_Height);

	int ret = (4 - new_Width * 3 % 4) % 4;
	head.bfSize = new_Width * new_Height * 3 + 54 + ret * new_Height;
	info.biSizeImage = new_Width * new_Height * 3 + ret * new_Height;
	info.biWidth = new_Width;
	info.biHeight = new_Height;

	// printf("新图片的字节对齐:%d\n", ret);//测试用
	// printf("新图片的宽:%d\n", info.biWidth);//测试用
	// printf("新图片的高:%d\n", info.biHeight);//测试用
	// printf("新图片的位图文件大小:%d\n", head.bfSize);//测试用
	// printf("新图片的位图大小:%d\n", info.biSizeImage);//测试用
	// 将修改过的头信息写进新照片
	fwrite(&head, sizeof(BITMAPFILEHEADER), 1, fpw2);
	fwrite(&info, sizeof(BITMAPINFOHEADER), 1, fpw2);

	int i = 0, j = 0;
	unsigned long dwsrcX, dwsrcY;														 // 新bmp像素点对应的原bmp像素点位置
	unsigned char *pucDest;																 // 新bmp行数对印的起始像素点
	unsigned char *pucSrc;																 // 原bmp像素点
	unsigned char *dest_data = calloc(1, new_Width * new_Height * 3 + ret * new_Height); // 新bmp像素空间大小
	for (i = 0; i < new_Height; i++)
	{
		dwsrcY = i * old_height / new_Height;
		pucDest = dest_data + i * new_Width * 3 + ret * i;
		pucSrc = src_data + dwsrcY * old_width * 3 + old_ret * dwsrcY;

		for (j = 0; j < new_Width + ret; j++)
		{
			dwsrcX = j * old_width / new_Width;
			memcpy(pucDest + j * 3, pucSrc + dwsrcX * 3, 3); // 数据拷贝
		}
	}
	fseek(fpw2, 54, SEEK_SET);
	fwrite(dest_data, new_Width * new_Height * 3 + ret * new_Height, 1, fpw2);
	printf("生成新图片成功!\n");

	// 释放堆空间
	free(dest_data);
	free(src_data);

	// 关闭文件
	fclose(fpr1);
	fclose(fpw2);
}

 /**
 *
 *   func name     :main
 *   brief         :测试Bmp_Bigger_And_Smaller函数
 *   func parameter:
 *                  @argc:命令行传入的字符串数量
 *					@argv:存储传入的字符串
 *   return        :None
 *   note          :None
 *   func author   :eon4051@163.com
 *   date          :2024/05/14
 *   version       :V1.0
 */
int main(int argc, char const *argv[])
{
	Bmp_Bigger_And_Smaller(argv[1]);
	return 0;
}

测试结果

image

posted @   藍桉未遇釋槐鳥  阅读(65)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示