什么是framebuffer,怎么应用(二)————如何打印BMP图片、字幕函数、字符串

如何切换到终端模式

在昨天写的文章中,没有写到如何切换到终端模式,在编译完函数之后,我们需要从桌面切换到终端模式:

ALT+CTRL+F3

切换到终端模式后,登录账号名与密码,其余操作均有桌面终端一样。
如何切换回:

ATL+CTRL+F1

那么讲完这些,我们该考虑如何打印BMP图片了

BMP图片

首先,BMP图片的数据格式可以分为四个部分:
1.文件头(bmp file header):占14字节,包含文件格式、大小等信息
2.位图信息头(bitmap information):占40字节,包含图片的数据尺寸、颜色索引等信息
3.调色板(color palette):颜色表用于说明位图中的颜色,它有若干个表项,每一个表项定义一种颜色。
4.位图书数据(bitmap data):位图数据记录了位图的每一个像素值。
所以在打印图片时,我们需要让数据向后偏移54个字节的位置进行打印,并且bmp图像是反过来的,当我们偏移到相对位置后,再从图片的最后一行开始,后续会介绍。

打印BMP图片

//BMP图片
void DrawBmp(char *bmpname,int w,int h)	//图片地址、宽度、高度
{int fd = open(bmpname,O_RDONLY);	//只读方式打开if(-1 == fd){perror("fail to open");		//输出错误信息并返回return ;}// 将文件指针移到像素数据的起始位置(跳过BMP文件头)lseek(fd,54,SEEK_SET);	// 分配内存以保存图片的像素数据unsigned char *pic = malloc(w * h * 24 / 8);// 从文件中读取像素数据,一次性读完read(fd,pic,w*h*24/8);unsigned char *p = pic;// 遍历像素数据,绘制图像//BMP 图片的像素数据存储是从图片的底部(最后一行)开始的,而不是从顶部开始,所以i从h-1开始for(int i = h -1;i >= 0;--i){for(int j = 0;j < w;++j){unsigned char r,g,b;// 从像素数据中读取RGB值b = *p;	// 蓝色分量++p;g = *p; // 绿色分量++p;r = *p;	// 红色分量++p;// 根据显示设备的颜色格式,绘制像素点if(fbinfo_g.bits == RGB888_FMT){// 对于RGB888格式,将RGB值组合成一个32位颜色值unsigned int col = r << 16 | g << 8 | b;DrawPoint(j,i,col);}else if(fbinfo_g.bits == RGB565_FMT){// 对于RGB565格式,将RGB值组合成一个16位颜色值unsigned short col = (r >> 3) << 11 | (g >> 2) << 5 | (b >> 3);DrawPoint(j,i,col);}}}free(pic);	// 释放分配的内存close(fd);	// 关闭文件
}int main(void)
{InitFb("/dev/fb0");		//昨天已经解释过,可以看昨天的内容DrawBmp("2.bmp",800,600);	//读取当前路径中2.bmp文件,高800,宽600UnInitFb();return 0;
}

什么是framebuffer,怎么应用(一)————如何画点、线、矩形、圆
结果:
在这里插入图片描述

字符串打印

在打印字符串之前,我们需要一个库函数,我已经将库函数传入资源中,大家可以自行去下载
C用于C和C ++的单头utf8字符串函数

打印

首先将#include "utf.h"放置头文件中,在使用utf之前,我们需要知道utf.c文件中这些函数

utf.h头文件

#ifndef UTF
#define UTF
#ifdef __cplusplus
extern "C"{
#endif
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#define u8 unsigned char 
#define u16 unsigned short 
#define u32 unsigned int#define ZIKUK_FILE_SMALL "./ziku"
#define ZIKUK_FILE_BIG "./ziku2_w32_h32"
/***字模文件缓存**/
typedef struct
{char path[256];//字模库文件路径unsigned width; //字模宽度unsigned height;//字模高度unsigned zimo_size;//每个字字模字节数unsigned char* g_ziku_data;//字模库文件缓存区
}UTF8_INFO;extern void init_utf8(UTF8_INFO *info);
extern unsigned char *get_utf_data(UTF8_INFO *info,int out);extern void uninit_utf8(UTF8_INFO *info);
extern int enc_utf8_to_unicode_one(const unsigned char* pInput, unsigned long *Unic);
extern int enc_unicode_to_utf8_one(unsigned long unic, unsigned char *pOutput,int outSize);
extern int enc_get_utf8_size(const unsigned char pInput);#ifdef __cplusplus
}
#endif
#endif // UTF

