Loading

数码相框-主界面MainPage页面规划

定义页面布局

/**
 * 主页面布局数组
 *
 * 该数组定义了主页面上各图标的位置和对应的图像文件名。数组中的每个元素代表一个图标,
 * 其中各个字段含义如下:
 * - iTopLeftX: 图标左上角X轴坐标
 * - iTopLeftY: 图标左上角Y轴坐标
 * - iBotRightX: 图标右下角X轴坐标
 * - iBotRightY: 图标右下角Y轴坐标
 * - strIconName: 图标对应的图像文件名(BMP格式)
 *
 * 数组末尾以NULL作为结束标记。
 */

static T_Layout g_atMainPageLayout[] = {
    // 浏览模式图标
    {0, 0, 0, 0, "browse_mode.bmp"},

    // 连播模式图标
    {0, 0, 0, 0, "continue_mod.bmp"},

    // 设置图标
    {0, 0, 0, 0, "setting.bmp"},

    // 数组结束标记
    {0, 0, 0, 0, NULL},
};

图标计算

图标计算:

image

  1. 图标高度与总体高度的比例: 一个图标的高度为2单位,总高度为4个基本单位(图标间隔)加上3个图标高度(每个图标高度为2单位),即:总高度 = 4 + 3 * 2 = 10 单位

  2. 因此,一个图标的高度占总高度的比例为:图标高度占比 = 图标高度 / 总高度 = 2 / 10

  3. 图标与屏幕分辨率的比例关系: 图标的分辨率为256×128像素,宽高比为2:1。这意味着图标的宽度始终为其高度的两倍。

  4. 计算图标在屏幕上的实际尺寸: 设屏幕的垂直分辨率(y轴方向)为 yres​ 像素。根据图标高度占比,一个图标的实际高度应为:

    1. 图标高度 = 图标高度占比 × 屏幕垂直分辨率 = (2/10) × yres 像素。
    2. 由于图标的宽高比为2:1,其宽度为:图标宽度 = 2 × 图标高度 = 2 × ((2/10) × yres) 像素 = (4/10) × yres 像素。
iIconHeight = iYres * 2 / 10; // 计算图标高度
iIconWidth  = iIconHeight * 2; // 根据高度计算宽度
    
iIconX = (iXres - iIconWidth)/2; // 计算图标X坐标
iIconY = iYres / 10; // 计算图标顶部Y坐标,从1/10的间隔开始画图

对文件的映射操作

定义文件映射结构体:

#ifndef _FILE_H
#define _FILE_H

// 定义文件映射结构体
typedef struct FileMap {
	char strFileName[128]; // 文件名
	int iFd; // 文件描述符
	int iFileSize; // 文件大小
	unsigned char *pucFileMapMem; // 文件映射内存指针
}T_FileMap, *PT_FileMap;

// 映射文件到内存
// @param ptFileMap 指向T_FileMap结构的指针,包含待映射文件的相关信息
// @return 成功返回0,失败返回非0
int MapFile(PT_FileMap ptFileMap);

// 从内存取消文件映射
// @param ptFileMap 指向T_FileMap结构的指针,包含待取消映射文件的相关信息
void UnMapFile(PT_FileMap ptFileMap);

#endif /* _FILE_H */

将文件映射到内存中:

/**
 * MapFile - 将文件映射到内存中
 * @param ptFileMap: 指向文件映射结构体的指针,包含文件名和后续映射操作所需的信息
 * @return: 成功返回0,失败返回-1
 *
 * 本函数的主要功能是打开指定文件,并将其映射到内存中,以便于直接在内存中对文件进行读写操作。
 * 具体步骤包括:打开文件、获取文件状态信息以获取文件大小、调用mmap系统函数将文件映射到内存。
 */
int MapFile(PT_FileMap ptFileMap)
{
	int iFd;
	struct stat tStat;

	/* 打开文件,以读写方式 */
	iFd = open(ptFileMap->strFileName, O_RDWR);
	if (iFd == -1) // 打开文件失败
	{
		DBG_PRINTF("can't open %s\n", ptFileMap->strFileName);
		return -1;
	}
	ptFileMap->iFd = iFd;

	fstat(iFd, &tStat); // 获取文件状态信息
	ptFileMap->iFileSize = tStat.st_size; // 设置文件大小
	// 将文件映射到内存,设置为可读写,并与文件共享
	ptFileMap->pucFileMapMem = (unsigned char *)mmap(NULL , tStat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, iFd, 0);
	if (ptFileMap->pucFileMapMem == (unsigned char *)-1) // 映射失败
	{
		DBG_PRINTF("mmap error!\n");
		return -1;
	}
	return 0; // 成功
}

