• 使用libjpeg库解码jpg图片 libjpeg版本:v6b 运行环境:arm /* *函数功能:解码jpg图片,存储解码出来的数据 *函数参数:pPic记录源jpg图片解码得到图片宽高、位深度、显示数据 *返回值 :解码正确返回0...

    libjpeg版本:v6b
    运行环境:arm

    /*
     *函数功能:解码jpg图片,存储解码出来的数据
     *函数参数:pPic记录源jpg图片,解码得到图片宽高、位深度、显示数据
     *返回值  :解码正确返回0,错误返回-1
     */
    int jpg_analyze (struct pic_info *pPic)
    {
    	struct jpeg_decompress_struct cinfo; //解压参数
    	struct my_error_mgr jerr;
    	FILE * infile;				//指向打开图片的指针	
     	char * buffer = NULL;       //指向解码行数据的指针
     	int row_stride;				//解码出来的一行图片信息的字节数
    	
    	if ((infile = fopen(pPic->pathname, "rb")) == NULL) {
      	  	fprintf(stderr, "can't open %s\n", pPic->pathname);
        	return -1;
      	}
    
    	//第1步:申请和初始化JPEG解压目标
    	cinfo.err = jpeg_std_error(&jerr.pub); //输出型参数
      	jerr.pub.error_exit = my_error_exit;	
    	if (setjmp(jerr.setjmp_buffer)) {
        	jpeg_destroy_decompress(&cinfo);
        	fclose(infile);
        	return -1;
     	}
    	//给解码器作必要的内存分配和数据结构的初始化
    	jpeg_create_decompress(&cinfo); 
    	
    	//第2步:将fopen打开的源jpg图片和解码器相关联
    	jpeg_stdio_src(&cinfo, infile);
    
    	//第3步:读取图片头信息
    	(void) jpeg_read_header(&cinfo, TRUE);
    	
    	//第4步:开始解码
    	(void) jpeg_start_decompress(&cinfo);
    	row_stride = cinfo.output_width * cinfo.output_components; //一行的字节数
    	buffer = (char *)malloc(row_stride); 	//申请一行的空间
    	if (NULL == buffer) {
    		fprintf(stderr, "cinfo.mem->alloc_sarray error.\n");
    		return -1;
    	}
    
    	//第5步:逐行解码,并将解码出的数据存到buffer中
    	while (cinfo.output_scanline < cinfo.output_height) {
    		jpeg_read_scanlines(&cinfo, &buffer, 1);
    		//将buffer中的一行数据移到数据缓冲区中
    		memcpy(pPic->pData + (cinfo.output_scanline-1*row_stride, buffer, row_stride);
    	}
    
    	pPic->bpp = cinfo.output_components*8; 
    	pPic->height = cinfo.image_height;
    	pPic->width = cinfo.image_width;	
    
    	//第6步:结束解码
    	(void) jpeg_finish_decompress(&cinfo);
    
    	//第7步:释放解码目标
    	jpeg_destroy_decompress(&cinfo);
    	fclose(infile);
    
    	return 0;
    }
    
    typedef struct pic_info {
    	char *pathname; 	  //图片在系统中的文件名加路径名
    	unsigned int width;   //宽
    	unsigned int height;  //高
    	unsigned int bpp;     //位深度
    	unsigned char *pData; //指向图片数据缓冲区
    } pic_info;
    

    note:执行读取函数jpeg_read_scanlines(),第一次读取出来的数据全是0000,所以存储数据的时候需要丢掉第一次读取的数据,操作就是pPic->pData + (cinfo.output_scanline-1)*row_stride,更改指针指向。

    数据处理过程:

    展开全文
  • 通常情况下,在Linux控制台下是无法查看图像文件的,要想查看图像文件,比如要查看JPEG格式的图像文件,可能必须启动X-Windows,通过GNOME或者KDE之类的桌面管理器提供的图像查看工具查看图片内容。那么,能不能有...
    在Linux控制台下显示JPEG图像 http://blog.sina.com.cn/s/blog_3f554a0f010007z4.html
     
    1、引言

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

    目前Linux上的底层图形支持通常是由Framebuffer提供的,因此,作者试图在本文中说明如何通过Framebuffer和libjpeg在控制台上显示JPEG图像。需要说明的是,本文中所编写的程序fv并非zgv的替代品,而只是一个出于验证想法的简单程序(fv的含义是Framebuffer Vision)。本文将先对Framebuffer和libjpeg的编程做一个简略的说明,然后再给出程序fv的具体实现。
    2、Framebuffer介绍

    Framebuffer在Linux中是作为设备来实现的,它是对图形硬件的一种抽象[1],代表着显卡中的帧缓冲区(Framebuffer)。通过Framebuffer设备,上层软件可以通过一个良好定义的软件接口访问图形硬件,而不需要关心底层图形硬件是如何工作的,比如,上层软件不用关心应该如何读写显卡寄存器,也不需要知道显卡中的帧缓冲区从什么地址开始,所有这些工作都由Framebuffer去处理,上层软件只需要集中精力在自己要做的事情上就是了。

    Framebuffer的优点在于它是一种低级的通用设备,而且能够跨平台工作,比如Framebuffer既可以工作在x86平台上,也能工作在PPC平台上,甚至也能工作在m68k和SPARC等平台上,在很多嵌入式设备上Framebuffer也能正常工作。诸如Minigui之类的GUI软件包也倾向于采用Framebuffer作为硬件抽象层(HAL)。

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

    从程序员的角度来看,Framebuffer设备其实就是一个文件而已,可以像对待普通文件那样读写Framebuffer设备文件,可以通过mmap()将其映射到内存中,也可以通过ioctl()读取或者设置其参数,等等。最常见的用法是将Framebuffer设备通过mmap()映射到内存中,这样可以大大提高IO效率。

    要在PC平台上启用Framebuffer,首先必须要内核支持,这通常需要重新编译内核。另外,还需要修改内核启动参数。在作者的系统上,为了启用Framebuffer,需要将/boot/grub/menu.lst中的下面这一行:

    kernel /boot/vmlinuz-2.4.20-8 ro root=LABEL=/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操作。又由于mmap()能够大大降低IO的开销,因此与Framebuffer设备有关的IO通常都是通过mmap()系统调用来完成的。mmap()的函数原型如下(Linux系统上的定义):

    #include <sys/mman.h>

    #ifdef _POSIX_MAPPED_FILES

     

    void  *  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,是指将一个磁盘文件的内容与内存中的一个空间相映射。当从这个映射内存空间中取数据时,就相当于从文件中读取相应的字节,而当向此映射内存空间写入数据时,就相当于向磁盘文件中写入数据。这就是内存映射IO的含义。

    具体到对mmap()而言,当调用成功时,返回值就是与磁盘文件建立了映射关系的内存空间的起始地址,当调用失败时,mmap()的返回值是-1。第一个参数start通常设置为0,表示由系统选择映射内存空间;第二个参数length指定了要映射的字节数;第三个参数指明了映射内存空间的保护属性,对于Framebuffer通常将其设置为PROT_READ | PROT_WRITE,表示既可读也可写;第四个参数flags指明了影响映射内存空间行为的标志,对于Framebuffer编程而言,要将flags设置为MAP_SHARED,表明当向映射内存空间写入数据时,将数据写入磁盘文件中;第五个参数fd是要映射的文件的文件描述符;第六个参数offset指明了要映射的字节在文件中的偏移量。

    如果mmap()调用成功,就可以在程序中对得到的映射内存空间进行读写操作了。所有的读写都将由操作系统内核转换成IO操作。

    在使用完映射内存空间之后,应当将其释放,这是通过munmap()系统调用完成的。munmap()的第一个参数是映射内存空间的起始地址,第二个参数length是映射内存空间的长度,单位为字节。如果释放成功,munmap()返回0,否则返回-1。

    如果应用程序需要知道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位整型数。
    3、libjpeg函数库介绍

    JPEG是CCITT和ISO定义的一种连续色调图像压缩标准[2]。JPEG是一种有损图像压缩标准,其基础是DCT变换(离散余弦变换)。JPEG图像的压缩过程分为三步:DCT计算,量化,变长编码分配。尽管CCITT定义了JPEG图像压缩标准,但是却并没有为JPEG定义标准的文件格式。这导致了现实世界中出现了各种各样的JPEG文件格式,而一种被称为JFIF的JPEG文件格式逐渐成为JPEG文件格式的主流。

    libjpeg是一个被广泛使用的JPEG压缩/解压缩函数库(至少在Unix类系统下是广泛使用的),它能够读写JFIF格式的JPEG图像文件,通常这类文件是以.jpg或者.jpeg为后缀名的。通过libjpeg库,应用程序可以每次从JPEG压缩图像中读取一个或多个扫描线(scanline,所谓扫描线,是指由一行像素点构成的一条图像线条),而诸如颜色空间转换、降采样/增采样、颜色量化之类的工作则都由libjpeg去完成了。

    要使用libjpeg,需要读者对数字图像的基本知识有初步的了解。对于libjpeg而言,图像数据是一个二维的像素矩阵。对于彩色图像,每个像素通常用三个分量表示,即R(Red)、G(Green)、B(Blue)三个分量,每个分量用一个字节表示,因此每个分量的取值范围从0到255;对于灰度图像,每个像素通常用一个分量表示,一个分量同样由一个字节表示,取值范围从0到255。由于本文不会涉及到索引图像,因此这里略去对索引图像的说明。

    在libjpeg中,图像数据是以扫描线的形式存放的。每一条扫描线由一行像素点构成,像素点沿着扫描线从左到右依次排列。对于彩色图像,每个分量由三个字节组成,因此这三个字节以R、G、B的顺序构成扫描线上的一个像素点。一个典型的扫描线形式如下:

           R,G,B,R,G,B,R,G,B,…

    通过libjpeg解压出来的图像数据也是以扫描线的形式存放的。

    在本文中,只涉及到JPEG的解压缩,因此只对libjpeg的解压过程进行说明,有关libjpeg的压缩过程和其它高级用法,请参考[3]。一般地,libjpeg的解压过程如下:

    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, "can't open %s\n", filename);

            exit(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_height                这是图像输出的高度

    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 scanlines */

           }

    对扫描线的读取是按照从上到下的顺序进行的,也就是说图像最上方的扫描线最先被jpeg_read_scanlines()读入存储空间中,紧接着是第二个扫描线,最后是图像底边的扫描线被读入存储空间中。

    7、调用jpeg_finish_decompress()完成解压过程:

        jpeg_finish_decompress(&cinfo);

    8、调用jpeg_destroy_decompress()释放JPEG解压对象cinfo:

        jpeg_destroy_decompress(&cinfo);

    以上就是通过libjpeg函数解压JPEG压缩图像的基本过程,由于本文不涉及libjpeg的高级特性和用法,因此,上面的介绍对于说明本文中要用到的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,而把16位颜色值称为RGB565,这种命名方式可能不太规范,不过无论如何,在本文中就这样称呼了。另外,读者可能会想到,上面这种直接将颜色分量的低位丢弃的方式不是会导致图像细节的丢失吗?比如,对于24位颜色的R字节,假如原来低3位的值在0~7之间均匀分布,转换之后,所有这低3位的值全部都变成了0,这就是颜色细节的丢失。为了处理这个问题,可以采用误差扩散算法或者抖动算法来完成颜色转换。为了保持程序的简单,本文中仍然只采用上面提到的最简单的转换方式——而且事实表明,这样做得到的结果并不差。


    4、结论

    上述测试结果表明,通过Framebuffer在控制台显示JPEG图像是能够实现的,并且效果能够接受。但是,程序fv目前只能接受JPEG格式的图像,并且图像大小不能超出屏幕大小范围,比如,对于作者测试时所用的Framebuffer设置而言,大小超过800x600的图像是无法显示的。显然,可以通过图像缩放来显示超出屏幕大小的JPEG图像。其次,也可以让fv能够识别更多格式的图像,比如可以通过libpng识别并显示png格式的图像。最后,fv还可以考虑采用误差扩散算法或者抖动算法来完成颜色转换,以减小颜色丢失。
    展开全文
  • 解码png图片的库

    2020-06-03 23:32:51
    此库可以用来解析png图片,已在linux环境中测试通过。
  • 里面涉及到一步关于Linux图片格式转换的内容,网上找到了这款ImageMagick的软件,提供的功能很多,支持png,jpg,gif,pdf等许多种图片格式的互相转换,而且开源,使用起来非常方便。  首先在这个网站上可以找到...

    转载自:http://www.xgezhang.com/linux_imagemagick.html


        最近需要用到一些Linux下图片格式转换的内容,网上找到了这款ImageMagick的软件,提供的功能很多,支持png,jpg,gif,pdf等许多种图片格式的互相转换,而且开源,使用起来非常方便。

        首先在这个网站上可以找到下载包:http://www.imagemagick.org/

        按照操作指南下载到tar.gz的安装包,解压之后进行3部安装。

       ./configure
        make
        make install


        默认设置安装位置是在/usr/local/bin下面,环境变量一般已经有了.

        第一次安装成功之后可以尝试使用convert命令对图像文件进行格式转换,比如把目录下的test.jpg 转换成test.png可以输入命令convert test.jpg test.png,其他复杂的操作可以参看官方网站提供的文档,也可以在安装好之后使用man 指令。

        在转换(png,.jpeg)的过程中可能会出现以下提示convert: no decode delegate for this image format,这是因为程序执行的时候需要一些其他的库来支持,比如支持png和支持jpeg的库,使用convert -list format指令可以查看目前ImageMagick支持的转化文件的格式,http://www.imagemagick.org/download/delegates/网站可以下载对应格式的库.比如libpng等,下载之后解压安装,具体安装方式参看文件中的README。ubuntu,debian用户也可以用sudo apt-get install 命令来安装。

    apt-get install libpng-dev 
    apt-get install libjpeg-dev
     

        然后再尝试以下convert test1.jpg test2.pdf,成功! 当然Imagemagick还提供了丰富的功能,具体内容这里就不详述了,大家可以自行阅读官方说明文档。

    展开全文
  • 显示的图片由参数指定,上面指令中test.bmp为测试用的bmp格式的图片 效果 源码说明 代码说明 有部分代码需要注意一下 显示屏设备节点 默认使用的是/dev/fb0这个节点,如果开发板的不是这个,需要改动 显示屏...

    功能

    在嵌入式linux上, 通过操作framebuffer, 直接在显示屏上显示bmp图片
    之前网上找的一些类似功能的都不靠谱, 于是自己写了一个测试程序

    使用方法

    编译后拷贝进开发板即可使用

    ./fb_show_bmp test.bmp
    

    显示的图片由参数指定,上面指令中test.bmp为测试用的bmp格式的图片

    效果

    在这里插入图片描述

    源码说明

    代码说明

    有部分代码需要注意一下

    1. 显示屏设备节点
      在这里插入图片描述
      默认使用的是/dev/fb0这个节点,如果开发板的不是这个,需要改动

    2. 显示屏显示一行像素的数据长度
      显示屏一行的数据长度由 struce fb_fix_screeninfo 中的 line_length 字段决定, 而通过屏幕的分辨率计算得到的一行的数据量不一定准确.
      例如一个显示屏是 800x480, bpp为32, 直接计算一行的数据长度为: 800 * (32 / 8) 个字节
      但是这样计算不一定准确, 还与驱动的实现方式有关, 所以最好还是直接使用 line_length 字段
      在这里插入图片描述

    3. bmp格式问题
      bmp图片的数据对于显示屏来说像是上下左右颠倒了, 所以进行转换时需要处理一下
      函数 cursor_bitmap_format_convert()进行了一行显示数据的左右处理
      上下方向上的数据我没有进行处理, 所以最终效果看起来是上下颠倒的

    4. 显示屏bpp
      我只测试了bpp为24/32的板子, 对于bpp为16的如果测试有问题, 可能还需要在修改下代码
      在这里插入图片描述

    源码

    源码与一些测试用的bmp图片可在这里下载: https://download.csdn.net/download/bruno_mars/11267270

    • fb_show_bmp.c
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <string.h>
    #include <linux/fb.h>
    #include <sys/mman.h>
    #include <sys/ioctl.h>
    #include <arpa/inet.h>
    #include <errno.h>
    
    //14byte文件头
    typedef struct
    {
    	char cfType[2];  //文件类型,"BM"(0x4D42)
    	int  cfSize;     //文件大小(字节)
    	int  cfReserved; //保留,值为0
    	int  cfoffBits;  //数据区相对于文件头的偏移量(字节)
    }__attribute__((packed)) BITMAPFILEHEADER;
    //__attribute__((packed))的作用是告诉编译器取消结构在编译过程中的优化对齐
    
    //40byte信息头
    typedef struct
    {
    	char ciSize[4];          //BITMAPFILEHEADER所占的字节数
    	int  ciWidth;            //宽度
    	int  ciHeight;           //高度
    	char ciPlanes[2];        //目标设备的位平面数,值为1
    	int  ciBitCount;         //每个像素的位数
    	char ciCompress[4];      //压缩说明
    	char ciSizeImage[4];     //用字节表示的图像大小,该数据必须是4的倍数
    	char ciXPelsPerMeter[4]; //目标设备的水平像素数/米
    	char ciYPelsPerMeter[4]; //目标设备的垂直像素数/米
    	char ciClrUsed[4];       //位图使用调色板的颜色数
    	char ciClrImportant[4];  //指定重要的颜色数,当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要
    }__attribute__((packed)) BITMAPINFOHEADER;
    
    typedef struct
    {
    	unsigned char blue;
    	unsigned char green;
    	unsigned char red;
    	unsigned char reserved;
    }__attribute__((packed)) PIXEL; //颜色模式RGB
    
    
    
    typedef struct
    {
    	int          fbfd;
    	char         *fbp;
    	unsigned int xres;
    	unsigned int yres;
    	unsigned int xres_virtual;
    	unsigned int yres_virtual;
    	unsigned int xoffset;
    	unsigned int yoffset;
    	unsigned int bpp;
    	unsigned long line_length;
    	unsigned long size;
    
    	struct fb_bitfield red;
    	struct fb_bitfield green;
    	struct fb_bitfield blue;
    } FB_INFO;
    
    typedef struct
    {
    	unsigned int width;
    	unsigned int height;
    	unsigned int bpp;
    	unsigned long size;
    	unsigned int data_offset;
    } IMG_INFO;
    
    
    
    FB_INFO fb_info;
    IMG_INFO img_info;
    
    int show_bmp(char *img_name);
    
    static int cursor_bitmap_format_convert(char *dst,char *src, unsigned long img_len_one_line)
    {
    	int img_len ,fb_len ;
    	char *p;
    	__u32 val;
    	PIXEL pix;
    
    	p = (char *)&val;
    
    	img_len = img_info.width; /*一行图片的长度*/
    	fb_len = fb_info.xres; /*一行显示屏的长度*/
    
    	/*进行x轴的偏移*/
    	dst += fb_info.xoffset * (fb_info.bpp / 8);
    	fb_len -= fb_info.xoffset;
    
    	/*bmp 数据是上下左右颠倒的,这里只进行左右的处理*/
    	/*先定位到图片的最后一个像素的地址,然后往第一个像素的方向处理,进行左右颠倒的处理*/
    	src += img_len_one_line - 1;
    
    	/*处理一行要显示的数据*/
    	while(1) {
    		if (img_info.bpp == 32)
    			pix.reserved = *(src--);
    		pix.red   = *(src--);
    		pix.green = *(src--);
    		pix.blue  = *(src--);
    
    		val = 0x00;
    		val |= (pix.red >> (8 - fb_info.red.length)) << fb_info.red.offset;
    		val |= (pix.green >> (8 - fb_info.green.length)) << fb_info.green.offset;
    		val |= (pix.blue >> (8 - fb_info.blue.length)) << fb_info.blue.offset;
    
    
    		if (fb_info.bpp == 16) {
    			*(dst++) = *(p + 0);
    			*(dst++) = *(p + 1);
    		}
    		else if (fb_info.bpp == 24) {
    			*(dst++) = *(p + 0);
    			*(dst++) = *(p + 1);
    			*(dst++) = *(p + 2);
    		}
    		else if (fb_info.bpp == 32) {
    			*(dst++) = *(p + 0);
    			*(dst++) = *(p + 1);
    			*(dst++) = *(p + 2);
    			*(dst++) = *(p + 3);
    		}
    
    		/*超过图片长度或显示屏长度认为一行处理完了*/
    		img_len--;
    		fb_len--;
    		if (img_len <= 0 || fb_len <= 0)
    			break;
    	}
    #if 0
    	printf("r = %d\n", pix.red);
    	printf("g = %d\n", pix.green);
    	printf("b = %d\n", pix.blue);
    #endif
    	return 0;
    }
    
    int show_bmp(char *img_name)
    {
    
    	FILE *fp;
    	int ret = 0;
    	BITMAPFILEHEADER FileHead;
    	BITMAPINFOHEADER InfoHead;
    
    	if(img_name == NULL) {
    		printf("img_name is null\n");
    		return -1;
    	}
    
    	fp = fopen( img_name, "rb" );
    	if(fp == NULL) {
    		printf("img[%s] open failed\n", img_name);
    		ret = -1;
    		goto err_showbmp;
    	}
    
    	/* 移位到文件头部 */
    	fseek(fp, 0, SEEK_SET);
    
    	ret = fread(&FileHead, sizeof(BITMAPFILEHEADER), 1, fp);
    	if ( ret != 1) {
    		printf("img read failed\n");
    		ret = -1;
    		goto err_showbmp;
    	}
    
    	//检测是否是bmp图像
    	if (memcmp(FileHead.cfType, "BM", 2) != 0) {
    		printf("it's not a BMP file[%c%c]\n", FileHead.cfType[0], FileHead.cfType[1]);
    		ret = -1;
    		goto err_showbmp;
    	}
    
    	ret = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
    	if ( ret != 1) {
    		printf("read infoheader error!\n");
    		ret = -1;
    		goto err_showbmp;
    	}
    
    	img_info.width       = InfoHead.ciWidth;
    	img_info.height      = InfoHead.ciHeight;
    	img_info.bpp         = InfoHead.ciBitCount;
    	img_info.size        = FileHead.cfSize;
    	img_info.data_offset = FileHead.cfoffBits;
    
    	printf("img info w[%d] h[%d] bpp[%d] size[%ld] offset[%d]\n", img_info.width, img_info.height, img_info.bpp, img_info.size, img_info.data_offset);
    
    	if (img_info.bpp != 24 && img_info.bpp != 32) {
    		printf("img bpp is not 24 or 32\n");
    		ret = -1;
    		goto err_showbmp;
    	}
    
    
    	/*
    	 *一行行处理
    	 */
    	char *buf_img_one_line;
    	char *buf_fb_one_line;
    	char *p;
    	int fb_height;
    
    	long img_len_one_line = img_info.width * (img_info.bpp / 8);
    	long fb_len_one_line = fb_info.line_length;
    
    	printf("img_len_one_line = %d\n", img_len_one_line);
    	printf("fb_len_one_line = %d\n", fb_info.line_length);
    
    	buf_img_one_line = (char *)calloc(1, img_len_one_line + 256);
    	if(buf_img_one_line == NULL) {
    		printf("alloc failed\n");
    		ret = -1;
    		goto err_showbmp;
    	}
    
    	buf_fb_one_line = (char *)calloc(1, fb_len_one_line + 256);
    	if(buf_fb_one_line == NULL) {
    		printf("alloc failed\n");
    		ret = -1;
    		goto err_showbmp;
    	}
    
    
    	fseek(fp, img_info.data_offset, SEEK_SET);
    
    	p = fb_info.fbp + fb_info.yoffset * fb_info.line_length; /*进行y轴的偏移*/
    	fb_height = fb_info.yres;
    	while (1) {
    		memset(buf_img_one_line, 0, img_len_one_line);
    		memset(buf_fb_one_line, 0, fb_len_one_line);
    		ret = fread(buf_img_one_line, 1, img_len_one_line, fp);
    		if (ret < img_len_one_line) {
    			/*图片读取完成,则图片显示完成*/
    			printf("read to end of img file\n");
    			cursor_bitmap_format_convert(buf_fb_one_line, buf_img_one_line, img_len_one_line); /*数据转换*/
    			memcpy(fb_info.fbp, buf_fb_one_line, fb_len_one_line);
    			break;
    		}
    
    		cursor_bitmap_format_convert(buf_fb_one_line, buf_img_one_line, img_len_one_line); /*数据转换*/
    		memcpy(p, buf_fb_one_line, fb_len_one_line); /*显示一行*/
    		p += fb_len_one_line;
    
    		/*超过显示屏宽度认为图片显示完成*/
    		fb_height--;
    		if (fb_height <= 0)
    			break;
    	}
    
    	free(buf_img_one_line);
    	free(buf_fb_one_line);
    
    	fclose(fp);
    	return ret;
    err_showbmp:
    	if (fp)
    		fclose(fp);
    	return ret;
    }
    
    int show_picture(char *img_name)
    {
    	struct fb_var_screeninfo vinfo;
    	struct fb_fix_screeninfo finfo;
    
    	if (fb_info.fbfd <= -1) {
    		printf("fb open fialed\n");
    		return -1;
    	}
    
    	if (ioctl(fb_info.fbfd, FBIOGET_FSCREENINFO, &finfo)) {
    		printf("fb ioctl fialed\n");
    		return -1;
    	}
    
    	if (ioctl(fb_info.fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
    		printf("fb ioctl fialed\n");
    		return -1;
    	}
    
    	fb_info.xres = vinfo.xres;
    	fb_info.yres = vinfo.yres;
    	fb_info.xres_virtual = vinfo.xres_virtual;
    	fb_info.yres_virtual = vinfo.yres_virtual;
    	fb_info.xoffset = vinfo.xoffset;
    	fb_info.yoffset = vinfo.yoffset;
    	fb_info.bpp  = vinfo.bits_per_pixel;
    	fb_info.line_length = finfo.line_length;
    	fb_info.size = finfo.smem_len;
    
    	memcpy(&fb_info.red, &vinfo.red, sizeof(struct fb_bitfield));
    	memcpy(&fb_info.green, &vinfo.green, sizeof(struct fb_bitfield));
    	memcpy(&fb_info.blue, &vinfo.blue, sizeof(struct fb_bitfield));
    
    	printf("fb info x[%d] y[%d] x_v[%d] y_v[%d] xoffset[%d] yoffset[%d] bpp[%d] line_length[%ld] size[%ld]\n", fb_info.xres, fb_info.yres, fb_info.xres_virtual, fb_info.yres_virtual, fb_info.xoffset, fb_info.yoffset, fb_info.bpp, fb_info.line_length, fb_info.size);
    
    	printf("fb info red off[%d] len[%d] msb[%d]\n", fb_info.red.offset, fb_info.red.length, fb_info.red.msb_right);
    	printf("fb info green off[%d] len[%d] msb[%d]\n", fb_info.green.offset, fb_info.green.length, fb_info.green.msb_right);
    	printf("fb info blue off[%d] len[%d] msb[%d]\n", fb_info.blue.offset, fb_info.blue.length, fb_info.blue.msb_right);
    
    	if (fb_info.bpp != 16 && fb_info.bpp != 24 && fb_info.bpp != 32) {
    		printf("fb bpp is not 16,24 or 32\n");
    		return -1;
    	}
    
    	if (fb_info.red.length > 8 || fb_info.green.length > 8 || fb_info.blue.length > 8) {
    		printf("fb red|green|blue length is invalid\n");
    		return -1;
    	}
    
    	// 内存映射
    	fb_info.fbp = (char *)mmap(0, fb_info.size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_info.fbfd, 0);
    	if (fb_info.fbp == (char *)-1) {
    		printf("mmap fialed\n");
    		return -1;
    	}
    
    	show_bmp(img_name);
    
    	//删除映射
    	munmap(fb_info.fbp, fb_info.size);
    
    	return 0;
    }
    
    
    int main(int argc, char **argv)
    {
    	char img_name[64];
    
    	if (argc != 2) {
    		printf("arg error\n");
    		return 0;
    	}
    
    	snprintf(img_name, sizeof(img_name), "%s", argv[1]);
    	printf("img_name = %s\n", img_name);
    
    	fb_info.fbfd = open("/dev/fb0", O_RDWR);
    	if (!fb_info.fbfd) {
    		printf("Error: cannot open framebuffer device(/dev/fb0).\n");
    		return -1;
    	}
    	show_picture(img_name);
    
    	close(fb_info.fbfd);
    		return 0;
    }
    
    展开全文
  • 嵌入式 linux arm 嵌入式 arm Qt支持jpg格式的图片 arm开发板上,Qt默认支持png格式的图片,对于jpg格式的图片,没有默认支持,若需支持jpg格式的图片,需要作如下操作: 1.qt移植到arm开发板时,编译qt库的时候,...

    嵌入式 linux arm

    嵌入式 arm Qt支持jpg格式的图片

    arm开发板上,Qt默认支持png格式的图片,对于jpg格式的图片,没有默认支持,若需支持jpg格式的图片,需要作如下操作:
    1.qt移植到arm开发板时,编译qt库的时候,需要将参数:-qt-libjpeg 打开(默认好像是打开的),编译库完成后,会在qt源码路径:qt_src/plugins/imageformats/ 下生成一系列的库文件。
    2.将qt的jpeg插件库复制到开发板相应的位置。假如开发板的qt库目录为/lib,则在开发板路径: /lib/ 下创建目录 plugins/imageformats/ ,并将qt源码对应目录下的所有图像库文件拷贝到开发板路径 /lib/plugins/imageformats/ 下。
    3.需要在开发板上增加两个环境变量:修改/etc/profile 文件,在profile文件后修改或者增加两行:
    export LD_LIBRARY_PATH=/lib/plugins/imageformats:$LD_LIBRARY_PATH
    export QT_PLUGIN_PATH=/lib/plugins
    4.在qt的pro文件中增加一行:
    QTPLUGIN += qjpeg

    参考:
    https://blog.csdn.net/zgrjkflmkyc/article/details/23672425

    展开全文
  • 答案是 为了降低其他无关因素对最后的识别结果的影响,比如说一幅图片在不同亮度或是对比度等指标下呈现的效果可能差别特别大,但是这些对于我们来说,不要影响到最后的识别结果,所以这就是预处理最想解决的东西,...
  • 本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。
  • 1.移植libjpeg库 ... 本文主要讲如何把libjpeg库移植到mini2440arm板上。(我用的是友善tiny6410) 我的系统:Fedora11 ...编译工具:arm-linux-gcc 第一步下载libjpeg库 下载地址http://www.ijg
  • 读取bmp文件头信息 文件头信息的格式定义可以参考这里,读取文件信息有两种方式,第一种方式是定义一个字符串,使用read函数将图像信息读取到字符串中,然后我们自己去提取想要的数据。这种方法需要我们提前知道...
  • 使用libpng库解码png图片 解码库版本:libpng-1.6.35 #include &amp;amp;amp;amp;amp;lt;stdlib.h&amp;amp;amp;amp;amp;gt; #include &amp;amp;amp;amp;amp;lt;string.h&amp;amp;amp;amp;amp;...
  • Linux下jpeg解码方法

    2011-01-06 22:47:00
     if ((infile = fopen(jpg_filename, "rb")) == NULL) {  fprintf(stderr, "open %s failed/n", jpg_filename);  return(-1); }   /*  init jpeg decompress object ...
  • 一、crop和pad ...当原图片尺寸大于目标图片时,自动截取原图片居中位置。 本文适用于图片存放形式为: 二、resize 图片由250*250resize为300*300 效果: 对于resize-image: meth...
  • 本文是libwlt2bmp.so相片解码Linux操作系统版本的下载,市场上的libwlt2bmp.so一般都只能支持Android操作系统,不支持Linux操作系统的,有用到的不妨试试看。 支持版本:X86、X64 Linux ARM的Linux由于没有测试...
  • 环境 ubuntu(16.04) ... 问题2: 如何将验证码图片解码成为一串数字?  问题3: 如何再次上交给网页? 以上问题均用C语言实现 先说问题二:如何将验证码图片解码成为一串数字?  这里我们要用到一个软件 叫
  • ffmpeg-解码例程-linux

    2020-06-03 23:32:42
    此例程在linux下实现了读取mp4文件进行解码,分析出I,P,B帧 有助于初学者学习ffmpeg
  • Linux下Base64转码解码

    2020-04-03 18:26:30
    解码:# echo -n "Y2VzaGkxMTEx" | base64 -d 输出: ceshi1111 附: base64命令说明 使用 Base64 编码/解码文件或标准输入输出。 - w, 在指定的字符数后自动换行(默认为76),0 为禁用自动换行 ...
  • 1. 解码屏幕上的二维码,将结果输出在终端 2. 在终端中将字符串转为二维码,直接显示二维码在终端中以供扫描
  • 图片解码播放器2

    2017-03-18 11:33:59
    《朱老师物联网大讲堂》课程学习笔记。 学习地址:www.zhulaoshi.org   24, 如何使用jpeg的库呢? 网上搜, 还有,库里面会有示例代码,以及说明文档,
  • base64编码 base64解码 测试
1 2 3 4 5 ... 20
收藏数 16,920
精华内容 6,768
热门标签