草庐IT

libjpeg-turbo使用教程

千叶择木 2023-04-20 原文

buildroot下libjpeg-turbo的使用

        libjpeg-turbo是一种JPEG图像编解码器的库,它使用SIMD指令(MMX、SSE2、AVX2、NEON、AltiVec)来加速x86、x86-64、ARM和PowerPC系统上的基线JPEG压缩和解压缩。libjpeg库使用的更广泛,不过它是使用纯c语言编写的,所以编解码速度慢。 libjpeg-turbo的速度通常是libjpeg的2-6倍。
        libjpeg-turbo支持rgba图像数据转jpeg,或者yuv格式的图像数据转jpeg。反之亦然。

主要功能

        libjpeg-turbo包含两种API,一种是libjpeg-turbo,另一种是libjpeg。当两种API都用于执行类似的操作时,这两种API没有显著的性能优势。具体的api使用方法可以参考 doc/index.html 网页的Modules下面的TurboJPEG链接的内容。
        libjpeg-turbo 使用起来更简单。
        libjpeg API 的存在是为了与API/ABI兼容,又与libjpeg v6b在数学上兼容。它还可以可选地配置为与libjpeg v7和v8兼容的API/ABI。

        libjpeg-turbo库提供的功能主要分为4类,包括编码,解码,格式转换,和读写bmp文件

  1. 编码
    将一个rgb图像编码为jpeg文件
    将一个yuv图像编码为jpeg文件
  2. 解码
    获取jpeg文件宽高,采样率,色彩空间等信息
    将一个jpeg文件解码为rgb图像
    将一个jpeg文件解码为yuv图像
  3. 格式转换
    rgb图像转为yuv图像
    yuv图像转rgb图像
  4. bmp
    读取一个bmp文件到内存
    将图像数据保存为bmp文件

编译库

  1. 查看cpu是否支持simd指令。
    通产cpu的数据手册会提示你有没有simd指令,如neon指令。也可以在linux板子上执行cat /proc/cpuinfo查看cpu信息。

  2. 检查buildroot是否已经配置了simd指令,如neon指令。
    检查buildroot的output文件夹下面的某个项目里的.config文件,里面是否有 BR2_ARM_CPU_HAS_NEON=y这个配置,没有的话,编译库的时候要加上。

  3. 可以参考BUILDING.md文件编译这个库。
            使用buildroot方式编译时,不需要参考这个md文件,只要在configs配置文件中添加 BR2_PACKAGE_JPEG=y 即可。这个配置包括两个配置选项,一个是jpeg库,另一个是jpegturbo库,所以,当cpu支持simd指令时,buildroot不会编译jpeg库,而是会编译jpegturbo库。编译完成后,会生成最重要的libturbojpeg.so文件和turbojpeg.h文件。

测试

        编译成功后,会产生一些可执行程序,将它们和生成的.so库文件一起拷到开发板上,便可开始测试。

  • tjexample
    主要用于把一个bmp文件转为jpeg,或者将一个jpeg文件转为bmp文件。
    bmp转jpeg:
    ./tjexample input.bmp output.jpg
    jpeg转bmp
    ./tjexample input.jpg output.bmp
  • tjbench
    测试编码或者解码性能
    测试编码性能:./tjbench cif.bmp 90    // 90为编码质量,范围为[1, 100]
    测试解码性能:./tjbench cif.jpg
            以下是rv1126_1109芯片所测的数据,测试的图片大小为1280x720,使用arm neon指令,4核Cortex-A7 1.5Ghz,测试时cpu大概占用25%。

示例

        以下代码会生成一个红色图片的jpg文件,保存在 /tmp/123.jpg 文件上。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <turbojpeg.h>

#define _throw(action, message) { \
  printf("ERROR in line %d while %s:\n%s\n", __LINE__, action, message); \
  retval = -1;  goto bailout; \
}
#define _throwtj(action)  _throw(action, tjGetErrorStr2(tjInstance))


void encode_jpeg_by_cpu(const void *input, int width, int height, int pixelFormat, void *output, unsigned long *size)
{
	int retval = 0;
	tjhandle tjInstance = NULL;	// 句柄
	unsigned char *jpegBuf = NULL;
	// pixelFormat = { TJPF_RGB, TJPF_BGR, TJPF_BGRX, TJPF_BGRX, TJPF_XRGB, TJPF_GRAY, TJPF_RGBA,
	// 				TJPF_BGRA, TJPF_ABGR, TJPF_ARGB, TJPF_CMYK, TJPF_UNKNOWN};

	*size = 0;
	if ((tjInstance = tjInitCompress()) == NULL)	// 创建一个TurboJPEG编码器实例
		_throwtj("initializing compressor");
	if (tjCompress2(tjInstance, (const unsigned char *)input, width, 0, height, pixelFormat,	// 将图像编码为jpeg文件
		&jpegBuf, size, TJSAMP_444, 90, 0) < 0)     // 编码质量为90,取值范围为[1,100],超过95会导致性能下降严重。
		_throwtj("compressing image");

	tjDestroy(tjInstance);  tjInstance = NULL;		// 销毁一个TurboJPEG编码器实例
	memcpy(output, jpegBuf, *size);
	tjFree(jpegBuf);	jpegBuf = NULL;

bailout:
	if (tjInstance) tjDestroy(tjInstance);
	if (jpegBuf) tjFree(jpegBuf);
}

int main(int argc, char *argv[])
{
	unsigned long size;
	int *red = malloc(640 * 480 * 4);
	int *jpeg = malloc(640 * 480 * 4);

	// 1. 生成红色图像
	for (int i = 0; i < 480; i++)
		for (int j = 0; j < 640; j++)
			red[i * 640 + j] = 0xffff0000;

	// 2.编码
	encode_jpeg_by_cpu(red, 640, 480, TJPF_BGRA, jpeg, &size);

	// 3.写入文件
	FILE *file = fopen("/tmp/123.jpg", "wb+");
	fwrite(jpeg, size, 1, file);
	fclose(file);
	printf("generate red picture to /tmp/123.jpg success!\n");
}

        将源文件保存为red.c,则编译命令为:arm-linux-gnueabihf-gcc red.c -o red -lturbojpeg,输出应用程序red。运行前需把red和libturbojpeg.so一起拷贝到开发板上。

有关libjpeg-turbo使用教程的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