libjpeg-turbo 的安装和简单使用

大家好,这篇文中介绍了libjpeg-turbo的简单使用,大部分是copy,有一点自己的心得

libjpeg是一款开源的jpeg压缩解压库,具体信息参见百度百科。libjpeg-turbo是它的升级版,性能有所 提升,源码去他的官网可以下载  https://libjpeg-turbo.org/  我用的1.2.1 最新的已经到2.0 

对于libjpeg-turbo的使用官方有详细的说明文档 :

/ ******************** JPEG DECOMPRESSION样本界面******************* /

/ *这个例子的这一半显示了如何从JPEG解压缩器读取数据。
 *这比上面更精致一点,因为我们显示:
 *(a)如何修改JPEG库的标准错误报告行为;
 *(b)如何使用库的内存管理器分配工作区。
 *
 *为了使这个例子与第一个例子有点不同,我们会
 *假设我们不打算将整个图像放入内存中
 *缓冲区,但要将其逐行发送到其他地方。我们需要一个单一的,
 * scanline-high JSAMPLE数组作为工作缓冲区,我们将让JPEG
 内存管理器为我们分配它。这种方法实际上非常有用
 *因为我们不需要记住单独释放缓冲区:它
 *清除JPEG对象时将自动消失。
 * /


/ *
 *错误处理:
 *
 * JPEG库的标准错误处理程序(jerror.c)分为
 *几个“方法”,你可以单独重写。这可以让你
 *调整行为而不重复大量的代码,你可能会这样做
 *必须更新每个未来版本。
 *
 *我们的例子展示了如何覆盖“error_exit”方法
 *发生致命错误时,控制权返回给库的调用者,
 *而不是像标准error_exit方法那样调用exit()。
 *
 *我们使用C的setjmp / longjmp工具来返回控制。这意味着
 *调用JPEG库的例程必须先执行setjmp()调用
 *建立返回点。我们想要更换error_exit来做一个
 * longjmp()。但是我们需要让setjmp缓冲区可以访问
 * error_exit例程。要做到这一点,我们做一个私人的延伸
 *标准的JPEG错误处理程序对象。(如果我们使用C ++,我们会说我们
 *正在制作常规错误处理程序的子类。)
 *
 *这是扩展的错误处理程序结构:
 * /

struct my_error_mgr {
  struct jpeg_error_mgr pub; / *“公共”字段* /

  jmp_buf setjmp_buffer; / *返回给调用者* /
};

typedef struct my_error_mgr * my_error_ptr;

/ *
 *以下是将替换标准error_exit方法的例程:
 * /

METHODDEF(无效)
my_error_exit(j_common_ptr cinfo)
{
  / * cinfo-> err真的指向一个my_error_mgr结构,所以强制指针* /
  my_error_ptr myerr =(my_error_ptr)cinfo-> err;

  / *总是显示消息。* /
  / *如果我们选择了,我们可以推迟到返回之后。* /
  (* cinfo-> err-> output_message)(cinfo);

  / *将控制权返回给setjmp点* /
  longjmp(myerr-> setjmp_buffer,1);
}


/ *
 * JPEG解压缩的示例程序。我们假设源文件名
 *传入。我们希望成功返回1,错误时return 0。
 * /


