ImageVerifierCode 换一换
格式:DOCX , 页数:14 ,大小:22.89KB ,
资源ID:4870486      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/4870486.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(在Linux控制台下使用libjpeg显示JPEG图像在framebuffer上.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

在Linux控制台下使用libjpeg显示JPEG图像在framebuffer上.docx

1、在Linux控制台下使用libjpeg显示JPEG图像在framebuffer上在Linux控制台下使用libjpeg显示JPEG图像在framebuffer上1、引言通常情况下,在Linux控制台下是无法查看图像文件的,要想查看图像文件,比如要查看JPEG格式的图像文件,可能必须启动X-Windows,通过GNOME或者KDE之类的桌面管理器提供的图像查看工具查看图片内容。那么,能不能有办法在控制台下面简单地浏览图像内容呢。实际上,这是完全可以的。在Linux下有一个名为zgv的看图软件就是工作在控制台下的。不过,由于它所使用的底层图形库svgalib已经是一个比较“古老”的图形库了,所以现

2、在知道zgv的人并不是很多,用的人就更少了。目前Linux上的底层图形支持通常是由Framebuffer提供的,因此,作者试图在本文中说明如何通过Framebuffer和libjpeg在控制台上显示JPEG图像。需要说明的是,本文中所编写的程序fv并非zgv的替代品,而只是一个出于验证想法的简单程序(fv的含义是Framebuffer Vision)。本文将先对Framebuffer和libjpeg的编程做一个简略的说明,然后再给出程序fv的具体实现。2、Framebuffer介绍Framebuffer在Linux中是作为设备来实现的,它是对图形硬件的一种抽象1,代表着显卡中的帧缓冲区(Fra

3、mebuffer)。通过Framebuffer设备,上层软件可以通过一个良好定义的软件接口访问图形硬件,而不需要关心底层图形硬件是如何工作的,比如,上层软件不用关心应该如何读写显卡寄存器,也不需要知道显卡中的帧缓冲区从什么地址开始,所有这些工作都由Framebuffer去处理,上层软件只需要集中精力在自己要做的事情上就是了。Framebuffer的优点在于它是一种低级的通用设备,而且能够跨平台工作,比如Framebuffer既可以工作在x86平台上,也能工作在PPC平台上,甚至也能工作在m68k和SPARC等平台上,在很多嵌入式设备上Framebuffer也能正常工作。诸如Minigui之类的

4、GUI软件包也倾向于采用Framebuffer作为硬件抽象层(HAL)。从用户的角度来看,Framebuffer设备与其它设备并没有什么不同。Framebuffer设备位于/dev下,通常设备名为fb*,这里*的取值从0到31。对于常见的计算机系统而言,32个Framebuffer设备已经绰绰有余了(至少作者还没有看到过有32个监视器的计算机)。最常用到的Framebuffer设备是/dev/fb0。通常,使用Framebuffer的程序通过环境变量FRAMEBUFFER来取得要使用的Framebuffer设备,环境变量FRAMEBUFFER通常被设置为”/dev/fb0”。从程序员的角度来看

5、,Framebuffer设备其实就是一个文件而已,可以像对待普通文件那样读写Framebuffer设备文件,可以通过mmap()将其映射到内存中,也可以通过ioctl()读取或者设置其参数,等等。最常见的用法是将Framebuffer设备通过mmap()映射到内存中,这样可以大大提高IO效率。要在PC平台上启用Framebuffer,首先必须要内核支持,这通常需要重新编译内核。另外,还需要修改内核启动参数。在作者的系统上,为了启用Framebuffer,需要将/boot/grub/menu.lst中的下面这一行:kernel /boot/vmlinuz-2.4.20-8 ro root=LAB

6、EL=/1修改为kernel /boot/vmlinuz-2.4.20-8 ro root=LABEL=/1 vga=0x0314即增加了vga=0x0314这样一个内核启动参数。这个内核启动参数表示的意思是:Framebuffer设备的大小是800x600,颜色深度是16bits/像素。下面,来了解一下如何编程使用Framebuffer设备。由于对Framebuffer设备的读写应该是不缓冲的,但是标准IO库默认是要进行缓冲的,因此通常不使用标准IO库读写Framebuffer设备,而是直接通过read()、write()或者mmap()等系统调用来完成与Framebuffer有关的IO操作

7、。又由于mmap()能够大大降低IO的开销,因此与Framebuffer设备有关的IO通常都是通过mmap()系统调用来完成的。mmap()的函数原型如下(Linux系统上的定义):#include #ifdef _POSIX_MAPPED_FILESvoid * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);int munmap(void *start, size_t length);#endif系统调用mmap()用来实现内存映射IO。所谓内存映射IO,是指将一个磁盘文件的内容与内存

8、中的一个空间相映射。当从这个映射内存空间中取数据时,就相当于从文件中读取相应的字节,而当向此映射内存空间写入数据时,就相当于向磁盘文件中写入数据。这就是内存映射IO的含义。具体到对mmap()而言,当调用成功时,返回值就是与磁盘文件建立了映射关系的内存空间的起始地址,当调用失败时,mmap()的返回值是-1。第一个参数start通常设置为0,表示由系统选择映射内存空间;第二个参数length指定了要映射的字节数;第三个参数指明了映射内存空间的保护属性,对于Framebuffer通常将其设置为PROT_READ | PROT_WRITE,表示既可读也可写;第四个参数flags指明了影响映射内存空

9、间行为的标志,对于Framebuffer编程而言,要将flags设置为MAP_SHARED,表明当向映射内存空间写入数据时,将数据写入磁盘文件中;第五个参数fd是要映射的文件的文件描述符;第六个参数offset指明了要映射的字节在文件中的偏移量。如果mmap()调用成功,就可以在程序中对得到的映射内存空间进行读写操作了。所有的读写都将由操作系统内核转换成IO操作。在使用完映射内存空间之后,应当将其释放,这是通过munmap()系统调用完成的。munmap()的第一个参数是映射内存空间的起始地址,第二个参数length是映射内存空间的长度,单位为字节。如果释放成功,munmap()返回0,否则返

10、回-1。如果应用程序需要知道Framebuffer设备的相关参数,必须通过ioctl()系统调用来完成。在头文件中定义了所有的ioctl命令字,不过,最常用的ioctl命令字是下面这两个:FBIOGET_FSCREENINFO和FBIOGET_VSCREENINFO,前者返回与Framebuffer有关的固定的信息,比如图形硬件上实际的帧缓存空间的大小、能否硬件加速等信息;而后者返回的是与Framebuffer有关的可变信息,之所以可变,是因为对同样的图形硬件,可以工作在不同的模式下,简单来讲,一个支持1024x768x24图形模式的硬件通常也能工作在800x600x16的图形模式下,可变的信

11、息就是指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),其类型