取消文件映射:

/**
 * MapFile - 将文件映射到内存中
 * @param ptFileMap: 指向文件映射结构体的指针,包含文件名和后续映射操作所需的信息
 * @return: 成功返回0,失败返回-1
 *
 * 本函数的主要功能是打开指定文件,并将其映射到内存中,以便于直接在内存中对文件进行读写操作。
 * 具体步骤包括:打开文件、获取文件状态信息以获取文件大小、调用mmap系统函数将文件映射到内存。
 */
int MapFile(PT_FileMap ptFileMap)
{
	int iFd;
	struct stat tStat;

	/* 打开文件,以读写方式 */
	iFd = open(ptFileMap->strFileName, O_RDWR);
	if (iFd == -1) // 打开文件失败
	{
		DBG_PRINTF("can't open %s\n", ptFileMap->strFileName);
		return -1;
	}
	ptFileMap->iFd = iFd;

	fstat(iFd, &tStat); // 获取文件状态信息
	ptFileMap->iFileSize = tStat.st_size; // 设置文件大小
	// 将文件映射到内存,设置为可读写,并与文件共享
	ptFileMap->pucFileMapMem = (unsigned char *)mmap(NULL , tStat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, iFd, 0);
	if (ptFileMap->pucFileMapMem == (unsigned char *)-1) // 映射失败
	{
		DBG_PRINTF("mmap error!\n");
		return -1;
	}
	return 0; // 成功
}

从图标中获取像素数据


/**
 * 为图标获取像素数据
 * 
 * 本函数负责从指定的文件中获取图标像素数据,首先会检查文件是否存在于指定路径下,并且是BMP格式,
 * 然后获取图标显示的分辨率及每像素位深度(Bpp),最后提取像素数据。
 * 
 * @param strFileName 要处理的图标文件名(不含路径)
 * @param ptPixelDatas 指向PT_PixelDatas结构体的指针,用于接收像素数据
 * @return 成功返回0,失败返回-1
 */
int GetPixelDatasForIcon(char *strFileName, PT_PixelDatas ptPixelDatas)
{
	T_FileMap tFileMap;
	int iError;
	int iXres, iYres, iBpp;

	// 构造图标文件的完整路径 图标存在/etc/digitpic/icons/ 
 	snprintf(tFileMap.strFileName, 128, "%s/%s", ICON_PATH, strFileName);
	tFileMap.strFileName[127] = '\0';

	// 将文件映射到内存
	iError = MapFile(&tFileMap);
	if (iError)
	{
		DBG_PRINTF("MapFile %s error!\n", strFileName);
		return -1;
	}

	// 检查文件是否为BMP格式
	iError = g_tBMPParser->isSupport(tFileMap.pucFileMapMem);
	if (iError == 0)
	{
		DBG_PRINTF("%s is not bmp file\n", strFileName);
		return -1;
	}

	// 获取图标显示的分辨率及每像素位深度
	GetDispResolution(&iXres, &iYres, &iBpp);
	ptPixelDatas->iBpp = iBpp;
	// 从文件内存映射中提取像素数据
	iError = g_tBMPParser->GetPixelDatas(tFileMap.pucFileMapMem, ptPixelDatas);
	if (iError)
	{
		DBG_PRINTF("GetPixelDatas for %s error!\n", strFileName);
		return -1;
	}

	return 0;
}

显示主页面

/**
 * 显示主页面
 * 
 * @param atLayout 页面布局信息
 * 
 * 本函数负责根据提供的页面布局信息,在屏幕上显示主页面。主要步骤包括:
 * 1. 获取用于显示主页面的显存;
 * 2. 若显存中的页面图片状态不是已生成,则计算图标大小和位置,绘制图标,并更新显存中的页面图片状态;
 * 3. 将显存中的图像刷新到设备屏幕上;
 * 4. 释放显存资源。
 */
