将BMP格式图片缩小生成另一个图片文件

news/2024/9/25 11:16:01

设计算法,要求把一张任意尺寸的 BMP 图片等比例且不失真的缩小为原来的 1/2,并生成一张新的 BMP 图片,要求 BMP 图片的路径都需要通过命令行进行传递

设计思路:

1.定义一个空间 buf存放从原图片读取的颜色分量(注意考虑BMP文件的字节补齐数量);

2.定义一个空间 half_buf存放缩小到1/2的颜色分量。我采用的是每行间隔一个颜色分量取数据;

3.将half_buf空间中的颜色分量写入颜色分量数据,同样要考虑字节补齐。

实现代码

/*** file name:BMP_reduction.c* author   : liaojx2016@126.com* date     : 2024-05-12* function : Reduce the BMP image by half to generate a new image file* note     : None* CopyRight (c)   2024  liaojx2016@126.com  Right Reseverd*
**/
#include<stdio.h>
#include <string.h>
#include<stdlib.h>
//取消字节对齐,因为需要的结构体是 14字节和 40字节大小
#pragma pack(1)
//定义图像文件头结构体
typedef struct BMP_FileHeader
{char                bfType[2];        //位图文件的类型,必须为BM int                 bfSize;           //文件大小,以字节为单位unsigned short int  bfReserverd1;     //位图文件保留字,必须为0 unsigned short int  bfReserverd2;     //位图文件保留字,必须为0 unsigned int        bfbfOffBits;      //位图文件头到数据的偏移量,以字节为单位
}BMP_FileHeader_t;
//定义图像信息头结构体
typedef  struct BMP_InfoHeader
{ unsigned int biSize;                       //该结构大小,字节为单位int  biWidth;                            //图形宽度以象素为单位int  biHeight;                            //图形高度以象素为单位unsigned short int  biPlanes;              //目标设备的级别,必须为1 unsigned short int  biBitcount;            //颜色深度,每个象素所需要的位数unsigned short int  biCompression;         //位图的压缩类型unsigned int  biSizeImage;                 //位图的大小,以字节为单位unsigned int  biXPelsPermeter;             //位图水平分辨率,每米像素数unsigned int  biYPelsPermeter;             //位图垂直分辨率,每米像素数unsigned int  biClrUsed;                   //位图实际使用的颜色表中的颜色数unsigned int  biClrImportant;              //位图显示过程中重要的颜色数
}BMP_InfoHeader_t;#pragma pack()      //开启字节对齐int main(int argc, char const *argv[])
{//判断通过命令行传入图片文件是否有效if (2 != argc){printf("import argument is invalid\n");return -1;}//打开图片文件FILE *bmp_fp = fopen(argv[1],"rb");if (NULL == bmp_fp){printf("fopen picture file error\n");return -1;}//判断是否打开成功//定义图像文件头和信息头的结构体变量BMP_FileHeader_t Fhead1,Fhead2;BMP_InfoHeader_t info_head1,info_head2;//读取图像文件头信息头的数据到结构体变量里fread(&Fhead1,1,14,bmp_fp);fread(&info_head1,1,40,bmp_fp);//输出原图像信息printf("the BMP picture size = %d;width is %d;height is %d\n",Fhead1.bfSize,info_head1.biWidth,info_head1.biHeight);//定义变量记录原图中的宽,高,字节补齐数量int prev_wight = info_head1.biWidth;int prev_height = info_head1.biHeight;int prev_add_byte = (4-(prev_wight*3)%4)%4;printf("pre_bmp add bytes = %d\n",prev_add_byte);//申请堆空间,存放原图颜色分量char *bmpbuf=(char*)malloc(prev_wight*prev_height*3);//读取原图文件的颜色分量到空间bmpbuf中for (int i = 0; i < prev_height; i++){fread(bmpbuf+3*prev_wight*i,1,prev_wight*3,bmp_fp); //读取一行的颜色分量fseek(bmp_fp,prev_add_byte,SEEK_CUR);   //图片文件的光标偏移字节补齐的数量}//关闭源图像文件fclose(bmp_fp);//将原图片文件头和信息头复制到缩小图片的结构体中memcpy(&Fhead2,&Fhead1,14);memcpy(&info_head2,&info_head1,40); //设置缩小图片的宽,高,字节补齐数量int wight = info_head2.biWidth/2;int height = info_head2.biHeight/2;int add_byte = (4-(wight*3)%4)%4;printf("bmp add bytes = %d\n",add_byte);//修改缩小图片的文件头和信息头数据Fhead2.bfSize = (wight*3+add_byte)*height + 54;info_head2.biWidth = wight;info_head2.biHeight = height;//输出缩小图片的大小,宽和高printf("the BMP picture size = %d;width is %d;height is %d\n",Fhead2.bfSize,info_head2.biWidth,info_head2.biHeight);//申请堆空间,存放缩小图片的颜色分量char *half_bmpbuf=(char*)malloc(wight*height*3);//从 bmpbuf空间中读取原图文件的颜色分量到空间half_bmpbuffor (int i = 0; i < height; i++){for (int j = 0,k=0; j < wight*3; j++,k++){half_bmpbuf[i*wight*3+j] = bmpbuf[2*i*prev_wight*3+k];  //读取一个字节数据if (k%3 ==2 ){//此时已经读取完一个颜色分量,bmpbuf的地址加3, 间隔掉一个颜色分量,做缩小的动作k+=3;}}}//打开存放缩小图片的文件,若没有,则创建FILE *half_bmp_fp = fopen("0half.bmp","wb");//将所有图片信息复制到缩小的图片文件fwrite(&Fhead2,1,14,half_bmp_fp);       //写入文件头数据fwrite(&info_head2,1,40,half_bmp_fp);   //写入信息头数据//写入颜色分量数据for (int i = 0; i < height; i++){//从halfbuf空间总读取一行颜色分量数据到缩小图片文件fwrite(half_bmpbuf+wight*3*i,1,wight*3,half_bmp_fp);    //考虑BMP图像文件字节补齐,做光标偏移,由于我用malloc申请的是堆空间,存储单元初值为0, 所以不需要额外复制fseek(half_bmp_fp,add_byte,SEEK_CUR);   }//释放堆内存free(bmpbuf);free(half_bmpbuf);//关闭缩小图像文件fclose(half_bmp_fp);return 0;
}