12、定义都是无符号32位整型数。3、libjpeg函数库介绍JPEG是CCITT和ISO定义的一种连续色调图像压缩标准2。JPEG是一种有损图像压缩标准,其基础是DCT变换(离散余弦变换)。JPEG图像的压缩过程分为三步:DCT计算,量化,变长编码分配。尽管CCITT定义了JPEG图像压缩标准,但是却并没有为JPEG定义标准的文件格式。这导致了现实世界中出现了各种各样的JPEG文件格式,而一种被称为JFIF的JPEG文件格式逐渐成为JPEG文件格式的主流。libjpeg是一个被广泛使用的JPEG压缩/解压缩函数库(至少在Unix类系统下是广泛使用的),它能够读写JFIF格式的JPEG图像文件,通常

13、这类文件是以.jpg或者.jpeg为后缀名的。通过libjpeg库,应用程序可以每次从JPEG压缩图像中读取一个或多个扫描线(scanline,所谓扫描线,是指由一行像素点构成的一条图像线条),而诸如颜色空间转换、降采样/增采样、颜色量化之类的工作则都由libjpeg去完成了。要使用libjpeg,需要读者对数字图像的基本知识有初步的了解。对于libjpeg而言,图像数据是一个二维的像素矩阵。对于彩色图像,每个像素通常用三个分量表示,即R(Red)、G(Green)、B(Blue)三个分量,每个分量用一个字节表示,因此每个分量的取值范围从0到255;对于灰度图像,每个像素通常用一个分量表示,一

