程序
/**
*
* 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;
}
测试结果