static void ShowMainPage(PT_Layout atLayout)
{
    PT_VideoMem ptVideoMem;    // 用于存储视频内存的指针
    T_PixelDatas tOriginIconPixelDatas; // 原始图标像素数据
    T_PixelDatas tIconPixelDatas; // 处理后的图标像素数据
    int iIconWidth; // 图标宽度
    int iIconHeight; // 图标高度
    int iIconX; // 图标X轴坐标
    int iIconY; // 图标Y轴坐标
    int iXres, iYres, iBpp; // 屏幕分辨率和位深度
    int iError; // 错误码

    /* 1. 获得显存 */
    ptVideoMem = GetVideoMem(ID("main"), 1);
    if (ptVideoMem == NULL)
    {
        DBG_PRINTF("can't get video mem for main page!\n");
        return;
    }

    /* 2. 描画数据 */
    if (ptVideoMem->ePicState != PS_GENERATED)
    {
        GetDispResolution(&iXres, &iYres, &iBpp); // 获取屏幕分辨率
        iIconHeight = iYres * 2 / 10; // 计算图标高度
        iIconWidth  = iIconHeight * 2; // 根据高度计算宽度
    
        iIconX = (iXres - iIconWidth)/2; // 计算图标X坐标
        iIconY = iYres / 10; // 计算图标顶部Y坐标,从1/10的间隔开始画图

        // 初始化图标像素数据结构
        tIconPixelDatas.iBpp        = iBpp;
        tIconPixelDatas.iWidth      = iIconWidth;
        tIconPixelDatas.iHeight     = iIconHeight;
        tIconPixelDatas.iLineBytes  = iIconWidth * iBpp / 8;
        tIconPixelDatas.iTotalBytes = tIconPixelDatas.iLineBytes * iIconHeight;
        tIconPixelDatas.aucPixelDatas = malloc(tIconPixelDatas.iTotalBytes);
        if (tIconPixelDatas.aucPixelDatas == NULL)
        {
            free(tIconPixelDatas.aucPixelDatas);
            return;
        }

        // 遍历布局中的所有图标
        while (atLayout->strIconName)
        {
            // 设置图标在屏幕上的位置
            atLayout->iTopLeftX  = iIconX;
            atLayout->iTopLeftY  = iIconY;
            atLayout->iBotRightX = iIconX + iIconWidth - 1;
            atLayout->iBotRightY = iIconY + iIconHeight - 1;

            iError = GetPixelDatasForIcon(atLayout->strIconName, &tOriginIconPixelDatas); // 获取图标像素数据
            if (iError)
            {
                DBG_PRINTF("GetPixelDatasForIcon error!\n");
                return;
            }
            PicZoom(&tOriginIconPixelDatas, &tIconPixelDatas); // 缩放图标
            PicMerge(iIconX, iIconY, &tIconPixelDatas, &ptVideoMem->tPixelDatas); // 将图标合并到显存中的图像
            FreePixelDatasForIcon(&tOriginIconPixelDatas); // 释放原始图标像素数据
            atLayout++; // 移动到下一个图标
            iIconY +=  iYres * 3 / 10; // 调整图标Y轴坐标,为下一个图标留出空间
        }
        free(tIconPixelDatas.aucPixelDatas); // 释放图标像素数据的内存
        ptVideoMem->ePicState = PS_GENERATED; // 设置图片状态为已生成
    }

    /* 3. 刷到设备上去 */
    FlushVideoMemToDev(ptVideoMem);

    /* 4. 解放显存 */
    PutVideoMem(ptVideoMem);
}

释放显存区

/**
 * 释放图标像素数据
 * @param ptPixelDatas 指向像素数据的指针
 * 
 * 该函数通过调用g_tBMPParser的FreePixelDatas方法,来释放图标相关的像素数据资源。
 */
void FreePixelDatasForIcon(PT_PixelDatas ptPixelDatas)
{
    g_tBMPParser->FreePixelDatas(ptPixelDatas); // 调用BMP解析器的函数释放像素数据
}

/**
 * 释放BMP图像的像素数据内存
 * @param ptPixelDatas 指向包含像素数据的结构体的指针
 * @return 始终返回0
 */
static int FreePixelDatasForBMP(PT_PixelDatas ptPixelDatas)
{
    // 释放存储像素数据的内存
    free(ptPixelDatas->aucPixelDatas);
    return 0;
}

posted @ 2024-04-11 22:25  阿四与你  阅读(8)  评论(0编辑  收藏  举报