首页 > 其他分享 >数码相框-显示bmp图片

数码相框-显示bmp图片

时间:2024-04-11 09:45:48浏览次数:21  
标签:显示 return 相框 bmp 数码 操作 ptTmp include ptDispOpr

写主函数和测试功能

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <config.h>
#include <draw.h>
#include <encoding_manager.h>
#include <fonts_manager.h>
#include <disp_manager.h>
#include <input_manager.h>
#include <pic_operation.h>
#include <render.h>
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

/*
 * 程序入口:处理命令行参数,打开BMP文件,读取并显示图像。
 * argc: 命令行参数个数。
 * argv: 命令行参数数组。
 * 返回值:成功返回0,失败返回-1。
 */
int main(int argc, char **argv)
{
    int iFdBmp;                  // 文件描述符
    int iRet;                    // 操作返回值
    unsigned char *pucBMPmem;    // BMP文件内存映射指针
    struct stat tBMPstat;        // 文件状态结构体
  
    PT_DispOpr ptDispOpr;        // 显示操作结构体指针

    extern T_PicFileParser g_tBMPParser; // BMP文件解析器

    T_PixelDatas tPixelDatas;        // 原始像素数据结构体
    T_PixelDatas tPixelDatasSmall;    // 缩小后的像素数据结构体
    T_PixelDatas tPixelDatasFB;       // 显示帧缓冲区的像素数据结构体

    // 检查命令行参数是否正确
    if (argc != 2)
    {
        printf("%s <bmp_file>\n", argv[0]);
        return -1;
    }

    // 初始化调试信息输出
    DebugInit();
    InitDebugChanel();

    // 初始化显示系统
    DisplayInit();

    // 初始化并设置显示设备
    ptDispOpr = GetDispOpr("fb");
    ptDispOpr->DeviceInit();
    ptDispOpr->CleanScreen(0);
  
    /* 打开BMP文件 */
    iFdBmp = open(argv[1], O_RDWR);
    if (iFdBmp == -1)
    {
        DBG_PRINTF("can't open %s\n", argv[1]);
    }

    // 获取BMP文件状态,用于后续内存映射
    fstat(iFdBmp, &tBMPstat);
    // 使用内存映射方式加载BMP文件
    pucBMPmem = (unsigned char *)mmap(NULL , tBMPstat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, iFdBmp, 0);
    if (pucBMPmem == (unsigned char *)-1)
    {
        DBG_PRINTF("mmap error!\n");
        return -1;
    }

    /* 检测是否是一个合格的bmp文件 */
    iRet = g_tBMPParser.isSupport(pucBMPmem);
    if (iRet == 0)
    {
        DBG_PRINTF("%s is not bmp file\n", argv[1]);
        return -1;    
    }

    // 解析BMP文件像素数据
    tPixelDatas.iBpp = ptDispOpr->iBpp;
    iRet = g_tBMPParser.GetPixelDatas(pucBMPmem, &tPixelDatas);
    if (iRet)
    {
        DBG_PRINTF("GetPixelDatas error!\n");
        return -1;    
    }

    // 设置帧缓冲区的像素数据结构体
    tPixelDatasFB.iWidth        = ptDispOpr->iXres;
    tPixelDatasFB.iHeight       = ptDispOpr->iYres;
    tPixelDatasFB.iBpp          = ptDispOpr->iBpp;
    tPixelDatasFB.iLineBytes    = ptDispOpr->iXres * ptDispOpr->iBpp / 8; 
    tPixelDatasFB.aucPixelDatas = ptDispOpr->pucDispMem;
  
    // 将BMP图像数据合并到帧缓冲区显示
    PicMerge(0, 0, &tPixelDatas, &tPixelDatasFB);

    // 缩小1/2图像并显示
    tPixelDatasSmall.iWidth  = tPixelDatas.iWidth/2;
    tPixelDatasSmall.iHeight = tPixelDatas.iHeight/2;
    tPixelDatasSmall.iBpp    = tPixelDatas.iBpp;
    tPixelDatasSmall.iLineBytes = tPixelDatasSmall.iWidth * tPixelDatasSmall.iBpp / 8;
    tPixelDatasSmall.aucPixelDatas = malloc(tPixelDatasSmall.iLineBytes * tPixelDatasSmall.iHeight);
  
    PicZoom(&tPixelDatas, &tPixelDatasSmall);
    PicMerge(128, 128, &tPixelDatasSmall, &tPixelDatasFB);
  
    return 0;
}

修改makefile

修改工程下的makefile:

image

修改render文件夹下的makefile:

