嵌入式Linux小项目之图片编解码播放器(2)
目录一、图片数据提取和显示1、Image2LCD提取图片数据2、图片显示编码与实践二、图片显示的高级话题1、RGB顺序调整2、显示函数的其他写法三、其他显示细节问题1、任意分辨率大小图片显示一、图片数据提取和显示1、Image2LCD提取图片数据(1)软件下载:http://www.cr173.com/soft/43222.html(2)软件使用1、首先找一张图片,格式为jpg,可自行在百度找一张
目录
一、图片数据提取和显示
1、Image2LCD提取图片数据
(1)软件下载:http://www.cr173.com/soft/43222.html
(2)软件使用
1、首先找一张图片,格式为jpg,可自行在百度找一张,颜色尽量丰富,测试效果更好些
我给大家提供一张我用的图片。
2、使用该软件打开图片。
示例图片:
软件打开界面:
图像头数据:包含了图像的长宽等信息,我们不勾选他,我们需要的是图片的数据
字节内像素数据反序:即像素数据的排列顺序,如010101变为101010
扫描模式:水平或垂直。自右至左、自底至顶扫描方式与默认的扫描方式相反(及软件打开时已有的扫描方式),我们使用默认的方式
高位在前:类似于大小端模式,我们不勾选
输出数据类型:即我们所需要的数据类型,因为我们使用C语言进行编程,故而我们选用,C语言数组
输出灰度:即我们想要的图片输出颜色,若选单色则是灰白的,彩色则是图片正常色彩,我们使用RGB888编码,使用24位真彩色
最大输出宽度和高度:可随意设置,可设为LCD的分辨率大小1024600,也可设为800480
亮度和对比度:我们不用进行调整
输出图像调整:我们选用24位真彩色
圈出来的蓝、绿、红颜色块是可以拖动调整的,即改变颜色序。此外我们也可以在代码中选择颜色序,但要确保代码使用的颜色序与使用该软件生成的数据所用的那个的颜色序是相同的,否则是无法正常显示的。
最后点击软件界面的保存,可生成一个.h或者.c文件。我使用RGB颜色序,并将其放到了display文件夹,我们只使用其进行测试,之后并不会再用。
开头被注释掉就是图像头数据,因为我们没有勾选该选项,所以其就被注释掉了,若勾选上则不会被注释掉。然后开头前三个元素即为第一个像素数据:0X09,0X71,0XB0
2、图片显示编码与实践
//将该数据头文件包含到使用该数据的C文件2
/*画800*460像素的图片,图像数据存在pData所指向的数组中*/
void lcd_draw_picture(const unsigned char *pData)
{
unsigned int x, y, color, p = 0;
for(y = 0; y < 460;y++)
{
for(x = 0;x < 800; x++)
{
/*在这里将坐标点(x, y)的那个像素填充上相应的颜色值即可*/
color = ((pData[p+2] << 16)|(pData[p+1] << 8)|(pData[p+0] << 0));
*(pfb + y * WIDTH + x) = color;
p += 3;
}
}
printf("lcd_draw_picture ending.\n");
}
使用该软件生成的数组元素数其实是略少于8004803的(我的是这样),在程序编译时没有问题,但在程序执行时就会出现段错误,访问到不允许访问的内存空间。怎么解决呢?我是将循环条件改了一下,把双重for循环最外层的那个数字由480改成了460,就可以了,最终效果如下所示。
大家可以看到,上边喜羊羊脸的颜色不太正常,是因为我的颜色序没有设置对,代码中的颜色序和图片数据不一致导致的,只要修改一下就可以了。
color = ((pData[p+2] << 16)|(pData[p+1] << 8)|(pData[p+0] << 0));
改为
color = ((pData[p+2] << 0)|(pData[p+1] << 8)|(pData[p+0] << 16));
二、图片显示的高级话题
1、RGB顺序调整
(1)RGB顺序有三个地方可以去修改:第一个是fb驱动中的排布,第二个是应用程序中的排布,第三个是图像数据本身排布(Image2LCD软件中调整RGB顺序)
(2)如果三个点中RGB顺序是一致的就会显示正常。如果三个设置不一致就可能会导致显示结果中R和B相反了。
(3)实际写程序时,一般不去分析这东西,而是根据实际显示效果去调。如果反了就去调正应用程序中的RGB顺序就行了,这样最简单。
2、图片像素显示的坐标系
三、其他显示细节问题
1、任意分辨率大小图片显示
(1)图片比屏幕分辨率大,这种情况下多出来的部分肯定是没法显示的。处理方法是直接在显示函数中把多余不能被显示的部分给丢掉。
(2)图片大小比屏幕大小要小。这种情况下图片只是填充屏幕中一部分,剩余部分仍然保持原来的底色。
大家可自行使用不同大小的图片去实践测试!
2、任意起点位置图片显示
(1)小图片任意起点(整个图片显示没有超出屏幕范围内)
/*任意起点的图片的显示*/
void lcd_draw_picture1(int x0, int y0, const unsigned char *pData)
{
unsigned int x, y, color, p = 0;
for(y = 0; y < 460;y++)
{
for(x = 0;x < 800; x++)
{
// 在这里将坐标点(x, y)的那个像素填充上相应的颜色值即可
// y * WIDTH + x:表示屏幕第多少个像素点,x、y值从0开始
color = ((pData[p+2] << 0)|(pData[p+1] << 8)|(pData[p+0] << 16));//得到图片一个像素点的颜色
*(pfb + (y+y0) * WIDTH + (x+x0)) = color;//将图片像素点的颜色填充到LCD屏幕的某个像素点上
p += 3;
}
}
printf("lcd_draw_picture1 ending.\n");
}
实际测试效果:
(2)将小图片显示到屏幕中央,即将图片像素的起点设为:
LCD分辨率:1024*600
图片大小:800*460
x0:(1024-800)/2
y0:(600-460)/2
实际测试效果:
(3)起点导致图片超出屏幕外
lcd_draw_picture1(1024, 600, gImage_800480);
lcd_draw_picture1(1000, 600, gImage_800480);
lcd_draw_picture1(100, 600, gImage_800480);
以上三次实际测试效果均为:
lcd_draw_picture1(1024, 500, gImage_800480);
lcd_draw_picture1(1024, 400, gImage_800480);
lcd_draw_picture1(1000, 300, gImage_800480);
以上实际测试效果依次为:
summary:根据上述的实际测试效果我们可以得出,当图片进行显示时,右边超出会补到左边进行显示,下边超出不会补到上边进行显示。
在之前的framebuffer驱动的文章以及应用编程的文章等等我们都提到过我们申请到的内存是双缓冲区域,实际大小是10246002*4,使用unsigned int型的内存空间存储一个像素点的颜色数据(原本一个像素点的颜色数据是3个字节,现在使用unsigned int类型,还剩余了一个字节),所以刚才进行测试时图片下边超出的部分是跑到双缓存区域的下半部分了,若是取消双缓存区域,则刚才的访问就会越界,报段错误。示例如下:
lcd_draw_picture1(1000, 1300, gImage_800480);//程序执行会报段错误:Segmentation fault
我们也可通过程序实现使得超出x和y方向之外的部分都不显示,示例代码如下:
//LCD的分辨率:WIDTH*HEIGHT
void lcd_draw_picture2(int x0, int y0, const unsigned char *pData)
{
unsigned int x, y, color, p = 0;
for(y = y0; y < (460+y0); y++)
{
if(y > HEIGHT)
break;
for(x = x0; x < (800+x0); x++)
{
if(x > WIDTH)
{
p += 3;
continue;
}
color = ((pData[p+2] << 0)|(pData[p+1] << 8)|(pData[p+0] << 16));//得到图片一个像素点的颜色
*(pfb + y * WIDTH + x) = color;//将图片像素点的颜色填充到LCD屏幕的某个像素点上
p += 3;
}
}
printf("lcd_draw_picture2 ending.\n");
}
注:本资料大部分由朱老师物联网大讲堂课程笔记整理而来并且引用了部分他人博客的内容,如有侵权,联系删除!水平有限,如有错误,欢迎各位在评论区交流。
更多推荐
所有评论(0)