GLOBAL(INT)
read_JPEG_file(char * filename)
{
  / *此结构包含JPEG解压缩参数和指针
   *工作空间(根据JPEG库的需要分配)。
   * /
  struct jpeg_decompress_struct cinfo;
  / *我们使用我们的专用扩展名JPEG错误处理程序。
   *注意,这个结构必须和主要的JPEG参数一样长
   * struct,以避免悬挂指针问题。
   * /
  struct my_error_mgr jerr;
  /* 更多东西 */
  文件* infile; /* 源文件 */
  JSAMPARRAY缓冲区; / *输出行缓冲区* /
  int row_stride; / *输出缓冲区中的物理行宽度* /

  / *在这个例子中,我们希望在做其他事情之前打开输入文件,
   *以便下面的setjmp()错误恢复可以假定文件已打开。
   *非常重要:如果你在一台机器上,使用“b”选项来打开()
   *需要它来读取二进制文件。
   * /

  if((infile = fopen(filename,“rb”))== NULL){
    fprintf(stderr,“无法打开%s \ n”,文件名);
    return 0;
  }

  / *步骤1:分配并初始化JPEG解压缩对象* /

  / *我们设置正常的JPEG错误例程,然后覆盖error_exit。* /
  cinfo.err = jpeg_std_error(&jerr.pub);
  jerr.pub.error_exit = my_error_exit;
  / *建立my_error_exit使用的setjmp返回上下文。* /
  if(setjmp(jerr.setjmp_buffer)){
    / *如果我们到达这里,JPEG代码会发出错误信号。
     *我们需要清理JPEG对象,关闭输入文件并返回。
     * /
    jpeg_destroy_decompress(&CINFO);
    FCLOSE(infile中);
    return 0;
  }
  / *现在我们可以初始化JPEG解压缩对象。* /
  jpeg_create_decompress(&CINFO);

  / *步骤2:指定数据源(例如文件)* /

  jpeg_stdio_src(&cinfo,infile);

  / *第3步:用jpeg_read_header()读取文件参数* /

  (void)jpeg_read_header(&cinfo,TRUE);
  / *我们可以忽略来自jpeg_read_header的返回值
   *(a)使用stdio数据源无法暂停,并且
   *(b)我们通过TRUE拒绝仅表格JPEG文件作为错误。
   *有关更多信息,请参阅libjpeg.txt。
   * /

  / *第4步:设置解压缩参数* /

  / *在这个例子中,我们不需要改变任何默认设置
   * jpeg_read_header(),所以我们在这里什么都不做。
   * /

  / *步骤5:开始解压缩* /

  (void)jpeg_start_decompress(&cinfo);
  / *由于暂停不可能,我们可以忽略返回值
   *与stdio数据源。
   * /

  / *在阅读之前,我们可能需要在此处进行一些设置
   * 数据。在jpeg_start_decompress()之后,我们有正确的缩放比例
   *输出图像尺寸可用,以及输出颜色图
   *如果我们要求颜色量化。
   *在这个例子中,我们需要制作一个合适大小的输出工作缓冲区。
   * / 
  / *输出缓冲区中每行的JSAMPLEs * /
  row_stride = cinfo.output_width * cinfo.output_components;
  / *制作一行高的样本数组,当完成图像时将消失* /
  buffer =(* cinfo.mem-> alloc_sarray)
		((j_common_ptr)&cinfo,JPOOL_IMAGE,row_stride,1);

  / *第6步:while(扫描行仍有待读取)* /
  / * jpeg_read_scanlines(...); * /

  / *这里我们使用库的状态变量cinfo.output_scanline作为
   *循环计数器,以便我们不必跟踪自己。
   * /
  while(cinfo.output_scanline <cinfo.output_height){
    / * jpeg_read_scanlines需要一个指向扫描线的指针数组。
     *这里的数组只有一个元素长,但你可以要求
     *如果更方便,一次有多个扫描线。
     * /
    (void)jpeg_read_scanlines(&cinfo,buffer,1);
    / *假设put_scanline_someplace需要一个指针和样本数。* /
    put_scanline_someplace(buffer [0],row_stride);
  }

  / *第7步:完成解压缩* /

  (void)jpeg_finish_decompress(&cinfo);
  / *由于暂停不可能,我们可以忽略返回值
   *与stdio数据源。
   * /

  / *第8步:释放JPEG解压缩对象* /

  / *这是一个重要的步骤,因为它会释放大量的内存。* /
  jpeg_destroy_decompress(&CINFO);

  / * finish_decompress之后,我们可以关闭输入文件。
   *在这里我们推迟它,直到没有更多的JPEG错误是可能的,
   *以简化上面的setjmp错误逻辑。(其实,我没有
   *认为jpeg_destroy可以做出错误退出,但为什么会假设任何事情......)
   * /
  FCLOSE(infile中);

  / *此时您可能需要检查是否有任何损坏数据
   *发生警告(测试jerr.pub.num_warnings是否为非零)。
   * /

  / *我们完成了!* /
  return 1;
}

相信一个可以执行的程序更能直观的说明问题 :

/*
功能 : 在LCD上显示一副图片
*/

#include <stdio.h>
#include "jpeglib.h"
#include <setjmp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <string.h>
#include <stdlib.h>