image

修改format的makefile:

image

修改operation的makefile:

image

测试

image

编译报错,需要补充函数,放在Disp_manager.c:


#include <config.h>
#include <disp_manager.h>
#include <string.h>

// 定义显示操作的链表头
static PT_DispOpr g_ptDispOprHead;
// 定义默认显示操作
static PT_DispOpr g_ptDefaultDispOpr;


/**
 * 注册显示操作
 * @param ptDispOpr 显示操作的结构体指针
 * @return 总是返回0
 */
int RegisterDispOpr(PT_DispOpr ptDispOpr)
{
	PT_DispOpr ptTmp;

	// 如果链表为空,将传入的操作设置为链表头
	if (!g_ptDispOprHead)
	{
		g_ptDispOprHead   = ptDispOpr;
		ptDispOpr->ptNext = NULL;
	}
	else
	{
		// 遍历链表,将新的显示操作添加到链表尾部
		ptTmp = g_ptDispOprHead;
		while (ptTmp->ptNext)
		{
			ptTmp = ptTmp->ptNext;
		}
		ptTmp->ptNext	  = ptDispOpr;
		ptDispOpr->ptNext = NULL;
	}

	return 0;
}


/**
 * 展示所有已注册的显示操作
 */
void ShowDispOpr(void)
{
	int i = 0;
	PT_DispOpr ptTmp = g_ptDispOprHead;

	// 遍历链表,打印每个显示操作的名称
	while (ptTmp)
	{
		printf("%02d %s\n", i++, ptTmp->name);
		ptTmp = ptTmp->ptNext;
	}
}

/**
 * 获取指定名称的显示操作
 * @param pcName 指向要获取的显示操作名称的指针
 * @return 找到的显示操作的结构体指针,如果未找到则返回NULL
 */
PT_DispOpr GetDispOpr(char *pcName)
{
	PT_DispOpr ptTmp = g_ptDispOprHead;

	// 遍历链表,查找名称匹配的显示操作
	while (ptTmp)
	{
		if (strcmp(ptTmp->name, pcName) == 0)
		{
			return ptTmp;
		}
		ptTmp = ptTmp->ptNext;
	}
	return NULL;
}

/**
 * 选择默认的显示设备
 * @param name 指向默认显示设备名称的指针
 */
void SelectDefaultDispDev(char *name)
{
	g_ptDefaultDispOpr = GetDispOpr(name); // 通过名称获取显示操作,并设置为默认
}

/**
 * 获取默认显示设备的分辨率
 * @param piXres 指向存储宽度的整型指针
 * @param piYres 指向存储高度的整型指针
 * @return 成功返回0,失败返回-1
 */
int GetDispResolution(int *piXres, int *piYres)
{
	if (g_ptDefaultDispOpr) // 检查是否有默认显示操作
	{
		*piXres = g_ptDefaultDispOpr->iXres; // 设置宽度
		*piYres = g_ptDefaultDispOpr->iYres; // 设置高度
		return 0;
	}
	else
	{
		return -1;
	}
}

/**
 * 初始化显示设备
 * @return 初始化错误码,0表示成功
 */
int DisplayInit(void)
{
	int iError;

	iError = FBInit(); // 初始化帧缓冲区

	return iError;
}

这段代码定义了一个显示操作的链表,提供了注册显示操作、展示所有已注册的显示操作、获取指定名称的显示操作、选择默认的显示设备、获取默认显示设备的分辨率和初始化显示设备等功能。

具体来说:

  • RegisterDispOpr​ 函数用于注册显示操作,将传入的操作添加到链表中。
  • ShowDispOpr​ 函数用于展示所有已注册的显示操作,遍历链表并打印每个操作的名称。
  • GetDispOpr​ 函数用于获取指定名称的显示操作,遍历链表并查找名称匹配的操作。
  • SelectDefaultDispDev​ 函数用于选择默认的显示设备,通过名称获取显示操作并设置为默认。
  • GetDispResolution​ 函数用于获取默认显示设备的分辨率,检查是否有默认显示操作,并返回宽度和高度。
  • DisplayInit​ 函数用于初始化显示设备,调用 FBInit​ 函数进行初始化并返回错误码。

编译之后生成digitpic:

image

拷贝文件和bmp图片到开发板:

image

修改报错

因为文件信息头获取到的字节数是16,不是14,没有正确读到信息,这是因为c语言结构体的内存自动优化了,所以必须强制对齐:

image

​​image

​​image

image​​

测试成功

image

补充

image

这些视频还需要看一遍,我看的b站视频顺序对不上。