14、个分量同样由一个字节表示,取值范围从0到255。由于本文不会涉及到索引图像,因此这里略去对索引图像的说明。在libjpeg中,图像数据是以扫描线的形式存放的。每一条扫描线由一行像素点构成,像素点沿着扫描线从左到右依次排列。对于彩色图像,每个分量由三个字节组成,因此这三个字节以R、G、B的顺序构成扫描线上的一个像素点。一个典型的扫描线形式如下: R,G,B,R,G,B,R,G,B,通过libjpeg解压出来的图像数据也是以扫描线的形式存放的。在本文中,只涉及到JPEG的解压缩,因此只对libjpeg的解压过程进行说明,有关libjpeg的压缩过程和其它高级用法,请参考3。一般地,libjpeg的

15、解压过程如下:1、分配并初始化一个JPEG解压对象(本文中将JPEG解压对象命名为cinfo): struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; . cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo);2、指定要解压缩的图像文件: FILE * infile; . if (infile = fopen(filename, rb) = NULL) fprintf(stderr, cant open %sn, filename); exi

16、t(1); jpeg_stdio_src(&cinfo, infile);3、调用jpeg_read_header()获取图像信息: jpeg_read_header(&cinfo, TRUE);4、这是一个可选步骤,用于设置JPEG解压缩对象cinfo的一些参数,本文可忽略;5、调用jpeg_start_decompress()开始解压过程: jpeg_start_decompress(&cinfo);调用jpeg_start_decompress()函数之后,JPEG解压缩对象cinfo中的下面这几个字段将会比较有用:l output_width 这是图像输出的宽度l output_hei

17、ght 这是图像输出的高度l output_components 每个像素的分量数,也即字节数这是因为在调用jpeg_start_decompress()之后往往需要为解压后的扫描线上的所有像素点分配存储空间,这个空间的大小可以通过output_width * output_componets确定,而要读取的扫描线的总数为output_height行。6、读取一行或者多行扫描线数据并处理,通常的代码是这样的: while (cinfo.output_scanline cinfo.ouput_height) jpeg_read_scanlines(); /* deal with scanline

18、s */ 对扫描线的读取是按照从上到下的顺序进行的,也就是说图像最上方的扫描线最先被jpeg_read_scanlines()读入存储空间中,紧接着是第二个扫描线,最后是图像底边的扫描线被读入存储空间中。7、调用jpeg_finish_decompress()完成解压过程: jpeg_finish_decompress(&cinfo);8、调用jpeg_destroy_decompress()释放JPEG解压对象cinfo: jpeg_destroy_decompress(&cinfo);以上就是通过libjpeg函数解压JPEG压缩图像的基本过程,由于本文不涉及libjpeg的高级特性和用法

19、,因此,上面的介绍对于说明本文中要用到的libjpeg的功能已经足够了。另外一个需要说明地方是:由于作者所用的Framebuffer设备的颜色深度为16位,颜色格式为5-6-5格式即R(红色)在16bit中占据高5位,G(绿色)在16bit中占据中间6位,B(蓝色)在16bit中占据低5位;而libjpeg解压出来的图像数据为24位RGB格式,因此必须进行转换。对于24位的RGB,每个字节表示一个颜色分量,因此转换的方式为:对于R字节,右移3位,对于G字节,右移2位,对于B字节,右移3位,然后将右移得到的值拼接起来,就得到了16位的颜色值。在后面的程序中,将把24位的颜色称为RGB888,而把

