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

数码相框-bmp图标显示

时间:2024-04-09 16:46:04浏览次数:24  
标签:pucSrc ptPixelDatas int 相框 像素 bmp 图像 iHeight 图标

bmp图片格式的解析

参考资料:

位图文件主要分为如下3个部分:

块名称 对应Windows结构体定义 大小(Byte)
文件信息头 BITMAPFILEHEADER 14
位图信息头 BITMAPINFOHEADER 40
RGB颜色阵列 BYTE* 由图像长宽尺寸决定

1、 文件信息头BITMAPFILEHEADER

结构体定义如下:

typedef struct tagBITMAPFILEHEADER { /* bmfh */

UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;

} BITMAPFILEHEADER;

其中:

bfType 说明文件的类型,该值必需是0x4D42,也就是字符'BM'。
bfSize 说明该位图文件的大小,用字节为单位
bfReserved1 保留,必须设置为0
bfReserved2 保留,必须设置为0
bfOffBits 说明从文件头开始到实际的图象数据之间的字节的偏移量。这个参数是非常有用的,因为位图信息头和调色板的长度会根据不同情况而变化,所以你可以用这个偏移值迅速的从文件中读取到位数据。

2、位图信息头BITMAPINFOHEADER

结构体定义如下:

typedef struct tagBITMAPINFOHEADER { /* bmih */

DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;

} BITMAPINFOHEADER;

其中:

biSize 说明BITMAPINFOHEADER结构所需要的字数。
biWidth 说明图象的宽度,以象素为单位。
biHeight 说明图象的高度,以象素为单位。注:这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位图,还是正向的位图。如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,也就是时,高度值是一个正数。
biPlanes 为目标设备说明位面数,其值将总是被设为1。
biBitCount 说明比特数/象素,其值为1、4、8、16、24、或32。但是由于我们平时用到的图像绝大部分是24位和32位的,所以我们讨论这两类图像。
biCompression 说明图象数据压缩的类型,同样我们只讨论没有压缩的类型:BI_RGB。
biSizeImage 说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0。
biXPelsPerMeter 说明水平分辨率,用象素/米表示。
biYPelsPerMeter 说明垂直分辨率,用象素/米表示。
biClrUsed 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
biClrImportant 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。

3、RGB颜色阵列

有关RGB三色空间我想大家都很熟悉,这里我想说的是在Windows下,RGB颜色阵列存储的格式其实BGR。也就是说,对于24位的RGB位图像素数据格式是:

蓝色B值 绿色G值 红色R值

对于32位的RGB位图像素数据格式是:

蓝色B值 绿色G值 红色R值 透明通道A值

透明通道也称Alpha通道,该值是该像素点的透明属性,取值在0(全透明)到255(不透明)之间。对于24位的图像来说,因为没有Alpha通道,故整个图像都不透明。

创建bmp图标显示

在include定义要使用的结构体

创建一个pic_operation.h:


#ifndef _PIC_OPERATION_H
#define _PIC_OPERATION_H

// 定义像素数据结构体
typedef struct PixelDatas {
	int iWidth;         // 图像宽度
	int iHeight;        // 图像高度
	int iBpp;           // 每像素位数(位/像素)
	int iLineBytes;     // 每行字节长度
	unsigned char *aucPixelDatas;   // 像素数据指针
}T_PixelDatas, *PT_PixelDatas;

// 定义图片文件解析器结构体
typedef struct PicFileParser {
	char *name;                                // 文件解析器名称
	int (*isSupport)(unsigned char *aFileHead); // 判断文件头是否支持的函数指针
	int (*GetPixelDatas)(unsigned char *aFileHead, PT_PixelDatas ptPixelDatas); // 获取像素数据的函数指针
	int (*FreePixelDatas)(PT_PixelDatas ptPixelDatas); // 释放像素数据的函数指针
}T_PicFileParser, *PT_PicFileParser;

#endif /* _PIC_OPERATION_H */x

bmp图标显示


/*
 * 功能:从BMP文件中解析出像素数据
 * 参数:
 *      aFileHead - 指向BMP文件头的指针
 *      ptPixelDatas - 像素数据的存储结构体指针,包含宽度、高度和位深度信息
 * 返回值:
 *      0 - 成功
 *      -1 - 失败
 */