#define FB_DEVICE_NAME "/dev/fb0"
#define DBG_PRINTF printf

static int g_fd;

static struct fb_var_screeninfo g_tFBVar;
static struct fb_fix_screeninfo g_tFBFix;			
static unsigned char *g_pucFBMem;
static unsigned int g_dwScreenSize;

static unsigned int g_dwLineWidth;
static unsigned int g_dwPixelWidth;

static int FBDeviceInit(void)
{
	int ret;
	
	g_fd = open(FB_DEVICE_NAME, O_RDWR);
	if (0 > g_fd)
	{
		DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME);
	}

	ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);
	if (ret < 0)
	{
		DBG_PRINTF("can't get fb's var\n");
		return -1;
	}

	ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);
	if (ret < 0)
	{
		DBG_PRINTF("can't get fb's fix\n");
		return -1;
	}
	
	g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;
	g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);
	if (0 > g_pucFBMem)	
	{
		DBG_PRINTF("can't mmap\n");
		return -1;
	}

	g_dwLineWidth  = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;
	g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;
	
	return 0;
}


static int FBShowPixel(int iX, int iY, unsigned int dwColor)
{
	unsigned char *pucFB;
	unsigned short *pwFB16bpp;
	unsigned int *pdwFB32bpp;
	unsigned short wColor16bpp; /* 565 */
	int iRed;
	int iGreen;
	int iBlue;

	if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres))
	{
		DBG_PRINTF("out of region\n");
		return -1;
	}

	pucFB      = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;
	pwFB16bpp  = (unsigned short *)pucFB;
	pdwFB32bpp = (unsigned int *)pucFB;
	
	switch (g_tFBVar.bits_per_pixel)
	{
		case 8:
		{
			*pucFB = (unsigned char)dwColor;
			break;
		}
		case 16:
		{
			iRed   = (dwColor >> (16+3)) & 0x1f;
			iGreen = (dwColor >> (8+2)) & 0x3f;
			iBlue  = (dwColor >> 3) & 0x1f;
			wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
			*pwFB16bpp	= wColor16bpp;
			break;
		}
		case 32:
		{
			*pdwFB32bpp = dwColor;
			break;
		}
		default :
		{
			DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);
			return -1;
		}
	}

	return 0;
}

static int FBCleanScreen(unsigned int dwBackColor)
{
	unsigned char *pucFB;
	unsigned short *pwFB16bpp;
	unsigned int *pdwFB32bpp;
	unsigned short wColor16bpp; /* 565 */
	int iRed;
	int iGreen;
	int iBlue;
	int i = 0;

	pucFB      = g_pucFBMem;
	pwFB16bpp  = (unsigned short *)pucFB;
	pdwFB32bpp = (unsigned int *)pucFB;

	switch (g_tFBVar.bits_per_pixel)
	{
		case 8:
		{
			memset(g_pucFBMem, dwBackColor, g_dwScreenSize);
			break;
		}
		case 16:
		{
			iRed   = (dwBackColor >> (16+3)) & 0x1f;
			iGreen = (dwBackColor >> (8+2)) & 0x3f;
			iBlue  = (dwBackColor >> 3) & 0x1f;
			wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
			while (i < g_dwScreenSize)
			{
				*pwFB16bpp	= wColor16bpp;
				pwFB16bpp++;
				i += 2;
			}
			break;
		}
		case 32:
		{
			while (i < g_dwScreenSize)
			{
				*pdwFB32bpp	= dwBackColor;
				pdwFB32bpp++;
				i += 4;
			}
			break;
		}
		default :
		{
			DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);
			return -1;
		}
	}

	return 0;
}

static int FBShowLine(int iXStart, int iXEnd, int iY, unsigned char *pucRGBArray)
{
	int i = iXStart * 3;
	int iX;
	unsigned int dwColor;

	if (iY >= g_tFBVar.yres)
		return -1;

	if (iXStart >= g_tFBVar.xres)
		return -1;

	if (iXEnd >= g_tFBVar.xres)
	{
		iXEnd = g_tFBVar.xres;		
	}
	
	for (iX = iXStart; iX < iXEnd; iX++)
	{
		/* 0xRRGGBB */
		dwColor = (pucRGBArray[i]<<16) + (pucRGBArray[i+1]<<8) + (pucRGBArray[i+2]<<0);
		i += 3;
		FBShowPixel(iX, iY, dwColor);
	}
	return 0;
}


