自定义bmp图像缩放及在lcd显示屏任意位置显示

news/2024/9/23 11:21:48

在LCD上任意位置显示一张任意大小并且宽高变为原来1/n大小的色深为 24bit的bmp图片

头文件

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <strings.h>

从此处开始以1字节对齐

#pragma pack(1) // 结构体以1字节对齐

自定义BMP文件头部结构,方便后续获取或创建bmp图片使用

typedef struct
{unsigned short bfType;unsigned int bfSize;unsigned short bfReserved1;unsigned short bfReserved2;unsigned int bfOffBits;
} BITMAPFILEHEADER;typedef struct
{unsigned int biSize;int biWidth;  // 宽int biHeight; // 高unsigned short biPlanes;unsigned short biBitCount; // 色深unsigned int biCompression;unsigned int biSizeImage;int biXPelsPerMeter;int biYPelsPerMeter;unsigned int biClrUsed;unsigned int biClrImportant;
} BITMAPINFOHEADER;

在此处取消字节对齐

#pragma pack()

调用此函数,可以将bmp图片正常缩放2及4的倍数倍(未进行字节对齐操作,后续补齐)
传入的参数分别通过命令行及运行时的标准输入传入,

/*********************************************************************	函数名称:	Scalinbmp*	函数功能:   在LCD上任意位置显示一张任意大小并且宽高变为原来1/n大小的色深为 24bit的bmp图片*	函数参数:*				@name 	bmp图像文件名*				@x		图像显示的起点x轴坐标*				@y		图像显示的起点y轴左边*				@n		想要缩放的倍数*	返回结果:* 	注意事项:   None* 	函数作者:   mailLinL@163.com*	创建日期:   2024/05/14*	修改历史:*	函数版本:	V1.0* *****************************************************************/
int Scalinbmp(char *name, int x, int y, int n)
{// 1.打开bmp文件,获取文件头信息,图像大小,图像宽,高,位深度等可用信息FILE *bmp_src = fopen(name, "rb");if (NULL == bmp_src){printf("open SRCFILE is error!\n");return -1;}BITMAPFILEHEADER src_head;BITMAPINFOHEADER src_vinfo;fread(&src_head, 1, 14, bmp_src);  // 读取bmp图像的文件头段	获取文件大小 以字节为单位fread(&src_vinfo, 1, 40, bmp_src); // 读取bmp图像的信息头段	获取文件宽,高 以像素点为单位 位深度以bits为单位int width = src_vinfo.biWidth;int height = src_vinfo.biHeight;// 3.以wb权限打开新建bmp图片,并向新的bmp图像的文件头中录入数据FILE *bmp_new = fopen("new.bmp", "wb");src_head.bfSize = src_vinfo.biWidth / n * src_vinfo.biHeight / n * src_vinfo.biBitCount / 8 + 54;// 新bmp文件的总大小 = 源bmp像素点宽的一半 * 源像素点高的一半 * bmp图像位深度 / 比特 + 新文件头54字节src_vinfo.biWidth = src_vinfo.biWidth / n;// 新bmp文件的像素点宽 = 源bmp像素点宽的一半src_vinfo.biHeight = src_vinfo.biHeight / n;// 新bmp文件的图像区大小 = 源bmp图像区大小的一半// src_vinfo.biSizeImage = src_vinfo.biSizeImage / 4;fwrite(&src_head, 1, 14, bmp_new);fwrite(&src_vinfo, 1, 40, bmp_new);// 创建缓冲区,每次读取一行存入缓冲区char *line_size = (char *)calloc(1, width * 3);// 循环将源bmp图片的颜色分量输入到新bmp文件中for (int i = 0; i < height * 3; i += n){                                            // 外层循环,隔行读取fread(line_size, 1, width * 3, bmp_src); // 每次读取一行,存入缓冲区for (int j = 0; j < width * 3; j += 3 * n){fwrite(&line_size[j], 3, 1, bmp_new);}bzero(line_size, width * 3);fseek(bmp_src, width * 3 * (n - 1), SEEK_CUR);}/*    // 5.打开lcd并建立lcd映射内存int lcd_fd = open("/dev/fb0", O_RDWR);if (lcd_fd == -1){printf("mmap for lcd is error\n");return -1;}// 调用LCD屏的像素 获取屏幕的宽高信息struct fb_var_screeninfo lcd_vinfo;ioctl(lcd_fd, FBIOGET_VSCREENINFO, &lcd_vinfo);int *lcd_mp = (int *)mmap(NULL,                                // 申请内存映射的地址,填NULL让MMU自行分配lcd_vinfo.xres * lcd_vinfo.yres * 4, // 申请的空间大小,以lcd屏实际像素大小*每个像素点的字节数PROT_READ | PROT_WRITE,              // 映射空间的操作权限,读 |写MAP_SHARED,                          // 映射空间对其他成员的权限 共享lcd_fd,                              // lcd文件指示符0);                                  // 映射空间起始偏移量// 5.将新的bmp图像位置指示器设置在颜色分量数据起始地址fseek(bmp_new, 54, SEEK_SET);// 6.定义缓冲区,获取新bmp图像的颜色分量,行列都缩放为原来的一半,像素宽/2*像素高/2乘以位深度/8char new_buff[src_vinfo.biHeight * src_vinfo.biWidth * src_vinfo.biBitCount / 8];// 初始化缓冲区bzero(new_buff, src_vinfo.biWidth * src_vinfo.biHeight * src_vinfo.biBitCount / 8);//				    像素点宽		       像素点高的				位深度// 7.将新的bmp图像中的颜色分量写入lcd映射内存中int data = 0;int cnt = 0;for (int i = (y + src_vinfo.biHeight - 1); i >= y; i--){ // bmp图像写入lcd的数据录入方式是自底向上,外层循环以指定位置到向上偏移bmp图像高度单位为终点for (int j = y; j < (src_vinfo.biWidth + y); j++){ // 内层循环写入lcd的数据录入方式是自左向右,以指定位置到向后偏移bmp图像宽度单位为止data |= new_buff[cnt];data |= new_buff[cnt + 1] << 8;data |= new_buff[cnt + 2] << 16;lcd_mp[i * (lcd_vinfo.xres) + j] = data;cnt += 3;data = 0;}}*/// 8.关闭源bmp图片,新bmp图片,lcd屏,释放映射内存fclose(bmp_src);fclose(bmp_new);// close(lcd_fd);// munmap(new_buff, lcd_vinfo.xres * lcd_vinfo.yres * 4);return 0;
}