static int GetPixelDatasFrmBMP(unsigned char *aFileHead, PT_PixelDatas ptPixelDatas)
{
	BITMAPFILEHEADER *ptBITMAPFILEHEADER;
	BITMAPINFOHEADER *ptBITMAPINFOHEADER;

	int iWidth;
	int iHeight;
	int iBMPBpp;
	int y;

	unsigned char *pucSrc;
	unsigned char *pucDest;
	int iLineWidthAlign;
	int iLineWidthReal;


	ptBITMAPFILEHEADER = (BITMAPFILEHEADER *)aFileHead;
	ptBITMAPINFOHEADER = (BITMAPINFOHEADER *)(aFileHead + sizeof(BITMAPFILEHEADER));

	iWidth = ptBITMAPINFOHEADER->biWidth;
	iHeight = ptBITMAPINFOHEADER->biHeight;
	iBMPBpp = ptBITMAPINFOHEADER->biBitCount;

	// 只支持24位深度的BMP文件
	if (iBMPBpp != 24)
	{
		return -1;
	}

	// 初始化像素数据结构体
	ptPixelDatas->iWidth  = iWidth;
	ptPixelDatas->iHeight = iHeight;
	ptPixelDatas->aucPixelDatas = malloc(iWidth * iHeight * ptPixelDatas->iBpp / 8);//每个像素占用的字节数 = 位深度 / 8

	ptPixelDatas->iLineBytes    = iWidth * ptPixelDatas->iBpp / 8;
	if (NULL == ptPixelDatas->aucPixelDatas)//分配失败
	{
		return -1;
	}

	iLineWidthReal = iWidth * iBMPBpp / 8;//每行像素数据占用的字节数
	iLineWidthAlign = (iLineWidthReal + 3) & ~0x3;   /* 对行宽度进行4字节对齐,向4取整 */

	// 计算数据指针的起始位置
	// 将pucSrc指向BITMAPFILEHEADER结构体中bfOffBits成员指定的偏移位置
	pucSrc = aFileHead + ptBITMAPFILEHEADER->bfOffBits;

	// 依据图像高度和行宽度对齐参数,调整pucSrc的指向位置,使其指向图像数据的起始位置
	pucSrc = pucSrc + (iHeight - 1) * iLineWidthAlign;

	pucDest = ptPixelDatas->aucPixelDatas;

	// 遍历图像高度,进行像素数据转换
	for (y = 0; y < iHeight; y++)
	{	
		memcpy(pucDest,pucSrc,iLineWidthReal);
		pucSrc  -= iLineWidthAlign; // 移动到下一行的起始位置
		pucDest += iLineWidthReal; // 移动到下一行的起始位置 // 移动到下一行的起始位置
	}
	return 0;
}

image

  1. pucSrc​最初被设置为指向BITMAPFILEHEADER​结构体中bfOffBits​成员指定的偏移位置。这个偏移量通常表示.bmp文件中图像数据的起始位置。
  2. 调整数据指针:关键部分在于这行代码:
// 计算数据指针的起始位置
// 将pucSrc指向BITMAPFILEHEADER结构体中bfOffBits成员指定的偏移位置
pucSrc = aFileHead + ptBITMAPFILEHEADER->bfOffBits;

// 依据图像高度和行宽度对齐参数,调整pucSrc的指向位置,使其指向图像数据的起始位置
pucSrc = pucSrc + (iHeight - 1) * iLineWidthAlign;

这里将pucSrc​指针向后移动,使其指向图像数据的实际起始读取位置。移动距离由(iHeight - 1) * iLineWidthAlign​计算得出,具体解释如下:

  • iHeight - 1​:由于大多数图像文件(包括.bmp)以从上到下的方式存储像素数据,而LCD屏幕通常以从下到上的顺序显示图像。因此,为了将文件中的像素数据正确地映射到LCD屏幕上,需要从文件底部开始读取数据。这里的iHeight - 1​就是将指针定位到图像数据的最后一行(即屏幕显示的第一行)。
  • iLineWidthAlign​:表示对齐后的每行像素数据占用的字节数。乘以(iHeight - 1)​是为了跳过前面所有行的数据,直接到达最后一行的起始位置。

现在来描述文件存储位置到LCD屏幕的映射关系:

假设您有一个.bmp文件,其中图像数据按照以下方式存储:

+-----------------------+
|  图像数据第1行      |
+-----------------------+
|  图像数据第2行      |
+-----------------------+
|        ...            |
+-----------------------+
|  图像数据第n行(最后一行)|
+-----------------------+

而LCD屏幕的显示顺序是从下到上,如下所示:

+-----------------------+
|  图像数据第n行(屏幕第一行)|
+-----------------------+
|  图像数据第n-1行     |
+-----------------------+
|        ...            |
+-----------------------+
|  图像数据第1行      |
+-----------------------+