20、16位颜色值称为RGB565,这种命名方式可能不太规范,不过无论如何,在本文中就这样称呼了。另外,读者可能会想到,上面这种直接将颜色分量的低位丢弃的方式不是会导致图像细节的丢失吗?比如,对于24位颜色的R字节,假如原来低3位的值在07之间均匀分布,转换之后,所有这低3位的值全部都变成了0,这就是颜色细节的丢失。为了处理这个问题,可以采用误差扩散算法或者抖动算法来完成颜色转换。为了保持程序的简单,本文中仍然只采用上面提到的最简单的转换方式而且事实表明,这样做得到的结果并不差。4、程序实现以下就是程序的完整实现,鉴于已经对Framebuffer和libjpeg的编程接口做了说明,以下不再对代码进行

21、说明:/* * $Id: fv.c * $Desp: draw jpeg to framebuffer * $Author: rockins * $Date: Wed Jan 3 20:15:49 CST 2007 */#include #include #include #include #include #include #include #include #include #define FB_DEV /dev/fb0/* function declaration */void usage(char *msg);unsigned short RGB888toRGB565(unsigned

22、 char red, unsigned char green, unsigned char blue);int fb_open(char *fb_device);int fb_close(int fd);int fb_stat(int fd, int *width, int *height, int *depth);void *fb_mmap(int fd, unsigned int screensize);int fb_munmap(void *start, size_t length);int fb_pixel(void *fbmem, int width, int height, int

23、 x, int y, unsigned short color);/* function implementation */intmain(int argc, char *argv) /* * declaration for jpeg decompression */ struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; FILE *infile; unsigned char *buffer; /* * declaration for framebuffer device */ int fbdev; char *fb_

24、device; unsigned char *fbmem; unsigned int screensize; unsigned int fb_width; unsigned int fb_height; unsigned int fb_depth; unsigned int x; unsigned int y; /* * check auguments */ if (argc != 2) usage(insuffient auguments); exit(-1); /* * open framebuffer device */ if (fb_device = getenv(FRAMEBUFFE

25、R) = NULL) fb_device = FB_DEV; fbdev = fb_open(fb_device); /* * get status of framebuffer device */ fb_stat(fbdev, &fb_width, &fb_height, &fb_depth); /* * map framebuffer device to shared memory */ screensize = fb_width * fb_height * fb_depth / 8; fbmem = fb_mmap(fbdev, screensize); /* * open input

26、jpeg file */ if (infile = fopen(argv1, rb) = NULL) fprintf(stderr, open %s failedn, argv1); exit(-1); /* * init jpeg decompress object error handler */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); /* * bind jpeg decompress object to infile */ jpeg_stdio_src(&cinfo, infile); /*

27、* read jpeg header */ jpeg_read_header(&cinfo, TRUE); /* * decompress process. * note: after jpeg_start_decompress() is called * the dimension infomation will be known, * so allocate memory buffer for scanline immediately */ jpeg_start_decompress(&cinfo); if (cinfo.output_width fb_width) | (cinfo.ou

28、tput_height fb_height) printf(too large JPEG file,cannot displayn); return (-1); buffer = (unsigned char *) malloc(cinfo.output_width * cinfo.output_components); y = 0; while (cinfo.output_scanline cinfo.output_height) jpeg_read_scanlines(&cinfo, &buffer, 1); if (fb_depth = 16) unsigned short color;

29、 for (x = 0; x cinfo.output_width; x+) color = RGB888toRGB565(bufferx * 3, bufferx * 3 + 1, bufferx * 3 + 2); fb_pixel(fbmem, fb_width, fb_height, x, y, color); else if (fb_depth = 24) memcpy(unsigned char *) fbmem + y * fb_width * 3, buffer, cinfo.output_width * cinfo.output_components); y+; / next

30、 scanline /* * finish decompress, destroy decompress object */ jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); /* * release memory buffer */ free(buffer); /* * close jpeg inputing file */ fclose(infile); /* * unmap framebuffers shared memory */ fb_munmap(fbmem, screensize); /* * close framebuffer device */ fb_close(fbdev); return (0);voidusage(char *msg) fprintf(stderr, %sn, msg); printf(Usage: fv some-jpeg-file.jpgn);/* * convert 24bit RGB888 to 16bit RGB565 color format */unsigned shortRGB888toRGB565(unsigned c

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1