/*
Allocate and initialize a JPEG decompression object    // 分配和初始化一个decompression结构体
Specify the source of the compressed data (eg, a file) // 指定源文件
Call jpeg_read_header() to obtain image info		   // 用jpeg_read_header获得jpg信息
Set parameters for decompression					   // 设置解压参数,比如放大、缩小
jpeg_start_decompress(...); 						   // 启动解压:jpeg_start_decompress
while (scan lines remain to be read)
	jpeg_read_scanlines(...);						   // 循环调用jpeg_read_scanlines
jpeg_finish_decompress(...);						   // jpeg_finish_decompress
Release the JPEG decompression object				   // 释放decompression结构体
*/

/* Uage: jpg2rgb <jpg_file>
 */

int main(int argc, char **argv)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	FILE * infile;
	int row_stride;
	unsigned char *buffer;

	if (argc != 2)
	{
		printf("Usage: \n");
		printf("%s <jpg_file>\n", argv[0]);
		return -1;
	}

	if (FBDeviceInit())
	{
		return -1;
	}

	FBCleanScreen(0);

	// 分配和初始化一个decompression结构体
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	// 指定源文件
	if ((infile = fopen(argv[1], "rb")) == NULL) {
		fprintf(stderr, "can't open %s\n", argv[1]);
		return -1;
	}
	jpeg_stdio_src(&cinfo, infile);

	// 用jpeg_read_header获得jpg信息
	jpeg_read_header(&cinfo, TRUE);
	/* 源信息 */
	printf("image_width = %d\n", cinfo.image_width);
	printf("image_height = %d\n", cinfo.image_height);
	printf("num_components = %d\n", cinfo.num_components);

	// 设置解压参数,比如放大、缩小  
	/* 无符号整数scale_num,scale_denom 
	通过scale_num / scale_denom分数缩放图像。默认值是
	1/1,或不缩放。目前,唯一支持的缩放比率
	是M / 8,所有M从1到16,或其任何缩小比例(例如
	1/2,3/4等)(库设计允许任意
	缩放比例,但是这是不太可能很快实施。)
	较小的缩放比例允许显着更快的解码,因为
	需要处理更少的像素并且可以使用更简单的IDCT方法 输入n/m*/
	printf("enter scale M/N:\n");
	scanf("%d/%d", &cinfo.scale_num, &cinfo.scale_denom);
	printf("scale to : %d/%d\n", cinfo.scale_num, cinfo.scale_denom);

	// 启动解压:jpeg_start_decompress	
	jpeg_start_decompress(&cinfo);

	/* 输出的图象的信息 */
	printf("output_width = %d\n", cinfo.output_width);
	printf("output_height = %d\n", cinfo.output_height);
	printf("output_components = %d\n", cinfo.output_components);

	// 一行的数据长度
	row_stride = cinfo.output_width * cinfo.output_components;
	buffer = malloc(row_stride);

	// 循环调用jpeg_read_scanlines来一行一行地获得解压的数据
	while (cinfo.output_scanline < cinfo.output_height) 
	{
		(void) jpeg_read_scanlines(&cinfo, &buffer, 1);

		// 写到LCD去
		FBShowLine(0, cinfo.output_width, cinfo.output_scanline, buffer);
	}
	
	free(buffer);
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);

	return 0;
}


如果你编译报错,记得安装libjpeg-turbo 

tar xzf libjpeg-turbo-1.2.1.tar.gz
cd libjpeg-turbo-1.2.1
./configure --prefix=/usr/local/libjpeg-turbo-1.2.1 --host=arm-linux

make

sudo su 

make install

编译时记得指定头文件和库 :

arm-linux-gcc -o jpg2rgb jpg2rgb.c -I /mnt/hgfs/share/libjpeg-turbo-1.2.1/tmp/include -L /mnt/hgfs/share/libjpeg-turbo-1.2.1/tmp/lib -ljpeg    /* 指定头文件和库 */

执行 : ./jpg2rgb 12.jpg 

1/1

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值