通过上述代码中对pucSrc​指针的调整,使得它指向图像数据的最后一行(即屏幕显示的第一行)。接着,您可以按照屏幕显示顺序逐行读取pucSrc​指针所指向的像素数据,并将其传递给LCD控制器进行显示。这样就实现了从文件存储位置到LCD屏幕的正确映射。

标签:pucSrc,ptPixelDatas,int,相框,像素,bmp,图像,iHeight,图标
From: https://www.cnblogs.com/rose24/p/18124286/digital-photo-framebmp-icon-display-1f80he

相关文章

  • 程序异常退出后,托盘残留图标清理方法(C#)
    程序猿对于宕机再熟悉不过了,如果一个程序异常退出,那我们只能在Windows日志中找到它的踪迹;如果它是一个托盘程序,异常退出后,它会停留在托盘中久久不能离去,直到我们的鼠标从它身上划过;如果一个程序被另一个守护程序不断的杀掉、重启,那么它的结果会如下图所示,请注意!!这不是扫雷!!没......
  • 产品中的图标icon切图、标注、团队配合
    产品中的图标icon切图、标注、团队配合切图切图手段切图图标了解切图结构切图命名状态类型知识总结切图界面设计下的重要能力,将界面内元素单独存成透明背景(例如PNG格式)的图片,并且为了不同设备和屏幕分辨率生成多倍数理想结果。切图手段位图输出和矢量图输出,使......
  • 数码相框-编写框架
    程序框架程序界面:​程序结构:main.c调用一个T_PageAction​数据类型的Run函数,展示界面。​T_PageAction​类型的结构体。T_PageAction​结构体用于定义页面的行为接口,包含以下成员:.name:字符串,表示页面名称(这里是"main"),用于标识该页面。.Run:函数指针,指向执行页面......
  • 数码相框-显示JPG图片
    LCD控制器会将LCD上的屏幕数据映射在相应的显存位置上。​​通过libjpeg把jpg图片解压出来RGB原始数据。libjpeg是使用c语言实现的读写jpeg文件的库。使用libjpeg的应用程序是以"scanline"为单位进行图像处理的。libjpeg解压图片的步骤:​​‍libjpeg的使用DirectoryList......
  • 如何创建一个双击打开就能关机的图标
    前言Windows每个版本的关机按钮位置好像都不太一样,有时候根本找不到。有些时候又得点好几次才能把电脑关了,着实是着急。万一遇到眼神不准的时候,关机按钮都点不到。这时候小白就在想,能不能弄个图标在桌面,双击打开就可以关机,这简直是爽翻了天。所以,这次的方法特别简单:创建......
  • 将24位BMP图像转换为8位BMP图像的实现方法
    项目说明周末想起一个项目需要使用agg与8bits的BMP进行绘制,因agg不支持8bitsBMP进行绘制,故自己实现了一个基于agg+rgb88进行绘制,绘制结果转为8bits的BMP.从24位BMP图像到8位BMP图像的转换过程。转换后的图像文件将只使用256种颜色,但仍保留了原始图像的基本信息。主要原理:读......
  • 数码相框-LCD显示多行文字
    显示几行文字:从左显示:先描边再算出边框。居中显示:先算出边框,再确定坐标描画。从左显示​​第一行数据的起始位置是从(0,24)开始的。​要知道第二行数据从哪里开始,我们得知道画出来的矢量字体的边框是多少:​​​​这个数据是笛卡尔坐标。​​​​测试:​​#include......
  • 韦东山-数码相框之freetyte
    矢量字体文件的优点,不会变形,放大放小都会不模糊。​​矢量字体文件的实现方式:取若干条闭合曲线的关键点使用贝塞尔曲线连接关键点填充内部空间Freetype的函数说明​​​FT_Init_FreeType​初始化​FT_New_Face​加载字体文件​FT_Set_Char_Size​设置字体大小​......
  • 数码相框-LCD显示多行文字
    显示几行文字:从左显示:先描边再算出边框。居中显示:先算出边框,再确定坐标描画。从左显示​​第一行数据的起始位置是从(0,24)开始的。​要知道第二行数据从哪里开始,我们得知道画出来的矢量字体的边框是多少:​​​​这个数据是笛卡尔坐标。​​​​测试:​​#include......
  • [工具] 批量BMP图片转为PNG透明图片,去掉BMP黑色背景,去黑底,压缩导出png图片V1.1
    批量BMP图片转为PNG透明图片,去掉BMP黑色背景,压缩导出png图片V1.1前段时间上传了一款bmp转png并去黑底的demo软件,非常受欢迎,  上一版本地址:批量BMP图片转为PNG透明图片,去掉BMP黑色背景应广大爱好者的要求,完善了一下软件的功能,增加了导出png图片压缩功能,界面如下:  压......