将字库文件读取到缓存区

函数名:init_utf8将字库文件读取到缓存区
参数:info     需要回收的字模缓存区
返回值:无
注意事项:无
void init_utf8(UTF8_INFO *info)
{int ret = 0 ;int fd = open(info->path,O_RDONLY);if(-1 == fd){exit(1);}struct stat st;ret = stat(info->path,&st);if(-1 == ret){printf("get zi ku file size error");exit(1);}if(NULL == info->g_ziku_data){info->g_ziku_data= malloc(st.st_size);}ret = read(fd,info->g_ziku_data,st.st_size);if(ret<=0){printf("read utf-8 info error!");exit(1);}
//    info->height = heigh;
//    info->width = width;info->zimo_size = st.st_size /65536;close(fd);
}

回收字模缓存区空间

函数名:uninit_utf8回收字模缓存区空间
参数:info     需要回收的字模缓存区
返回值:无
注意事项:无
void uninit_utf8(UTF8_INFO *info)
{free(info->g_ziku_data);
}

打印字符串

UTF-8 字符串

int draw_utf8(UTF8_INFO *info,int x,int y,char *zi,unsigned int col,unsigned int col1)
{unsigned long out = 0;// 将UTF-8编码转换为Unicode码点int ret = enc_utf8_to_unicode_one((unsigned char *)zi,&out);// 获取UTF字体数据unsigned char *data = get_utf_data(info,out);unsigned char temp = 0;unsigned int i,j,k;unsigned int num = 0;for(i = 0;i < info->height;i++){for(j = 0;j < info->width/8;++j){temp = data[num++];for(k = 0;k<8;k++){if(0x80&temp)	//按位与{DrawPoint(x+j*8+k,y+i,col);}else{//DrawPoint(x+j*8+k,y+i,col1);}temp = temp << 1;}}}return ret;
}

main.c

#include "framebuffer.h" // 包含 framebuffer.h 头文件UTF8_INFO utf8_info; // 定义一个 UTF8_INFO 结构体变量 utf8_infoint main(void) {InitFb("/dev/fb0"); // 初始化帧缓冲设备// 以下代码段被注释掉了,不会被执行bzero(&utf8_info, sizeof(UTF8_INFO)); // 将 utf8_info 清零strcpy(utf8_info.path, ZIKUK_FILE_BIG); // 设置 utf8_info 的路径为 ZIKUK_FILE_BIGutf8_info.width = 32; // 设置 utf8_info 的宽度为 32utf8_info.height = 32; // 设置 utf8_info 的高度为 32init_utf8(&utf8_info); // 初始化 utf8_infoDrawBmp("2.bmp", 800, 600); // 绘制 BMP 图像到屏幕sleep(1); // 等待 1 秒draw_utf8_str(&utf8_info, 100, 100, "大家好,我是古天乐,是兄弟就砍我100刀!", 0x00ff0000, 0x00000000); // 在屏幕上绘制 UTF-8 字符串uninit_utf8(&utf8_info); // 反初始化 utf8_infoUnInitFb(); // 反初始化帧缓冲设备return 0; }
}

结果:
请添加图片描述
以上就是今天的内容,谢谢!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML input 实现回车切换到下一个输入框功能

前言 遇到需求&#xff0c;在客户填写单子时&#xff0c;有多个输入框&#xff0c;为了省事&#xff0c;不需要频繁移动光标填写。 实现效果 实现方式一 HTML <input type"text" name"serialNumber1" onkeydown"cursor(this);"/><in…

spring多线程实现+合理设置最大线程数和核心线程数