测试结果

image

缩小后

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/30770.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

shell脚本编程

目录一、什么是shell1、简介2、常见的shell3、查看当前正在使用的shell二、shell脚本注意事项1、Shebang行2、注释3、缩进4、日志与回显三、如何执行shell脚本1、source2、bash/sh/zsh3、./四、shell变量1、系统变量2、自定义变量2.1、变量定义的规则2.2、定义变量2.3、赋值时使…

软件设计师:信息安全

防火墙内网———DMZ隔离区(非军事化区)——外网 通常把Web服务器放在DMZ中 包过滤防火墙(网络层和数据链路层之间)对用户完全透明,速度快 不能防范黑客攻击 应用代理网关防火墙(应用层)彻底隔断内网与外网直接通信 难以配置,处理速度慢 状态检测技术防火墙 目前没考过病毒网…

Scurm冲刺第七天

Scurm冲刺第七天 1. 站立式会议内容昨日已完成任务 今日计划完成任务学习 前后端接口设计与交互实现,前端界面合理跳转功能实现 的相关知识 前后端接口设计与交互实现,前端界面合理跳转功能实现研讨 前端UI设计代码编写(基于用户界面对管理员界面的设计)的解决方法 前端UI设…

CentOS7离线部署JDK

一、 下载JDK 官网地址: https://www.oracle.com/java/technologies/downloads/#java18二、安装部署点击查看代码 ## 创建存放的文件夹 [root@localhost /]# cd / [root@localhost /]# mkdir data [root@localhost /]# cd /data [root@localhost data]# mkdir java## 解压,安…

项目冲刺day5

这个作业属于哪个课程 软工4班这个作业要求在哪里 作业要求1.会议1. 照片2. 昨日已完成: 完成商品管理、图标功能,部分完成文件修改上传功能3.今天计划完成的工作 商品分类,购物车功能。2.燃尽图3.每人的代码签入记录4.适当的项目程序截图5.每日总结 明天继续努力!

Adding Drivers into VMWare ESXi Installation Image

The standard ESXi ISO image doesn’t support most desktop NIC adapters. To install ESXi on such a computer, you will need to inject the drivers for your network adapter into your ESXi installation image Let’s see how to add the driver to the VMware ESXi 6…

如何批量导出地图上商家店铺资料到手机电脑excel表格

搜索打开小程序:小胖汇客。在搜索框中输入商家店铺的关键词。在搜索结果中找到目标商家店铺,在详情页面中,你可以查看商家的地址、电话、营业时间等信息。选中需要下载的商家,一键导出到excel表格

Scrum冲刺6--5.12

Scrum冲刺6--5.12这个作业属于哪个课程 软件工程这个作业要求在哪里 团队项目这个作业的目标 进行敏捷冲刺,熟悉团队合作开发前端仓库 前端后端仓库 后端每次冲刺日志索引时间 博客5.7 Day1ᕙ(`▿)ᕗ5.8 Day2ᕙ(• ॒ ູ•)ᕘ5.9 Day3(˚ ˃̣̣̥᷄⌓˂̣̣̥᷅ )5.10 Day4 (…