下面是有关JPEG的介绍和相关代码,希望对你有所帮助!
目录
JPEG图片显示
1. JPEG 图像介绍
对于BMP 图像来说,图像没有失真、并且解析简单,但是由于图像数据没有进行任何压缩,因此, BMP 图像文件所占用的存储空间很大,不适合存储在磁盘设备中。
而 JPEG(或 JPG)、 PNG 则是经过压缩处理的图像格式,将图像数据进行压缩编码,大大降低了图像文件的大小, 适合存储在磁盘设备中, 所以很常用。
JPEG(Joint Photographic Experts Group)是由国际标准组织为静态图像所建立的第一个国际数字图像压缩标准,也是至今一直在使用的、应用最广的图像压缩标准。
JPEG 可以提供有损压缩,因此压缩比可以达到其他传统压缩算法无法比拟的程度;
JPEG 虽然是有损压缩,但这个损失的部分是人的视觉不容易察觉到的部分,它充分利用了人眼对计算机色彩中的高频信息部分不敏感的特点,来大大节省了需要处理的数据信息。JPEG 压缩文件通常以.jpg 或.jpeg 作为文件后缀名。
2. libjpeg 简介
JPEG 压缩标准使用了一套压缩算法对原始图像数据进行了压缩得到.jpg 或.jpeg 图像文件,如果想要在 LCD 上显示.jpg 或.jpeg 图像文件,则需要对其进行解压缩、以得到图像的原始数据,譬如 RGB 数据。
既然压缩过程使用了算法,那对.jpg 或.jpeg 图像文件进行解压同样也需要算法来处理
libjpeg 是一个完全用 C 语言编写的函数库,包含了 JPEG 解码(解压缩) 、 JPEG 编码(创建压缩) 和 其他的 JPEG 功能的实现。 可以使用 libjpeg 库对.jpg 或.jpeg 压缩文件进行解压或者生成.jpg 或.jpeg 压缩文件。libjpeg 是一个开源 C 语言库,我们获取到它的源代码。
3. libjpeg 使用说明
libjpeg 提供 JPEG 解码、 JPEG 编码和其他的 JPEG 功能的实现, 下面给大家介绍如何使用libjpeg 提供的库函数对.jpg/.jpeg 进行解码(解压),得到 RGB 数据。
首先,使用 libjpeg 库需要在我们的应用程序中包含它的头文件 jpeglib.h,该头文件包含了一些结构体数据结构以及 API 接口的申明。
先来看看解码操作的过程:
- 创建 jpeg 解码对象
- 指定解码数据源
- 读取图像信息
- 设置解码参数
- 开始解码
- 读取解码后的数据
- 解码完毕
- 释放/销毁解码对象
4.libjpeg 移植
进入网站下载源码包,我选择的是v9b,对应的文件名为 jpegsrc.v9b.tar.gz
Directory Listing of /files (ijg.org)https://www.ijg.org/files/
之后需要编译源码、安装、移植到开发板上,这里我就不操作了,有需要的可以看其他博主的文章!
下面是示例代码,有需要的自取即可!
示例代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include "jpeglib.h"
typedef struct bgr888_color //定义一个 BGR888 颜色类型
{
unsigned char red; //红
unsigned char green; //绿
unsigned char blue; //蓝
} __attribute__ ((packed)) bgr888_t;
unsigned short *fb_base = NULL; //内存映射的起始地址
int width = 1024; //宽
int height = 600; //高
int bpp; //深度值
int jpg_show(const char *path)
{
struct jpeg_decompress_struct jinfo;
struct jpeg_error_mgr jerr;
FILE *jpeg_file = NULL;
bgr888_t *j_buf = NULL; //行缓冲(每行数据)
unsigned short *fb_buf_line = NULL;//显示屏行缓冲
unsigned int min_width,min_height;
int value_width;
//step1.打开文件,可读可写的方式
jpeg_file = fopen(path, "r+");
if(jpeg_file == NULL)
{
perror("fopen error"); //打开失败
return -1;
}
//step2.创建解码对象
jpeg_create_decompress(&jinfo);
//step3.指定图像文件
jpeg_stdio_src(&jinfo, jpeg_file);
//step4.读取图像的信息
jpeg_read_header(&jinfo, TRUE);
printf("size is %d * %d\n", jinfo.image_height, jinfo.image_width);
//step5.配置参数(解码参数)
jinfo.out_color_space = JCS_RGB; //输出的颜色配置为 RGB 颜色
jinfo.scale_num = 1; //将输出图像设置为原图的 1/2 大小
jinfo.scale_denom = 2;
//step6.开始解析图像
jpeg_start_decompress(&jinfo);
//step7.分配内存
j_buf = malloc(jinfo.output_components * jinfo.image_width);
//fb_buf_line = malloc(1024);
if(jinfo.output_width > width)
min_width = width;
else
min_width = jinfo.output_width;
if(jinfo.output_height > height)
min_height = height;
else
min_height = jinfo.output_height;
//step8.读取数据
value_width = min_width * bpp/8; //每行有效字节数
unsigned short *fb_base_tmp = fb_base;
while(jinfo.output_scanline < min_height)
{
jpeg_read_scanlines(&jinfo, (unsigned char **)&j_buf, 1);
/*
//888转565
red + gre
for(int i = 0; i< min_wieth; i++)
{
// red >> 3 <<11 (占5个字节) green>>2 << 5 blue >> 3
fb_buf_line[i] = (j_buf[i].red & 0xF8) << 8 | (j_buf[i].green & 0xFC) << 3 | (j_buf[i].blue & 0xF8) >> 3;
}
*/
//
memcpy(fb_base_tmp, j_buf, value_width);
fb_base_tmp = fb_base_tmp + width;
}
//step9. 释放资源
jpeg_finish_decompress(&jinfo); //完成解码
jpeg_destroy_decompress(&jinfo);//销毁JPEG解码对象、释放资源
fclose(jpeg_file);
free(j_buf);
free(fb_buf_line);
return -1;
}
int main()
{
struct fb_fix_screeninfo fb_fix; //固定参数信息
struct fb_var_screeninfo fb_var; //可变参数信息
unsigned int size; //定义无符号屏幕缓冲区大小
int lcdfd = open("/dev/fb0", O_RDWR); //显示图片信息,以可读可写 打开LCD(显示屏)
if(lcdfd < 0)
{
perror("open lcd error");
exit(-1);
}
//ioctl函数获取显示屏信息并存储
ioctl(lcdfd, FBIOGET_VSCREENINFO, &fb_var);
ioctl(lcdfd, FBIOGET_FSCREENINFO, &fb_fix);
size = fb_fix.line_length * fb_var.yres; //屏幕显示缓冲区的大小
width = fb_var.xres; //屏幕的水平分辨率
height = fb_var.yres; //屏幕的垂直分辨率
int i = 0;
//内存映射
int *fb_base = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, lcdfd, 0);
if(fb_base == NULL)
{
perror("mamp error");
exit(-1);
}
jpg_show("a.jpg");
jpg_show("b.jpg");
munmap(fb_base, size); //取消映射
close(lcdfd); //关闭lcd显示屏
return 1;
}
如果喜欢请不吝给予三连支持!