1.最简单的方法&#xff1a; 需要在 Spring Boot 主类上添加 EnableAsync 注解启用异步功能&#xff1b;需要在异步方法上添加 Async 注解。 示例代码如下&#xff1a; SpringBootApplication EnableAsync public class Application {public static void main(String[] args…

什么是DevOps?如何使用DevOps?

无论您是在维持公司基础设施的正常运行&#xff0c;还是在为客户的IT问题管理提供支持&#xff0c;抑或是在构建、测试或修复软件&#xff0c;还是在保护同事免受安全威胁&#xff0c;您都可能接触过 DevOps。 毕竟&#xff0c;这个术语已经出现了 15 年&#xff0c;其采用率也…

C#_泛型_委托

文章目录 泛型泛型的使用泛型的约束委托委托的实例化多播委托委托的调用内置委托类型委托练习泛型委托Lambda表达式(进阶)上期习题答案本期习题 泛型 泛型&#xff08;Generic&#xff09; 是一种规范&#xff0c;它允许我们使用占位符来定义类和方法&#xff0c;编译器会在编…

基于单片机病房呼叫系统数码管显示房号设计

**单片机设计介绍&#xff0c;基于单片机病房呼叫系统数码管显示房号设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机病房呼叫系统数码管显示房号设计概要主要涵盖了利用单片机技术实现病房呼叫系统&#xff0c;并…

工厂数字化看板是什么?部署工厂数字化看板有什么作用?

随着工业4.0时代的来临&#xff0c;数字化转型已成为制造业发展的必然趋势。在这个背景下&#xff0c;工厂数字化看板作为一种高效的信息展示与管理工具&#xff0c;正逐渐受到越来越多企业的青睐。那么&#xff0c;什么是工厂数字化看板&#xff1f;部署工厂数字化看板又有哪些…

2024软件设计师备考讲义——(3)

程序设计语言 一、程序语言基础 1.基本概念 低级语言&#xff1a;机器语言、汇编语言高级语言&#xff1a; Fortran 科学计算&#xff0c;执行效率高Pascal 为教学开发&#xff0c;表达能力强Prolog 逻辑性程序设计语言C语言 指针操作能力强&#xff0c;可以开发系统级软件&a…

vue实现文字一个字一个字的显示(开箱即用)

图示&#xff1a; 核心代码 Vue.prototype.$showHtml function (str, haveCallback null) {let timeFlag let abcStr for (let i 0; i < str.length; i) {(function (i) {timeFlag setTimeout(function () {abcStr str[i]haveCallback(abcStr)if ((i 1) str.length…

JUC:Monitor 与 Java对象头的内容与锁关系

文章目录 Monitorjava对象头Monitor&#xff08;锁、管程&#xff09; Monitor java对象头 普通对象 Mark Word 主要用来存储对象自身的运行时数据、klass word就是指向该对象的类型。 数组对象 mark word 不同对象状态下结构和含义不同。 Monitor&#xff08;锁、管…

JavaEE 初阶篇-深入了解多线程等待与多线程状态

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 线程等待 1.1 线程等待 - join() 方法 1.1.1 main 线程中等待多个线程 1.1.2 main 线程等待 t2 线程且t2 线程等待 t1 线程 1.1.3 其他线程阻塞等待 main 线程 1.…

期货开户要找到适合自己的系统

物有一个生物圈&#xff0c;大鱼吃小鱼&#xff0c;小鱼吃虾。在期货市场这条生物圈里面&#xff0c;大部分人就是期货市场的虾子&#xff0c;是被吃的&#xff0c;所以必须成长起来&#xff0c;往更高一层走&#xff0c;到可以吃虾子的时候&#xff0c;就是挣钱的时候。学习不…

物流监控升级,百递云·API开放平台助力某电商平台实现高效物流管理

不论是电商平台自身还是消费者&#xff0c;都有着对物流监控的强烈需求。 消费者下单后be like: 每十分钟看一次快递轨迹 放心&#xff0c;电商平台也一样关心物流状态&#xff01;怎样第一时间向用户传递物流状态&#xff1f; 怎么减少重复的提问和投诉&#xff1f;怎样监管…