主函数中测试

int main(int argc, char *argv[])
{if (argc != 2){printf("argument is error!\n");return -1;}if (NULL == argv[1]){printf("argument 2 is error!\n");return -1;}int x, y, n;scanf("%d%d%d", &x, &y, &n);Scalinbmp(argv[1], x, y, n);return 0;
}

源bmp图片

image

文件属性

image

运行程序后生成的新bmp图片

image

文件属性

image

注:此代码仍需优化,考虑字节对齐,优化后将及时更改

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

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

相关文章

树刷题题后感——相对来说概念和公式数量可以和数论比较

在刷题的时候因为概念太多了越刷越懵所以先整理一下。题目来源:牛客网专项练习牛客网专项练习_校招题库练习题_行测题库考点考题 (nowcoder.com)树:参考链接:如何理解数据结构中树的度(树的度是什么意思)?-CSDN博客       (他这里打的“节点数“是指节点,,意思就…

PWM

PWMPWM1. 什么是PWM? 2. 面积等效原理2.1. 什么是面积等效原理? 2.2. 面积等效原理的理解3. 相关概念3.1. 周期和频率 3.2. 占空比4. 总结 参考链接 others1. 什么是PWM? PWM是Pulse Width Modulation的缩写,中文是脉冲宽度调制。 是利用微处理器的数字输出来对模拟电路进行…

02--JS02--高级

JavaScript02: 进阶 一. 变量声明 1.1 变量提升 // 以下代码,或多或少会有些问题的 function fn(){console.log(name);var name = 大马猴; }fn()// 问题: name变量先使用,再定义 这么写代码,在其他语言里. 绝对是不允许的 但是在js里,不但允许,还能执行,为什么呢? 因…

库的移植

库移植的步骤从官网下载需要移植的库的源码包。解压压缩包,解压后找到自述文件README,打开README了解libjpeg库的使用规则!根据源码包中的install.txt的文本,学习libjpeg库的移植和安装的步骤,移植libjpeg的步骤分为三步:配置(./configure) + 编译(make) + 安装(make in…

uniapp wifi调试

adb 版本大于 30无线调试 -> 使用配对码配对设备终端输入命令: adb pair ip地址:port端口 (替换为对应的ip和端口),回车后,继续输入WLAN配对码成功提示 Successfully paired to 192.168.137.21:38583 [guid=adb-xxxxxxx]最后 adb connect ip地址:port端口 (替换为对应的i…

项目冲刺day6

这个作业属于哪个课程 软工4班这个作业要求在哪里 作业要求1.会议1. 照片 线上会议:2. 昨日已完成: 商品分类,购物车功能。部分完成轮播图功能。3.今天计划完成的工作 完成剩下的轮播图、用户头像、文件上传功能,争取尽早将后端部分部署于云端。2.燃尽图3.每人的代码签入记…

在线抽奖系统的测试报告

上一篇博客解析了在线抽奖系统的难点,这篇博客是在线抽奖系统的测试报告 本文主要就是展示在线抽奖系统各个模块的测试用例以及使用自动化工具测试核心功能 一、测试用例 1、注册页面测试用例2、登录页面测试用例3、奖项设置页面测试用例 4、抽奖页面测试用例二、功能测试 测试…