bmp图片分析显示

 

1、显示器,显示最小的单位:像素点(开发板的分辨率是800X480)  

 

怎么样去表示每一个像素点?

比如说只有一个位,来显示,那只能显示白色和黑色,比如说有 8bit -> 1Byte 有2^8种情况,位数越大,所能表示的颜色就越多

 

三原色( ARGB )  8:8:8:8 每一个像素点有32位来表示

 ABGR

 

char buf[4];

int size;

int r;

 

fd = open("1.bmp",O_RDONLY);

lseek(fd,2,SEEK_SET);

r = read(fd,buf,4);

 

size = (buf[3] & 0xff) << 24 | (buf[2] & 0xff) << 16 | (buf[1] & 0xff) << 8 | (buf[0] & 0xff) << 0;

 

头两个字节,分辨率,大小,位深

 

 

read(fd,buf,2);

 

buf[1] << 8 | buf[0]

 

 

2、开发环境搭建和使用

安装minicom

sudo apt-get install minicom

 

网络问题:

vim /etc/network/interfaces

auto eth0

iface eth0 inet static

address 192.168.5.3//自己号码加65,自己52+65=117;

netmask 255.255.255.0

gateway 192.168.5.1

dns-nameserver 192.168.5.1

 

sudo ifconfig eth0  IP

sudo route add default gw 192.168.5.1

Ping 192.168.5.1//ping一下网关

ping www.baidu.com//如果能连网但是不能ping百度,可能是不能解析域名;进行下面操作;

sudo vim /etc/resolv.conf  在最下面添加一行  ->  nameserver 192.168.5.1

刚才看很多同学wind10的电脑,更新不了软件,是更新源的问题,大家可以下载群里面这个source.list文件,替换系统原来的更新源

 

法一、如果能连网但是不能下载软件,可能是更新源的问题,sources.list

sudo vim/etc/apt/sources.list进入到里面粘贴百度复制的更新源代码;

百度Ubuntu 14.4源

法二、或者找一个好的sources.list放入share文件里面

sudo cp  source.list   /etc/apt/

sudo apt-get update 

sudo apt-get install minicom

 

3、minicom的使用

 

dmesg查看USB转串口是否链接到虚拟机。 /dev/ttyUSB0

 

配置minicom

sudo minicom -s  ---> Serial port setup

 

    +-----------------------------------------------------------------------+

    | A -    Serial Device      : /dev/ttyUSB0                              |

    | B - Lockfile Location     : /var/lock                                 |

    | C -   Callin Program      :                                           |

    | D -  Callout Program      :                                           |

    | E -    Bps/Par/Bits       : 115200 8N1                                |

    | F - Hardware Flow Control : No                                        |

    | G - Software Flow Control : No                                        |

    |                                                                       |

    |    Change which setting?                                              |

    +-----------------------------------------------------------------------+

按对应的字母进入对应的选项来修改设置,修改好之后,回车结束。

 

然后选择 Save setup as dfl 保存为默认的配置,以后就不需要再进行配置了。

 

Exit from Minicom

 

$ sudo minicom  -c on

退出 ctrl + a 然后再按q退出

 

 

 

4、LCD的使用

 

打开对应的设备节点,往framebuffer写入显示的数据

 

#include <stdio.h>

#include <fcntl.h>

 

int main()

{

    int fd ;

    int lcd_buf[800*480];//ARGB -> 4个字节

    int i;

 

    for(i=0;i<800*480;i++){

         lcd_buf[i] = 0x00FF0000;

     }   

 

    fd = open("/dev/fb0",O_RDWR);

     if(fd < 0)

     {   

         perror("open fail");

         return -1;

     }   

 

write(fd,lcd_buf,800*480*4);

 

close(fd);

     return 0;

}

编译: arm-linux-gcc -o lcd lcd.c

arm-linux-gcc lcd.c -o lcd

然后通过串口下载到开发板

#rx lcd

#chmod 777 lcd

#./lcd

#ps (查看当前后台运行的iot程序,然后把这个iot程序杀死 ,kill 对应的进程号码)

 

ps可以查看进程;

 

 

5、将framebuffer映射到我们进程空间

首先我们要根据显示设备进行映射,就要获取到它的硬件信息,这个信息在这个头文件有定义:vim /usr/include/linux/fb.h

 

 

238 struct fb_var_screeninfo {

239     __u32 xres;         /* 宽 度  w      */

240     __u32 yres;        //高度     h

245

246     __u32 bits_per_pixel;       /* 每一个像素用多少位来表示        */

}

 

FBIOGET_VSCREENINFO


framebuffer设备的参数

2010年11月18日 20:22:00

阅读数:3486

如果应用程序需要知道Framebuffer设备的相关参数,必须通过ioctl()系统调用来完成。

在头文件<linux/fb.h>中定义了所有的ioctl命令字,不过,最常用的ioctl命令字是下面这两个:FBIOGET_FSCREENINFO和FBIOGET_VSCREENINFO。

前者返回与Framebuffer有关的固定的信息,比如图形硬件上实际的帧缓存空间的大小、能否硬件加速等信息。

而后者返回的是与Framebuffer有关的可变信息。

之所以可变,是因为对同样的图形硬件,可以工作在不同的模式下。

简单来讲,一个支持1024x768x24图形模式的硬件通常也能工作在800x600x16的图形模式下。

可变的信息就是指Framebuffer的长度、宽度以及颜色深度等信息。

 

这两个命令字相关的结构体有两个:struct fb_fix_screeninfo和struct fb_var_screeninfo。

这两个结构体都比较大,前者用于保存Framebuffer设备的固定信息,后者用于保存Framebuffer设备的可变信息。