标签:显示,return,相框,bmp,数码,操作,ptTmp,include,ptDispOpr
From: https://www.cnblogs.com/rose24/p/18128055/digital-photo-framedisplay-bmp-image-z1bme5x

相关文章

  • 数码相框-bmp图标显示
    bmp图片格式的解析参考资料:bmp格式分析‍位图文件主要分为如下3个部分:块名称对应Windows结构体定义大小(Byte)文件信息头BITMAPFILEHEADER14位图信息头BITMAPINFOHEADER40RGB颜色阵列BYTE*由图像长宽尺寸决定1、文件信息头BITMAPFILEHEADER结......
  • 数码管显示屏驱动芯片VK1640 SOP28,2线串行接口,适用于小型LED显示屏驱动
    产品品牌:永嘉微电/VINKA产品型号:VK1640封装形式:SOP28概述VK1640是一种数码管或点阵LED驱动控制专用芯片,内部集成有数据锁存器、LED驱动等电路。SEG脚接LED阳极,GRID脚接LED阴极,可支持8SEGx16GRID的点阵LED显示。适用于小型LED显示屏驱动。采用SOP28的封装形式。LJQ336特点•......
  • 数码管闪烁模板及注意事项
    数码管闪烁模板及注意事项方式1:直接在segProc()里写查看代码voidSeg_Proc(void){ if(Seg_Slow_Down)return; Seg_Slow_Down=1; /***用户自定义代码区↓***/ sprintf(seg_string,"-%d-%3d",(unsignedint)disp1,disp2); if(state_flag==2)//让disp1......
  • 数码相框-编写框架
    程序框架程序界面:​程序结构:main.c调用一个T_PageAction​数据类型的Run函数,展示界面。​T_PageAction​类型的结构体。T_PageAction​结构体用于定义页面的行为接口,包含以下成员:.name:字符串,表示页面名称(这里是"main"),用于标识该页面。.Run:函数指针,指向执行页面......
  • 数码摄影基础入门,新手摄影资料大全
    一、资料前言本套新手摄影资料,大小2.44G,共有125个文件。二、资料目录(一)、新手摄影基础入门7小时精通数码单反摄影百种技巧.pdfCanon单反摄影入门.pdf[摄影师的视界——迈克尔弗里曼摄影构图与设计].pdf[数码摄影构图].郑承益.扫描版.pdf《10天学通摄影入门教程》.p......
  • 数码相框-显示JPG图片
    LCD控制器会将LCD上的屏幕数据映射在相应的显存位置上。​​通过libjpeg把jpg图片解压出来RGB原始数据。libjpeg是使用c语言实现的读写jpeg文件的库。使用libjpeg的应用程序是以"scanline"为单位进行图像处理的。libjpeg解压图片的步骤:​​‍libjpeg的使用DirectoryList......
  • 将24位BMP图像转换为8位BMP图像的实现方法
    项目说明周末想起一个项目需要使用agg与8bits的BMP进行绘制,因agg不支持8bitsBMP进行绘制,故自己实现了一个基于agg+rgb88进行绘制,绘制结果转为8bits的BMP.从24位BMP图像到8位BMP图像的转换过程。转换后的图像文件将只使用256种颜色,但仍保留了原始图像的基本信息。主要原理:读......
  • 基于EP4CE6F17C8的FPGA可调校数码管时钟实例
    一、电路模块1、数码管开发板板载了6个数码管,全部为共阳型,原理图如下图所示,段码端引脚为DIG[0]~DIG[7]共8位(包含小数点),位选端引脚为SEL[0]~SEL[5]共6位。端口均为低电平有效。其实物图如下所示。数码管引脚分配见下表。2、时钟晶振开发板板载了一个50MHz的有源晶振,为系统......
  • 数码相框-LCD显示多行文字
    显示几行文字:从左显示:先描边再算出边框。居中显示:先算出边框,再确定坐标描画。从左显示​​第一行数据的起始位置是从(0,24)开始的。​要知道第二行数据从哪里开始,我们得知道画出来的矢量字体的边框是多少:​​​​这个数据是笛卡尔坐标。​​​​测试:​​#include......
  • 韦东山-数码相框之freetyte
    矢量字体文件的优点,不会变形,放大放小都会不模糊。​​矢量字体文件的实现方式:取若干条闭合曲线的关键点使用贝塞尔曲线连接关键点填充内部空间Freetype的函数说明​​​FT_Init_FreeType​初始化​FT_New_Face​加载字体文件​FT_Set_Char_Size​设置字体大小​......