在调用ioctl()的时候,要用到这两个结构体。

应用程序中通常要用到struct fb_var_screeninfo的下面这几个字段:

xres、yres、bits_per_pixel,分别表示x轴的分辨率、y轴的分辨率以及每像素的颜色深度(颜色深度的单位为bit/pixel),其类型定义都是无符号32位整型数。

16:32:59
我的电脑 2018/7/17 16:32:59
 

 

一、 什么是ioctl。
ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数如下:
int ioctl(int fd, ind cmd, …);
其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和cmd的意义相关的。
ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。 【所以说这些cmd不能和内核中的相同,否则就有冲突了】

 

 

 

 

#include <stdio.h>

#include <fcntl.h>

#include <sys/ioctl.h>

#include <linux/fb.h>

#include <sys/mman.h>

 

int main()

{

int fd;

int *plcd=NULL;

 

fd = open("/dev/fb0",O_RDWR);

if(fd < 0)

{

perror("open lcd fail");

return -1;

}

struct fb_var_screeninfo fbinfo;

 

ioctl(fd,FBIOGET_VSCREENINFO,&fbinfo);

printf("x:%d y:%d bit_per_pixel:%d\n",fbinfo.xres,fbinfo.yres,fbinfo.bits_per_pixel);

 

plcd = mmap(

NULL ,//表示映射的地址,为空让系统自动分配

fbinfo.xres*fbinfo.yres*fbinfo.bits_per_pixel/8,//分配内存的大小

PROT_WRITE,//对这个内存区域访问的权限

MAP_SHARED,//其他进程访问的权限

fd,

0//偏移量

);

if(plcd == MAP_FAILED)

{

perror("mmap fail");

close(fd);

return -1;

}

int x,y;

for(y=0;y<480;y++)

{

for(x=0;x<800;x++)

{

*(plcd + x + y*800) = 0x000000FF;

}

}

 

close(fd);

munmap(plcd,fbinfo.xres*fbinfo.yres*fbinfo.bits_per_pixel/8);

return 0;

}

显示一张图片程序:

#include <stdio.h>

#include <fcntl.h>

#include <sys/ioctl.h>

#include <linux/fb.h>

#include <sys/mman.h>

#include <stdlib.h>

 

int fd;

int *plcd=NULL;

 

 

void LCD_Draw_Point(int x,int y,int color)

{

if(x >=0 && x < 800 && y >=0 && y < 480)

{

*(plcd + 800*y + x) = color;

}

}

 

void bmp_display()

{

int fdBmp;

int w,h;

unsigned char buf[4];

int color_depth;

 

//打开对应的文件

fdBmp = open("1.bmp",O_RDONLY);

if(fdBmp<0)

{

perror("bmp open fail");

return;

}

//判断是不是BMP图片

read(fdBmp,buf,2);

if(buf[0] != 0x42  || buf[1] != 0x4d)

{

printf("This is not a BMP picture\n");

return;

}

//读图片的宽度

lseek(fdBmp,0x12,SEEK_SET);

read(fdBmp,buf,4);

w = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];

//读图片的高度

lseek(fdBmp,0x16,SEEK_SET);

read(fdBmp,buf,4);

h = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];

 

printf("w=%d h=%d\n",w,h);

 

//读图片的色深

lseek(fdBmp,0x1c,SEEK_SET);

read(fdBmp,buf,2);

color_depth = buf[1] << 8 | buf[0];

 

//计算图片数据的大小

int size = abs(w*h*color_depth/8) ;

 

//分配用来保存图片数据的内存空间

unsigned char *pixel = malloc(size);

lseek(fdBmp,54,SEEK_SET);

read(fdBmp,pixel,size);

 

int x,y;

int i=0;

unsigned char a,r,g,b;

int color;

 

for(y=0;y < abs(h); y++)

{

for(x=0;x<abs(w);x++){

b = pixel[i++];

g = pixel[i++];

r = pixel[i++];

a = (color_depth == 32) ? pixel[i++] : 0;

color = a << 24 | r << 16 | g << 8 | b; //组合成一个新的颜色值ARGB

int dy = h > 0 ? (h - 1 - y) : y; //判断图片是从左下角还是左上角开始显示

LCD_Draw_Point(x,dy,color);

}

}

free(pixel);

close(fdBmp);

}

 

int main()

{

// int fd;

// int *plcd=NULL;

 

fd = open("/dev/fb0",O_RDWR);

if(fd < 0)

{

perror("open lcd fail");

return -1;

}

struct fb_var_screeninfo fbinfo;

 

ioctl(fd,FBIOGET_VSCREENINFO,&fbinfo);

printf("x:%d y:%d bit_per_pixel:%d\n",fbinfo.xres,fbinfo.yres,fbinfo.bits_per_pixel);

 

plcd = mmap(

NULL ,//表示映射的地址,为空让系统自动分配

fbinfo.xres*fbinfo.yres*fbinfo.bits_per_pixel/8,//分配内存的大小

PROT_WRITE,//对这个内存区域访问的权限

MAP_SHARED,//其他进程访问的权限

fd,

0//偏移量

);

if(plcd == MAP_FAILED)

{

perror("mmap fail");

close(fd);

return -1;

}

int x,y;

for(y=0;y<480;y++)

{

for(x=0;x<800;x++)

{

*(plcd + x + y*800) = 0x000000FF;

}

}

 

bmp_display();

 

close(fd);

munmap(plcd,fbinfo.xres*fbinfo.yres*fbinfo.bits_per_pixel/8);

return 0;

}

 

 

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/weixin_41723504/article/details/81430845
今日推荐