使用libjpeg-turbo进行JPG编解码-YUV422P转JPG为例

本文转自公众号,欢迎关注
使用libjpeg-turbo进行jpg编解码-yuv422p转jpg为例 (qq.com)
一.前言在uvc项目中需要测试mjpeg的传输, 通常jpg使用的是yuv420采样压缩,恰好有个uvc的显示设备不支持yuv420采样压缩,只支持yuv422采样压缩,所以需要生成yuv422采样压缩的jpg文件用于测试。于是使用libjpeg代码库生成。这里使用libjpeg-turbo,相对官方的libjpeg,其使用了simd进行了速度优化,并且进一步封装了接口,接口更简洁更方便使用。
关于yuv422和yuv420采样的jpg,以下文章有更详细的说明,总的来说yuv420更常见,毕竟都有损压缩了,使用yuv422带来的质量提升已经没什么意义了,使用yuv420空间更小,质量差异不大。https://calendar.perfplanet.com/2015/why-arent-your-images-using-chroma-subsampling/
项目见: https://github.com/libjpeg-turbo/libjpeg-turbo.git
https://libjpeg-turbo.org/
libjpeg见:http://www.ijg.org/files/
以下基于wsl+ubuntu环境进行。
二.下载代码lhj@lhj:~$ git clone https://github.com/libjpeg-turbo/libjpeg-turbo.git
cloning into 'libjpeg-turbo'...remote: enumerating objects: 19401, done.remote: counting objects: 100% (432/432), done.remote: compressing objects: 100% (199/199), done.remote: total 19401 (delta 259), reused 325 (delta 219), pack-reused 18969receiving objects: 100% (19401/19401), 17.02 mib | 10.70 mib/s, done.resolving deltas: 100% (14372/14372), done.进入目录查看文件如下
lhj@lhj:~$ cd libjpeg-turbo/
lhj@lhj:~/libjpeg-turbo$ ls
building.md fuzz jconfig.txt jdhuff.c jfdctfst.c jstdhuff.c tjexampletest.incmakelists.txt jaricom.c jconfigint.h.in jdhuff.h jfdctint.c jutils.c tjunittest.cchangelog.md java jcparam.c jdicc.c jidctflt.c jversion.h.in tjutil.clicense.md jcapimin.c jcphuff.c jdinput.c jidctfst.c libjpeg.map.in tjutil.hreadme.ijg jcapistd.c jcprepct.c jdlhuff.c jidctint.c libjpeg.txt transupp.creadme.md jcarith.c jcsample.c jdlossls.c jidctred.c md5 transupp.happveyor.yml jccoefct.c jcstest.c jdmainct.c jinclude.h rdbmp.c turbojpeg-jni.ccderror.h jccolext.c jctrans.c jdmainct.h jlossls.h rdcolmap.c turbojpeg-mapfilecdjpeg.c jccolor.c jdapimin.c jdmarker.c jmemmgr.c rdgif.c turbojpeg-mapfile.jnicdjpeg.h jcdctmgr.c jdapistd.c jdmaster.c jmemnobs.c rdjpgcom.1 turbojpeg-mp.cchange.log jcdiffct.c jdarith.c jdmaster.h jmemsys.h rdjpgcom.c turbojpeg.ccjpeg.1 jchuff.c jdatadst-tj.c jdmerge.c jmorecfg.h rdppm.c turbojpeg.hcjpeg.c jchuff.h jdatadst.c jdmerge.h jpeg_nbits_table.h rdswitch.c usage.txtdoxygen-extra.css jcmaster.h jdct.h jerror.c jsamplecomp.h tjbench.c wrtarga.cdoxygen.config jcomapi.c jddctmgr.c jerror.h jsimd.h tjbenchtest.inexample.c jconfig.h.in jddiffct.c jfdctflt.c jsimddct.h tjexample.clhj@lhj:~/libjpeg-turbo$ code .
三.安装nasmlhj@lhj:~/libjpeg-turbo$ sudo apt install nasm
[sudo] password for lhj:reading package lists... donebuilding dependency treereading state information... donethe following new packages will be installed: nasm0 upgraded, 1 newly installed, 0 to remove and 224 not upgraded.need to get 362 kb of archives.after this operation, 3374 kb of additional disk space will be used.get:1 http://archive.ubuntu.com/ubuntu focal/universe amd64 nasm amd64 2.14.02-1 [362 kb]fetched 362 kb in 2s (185 kb/s)selecting previously unselected package nasm.(reading database ... 131163 files and directories currently installed.)preparing to unpack .../nasm_2.14.02-1_amd64.deb ...unpacking nasm (2.14.02-1) ...setting up nasm (2.14.02-1) ...processing triggers for man-db (2.9.1-1) ...四.编译lhj@lhj:~/libjpeg-turbo$ mkdir build
lhj@lhj:~/libjpeg-turbo$ cd build
lhj@lhj:~/libjpeg-turbo/build$ cmake ../
-- the c compiler identification is gnu 9.4.0-- check for working c compiler: /usr/bin/cc-- check for working c compiler: /usr/bin/cc -- works-- detecting c compiler abi info-- detecting c compiler abi info - done-- detecting c compile features-- detecting c compile features - done-- cmake_build_type = release-- version = 3.0.1, build = 20230810-- 64-bit build (x86_64)-- cmake_install_prefix = /opt/libjpeg-turbo-- cmake_install_bindir = bin (/opt/libjpeg-turbo/bin)-- cmake_install_datarootdir = (/opt/libjpeg-turbo)-- cmake_install_docdir = doc (/opt/libjpeg-turbo/doc)-- cmake_install_includedir = include (/opt/libjpeg-turbo/include)-- cmake_install_libdir = lib64 (/opt/libjpeg-turbo/lib64)-- cmake_install_mandir = man (/opt/libjpeg-turbo/man)-- shared libraries enabled (enable_shared = 1)-- static libraries enabled (enable_static = 1)-- arithmetic decoding support enabled (with_arith_dec = 1)-- arithmetic encoding support enabled (with_arith_enc = 1)-- turbojpeg api library enabled (with_turbojpeg = 1)-- turbojpeg java wrapper disabled (with_java = 0)-- emulating libjpeg api/abi v6.2 (with_jpeg7 = 0, with_jpeg8 = 0)-- libjpeg api shared library version = 62.4.0-- compiler flags = -o3 -dndebug-- linker flags =-- looking for sys/types.h-- looking for sys/types.h - found-- looking for stdint.h-- looking for stdint.h - found-- looking for stddef.h-- looking for stddef.h - found-- check size of size_t-- check size of size_t - done-- check size of unsigned long-- check size of unsigned long - done-- performing test have_builtin_ctzl-- performing test have_builtin_ctzl - success-- performing test right_shift_is_unsigned-- performing test right_shift_is_unsigned - failed-- performing test inline_works-- performing test inline_works - success-- inline = __inline__ __attribute__((always_inline)) (force_inline = 1)-- performing test have_thread_local-- performing test have_thread_local - success-- thread_local = __thread-- performing test have_version_script-- performing test have_version_script - success-- linker supports gnu-style version scripts-- cmake_executable_suffix =-- looking for a asm_nasm compiler-- looking for a asm_nasm compiler - /usr/bin/nasm-- the asm_nasm compiler identification is nasm-- found assembler: /usr/bin/nasm-- cmake_asm_nasm_compiler = /usr/bin/nasm-- cmake_asm_nasm_object_format = elf64-- cmake_asm_nasm_flags = -delf -d__x86_64__ -dpic-- simd extensions: x86_64 (with_simd = 1)-- floattest8 = sse-- floattest12 = no-fp-contract-- rpm architecture = x86_64, deb architecture = amd64-- configuring done-- generating done-- build files have been written to: /home/lhj/libjpeg-turbo/buildlhj@lhj:~/libjpeg-turbo/build$ make
scanning dependencies of target simd[ 0%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jsimdcpu.asm.o[ 0%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jfdctflt-sse.asm.o[ 0%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jccolor-sse2.asm.o[ 0%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jcgray-sse2.asm.o[ 1%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jchuff-sse2.asm.o[ 1%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jcphuff-sse2.asm.o[ 1%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jcsample-sse2.asm.o[ 1%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jdcolor-sse2.asm.o[ 1%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jdmerge-sse2.asm.o[ 2%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jdsample-sse2.asm.o[ 2%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jfdctfst-sse2.asm.o[ 2%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jfdctint-sse2.asm.o[ 2%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jidctflt-sse2.asm.o[ 3%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jidctfst-sse2.asm.o[ 3%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jidctint-sse2.asm.o[ 3%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jidctred-sse2.asm.o[ 3%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jquantf-sse2.asm.o[ 3%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jquanti-sse2.asm.o[ 4%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jccolor-avx2.asm.o[ 4%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jcgray-avx2.asm.o[ 4%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jcsample-avx2.asm.o[ 4%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jdcolor-avx2.asm.o[ 5%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jdmerge-avx2.asm.o[ 5%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jdsample-avx2.asm.o[ 5%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jfdctint-avx2.asm.o[ 5%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jidctint-avx2.asm.o[ 5%] building asm_nasm object simd/cmakefiles/simd.dir/x86_64/jquanti-avx2.asm.o[ 6%] building c object simd/cmakefiles/simd.dir/x86_64/jsimd.c.o[ 6%] built target simdscanning dependencies of target turbojpeg12.......scanning dependencies of target md5cmp[ 99%] building c object md5/cmakefiles/md5cmp.dir/md5cmp.c.o[100%] building c object md5/cmakefiles/md5cmp.dir/md5.c.o[100%] building c object md5/cmakefiles/md5cmp.dir/md5hl.c.o[100%] linking c executable md5cmp[100%] built target md5cmp生成文件如下
lhj@lhj:~/libjpeg-turbo/build$ ls
cmakecache.txt cmake_uninstall.cmake jconfigint.h libjpeg.so md5 tjbench-staticcmakefiles croptest jcstest libjpeg.so.62 pkgscripts tjbenchtestctesttestfile.cmake djpeg jpegtran libjpeg.so.62.4.0 rdjpgcom tjexamplemakefile djpeg-static jpegtran-static libturbojpeg.a sharedlib tjexampletestcjpeg example jversion.h libturbojpeg.so simd tjunittestcjpeg-static example-static libjpeg.a libturbojpeg.so.0 strtest tjunittest-staticcmake_install.cmake jconfig.h libjpeg.map libturbojpeg.so.0.3.0 tjbench wrjpgcom五.安装lhj@lhj:~/libjpeg-turbo/build$ sudo make install
安装于/opt/libjpeg-turbo/lib64
[sudo] password for lhj: [ 6%] built target simd[ 7%] built target turbojpeg12[ 10%] built target jpeg16[ 16%] built target jpeg12[ 17%] built target turbojpeg16[ 31%] built target turbojpeg[ 31%] built target turbojpeg12-static[ 34%] built target jpeg16-static[ 40%] built target jpeg12-static[ 53%] built target jpeg-static[ 54%] built target djpeg12-static[ 54%] built target djpeg16-static[ 56%] built target djpeg-static[ 56%] built target example-static[ 57%] built target tjexample[ 57%] built target turbojpeg16-static[ 71%] built target turbojpeg-static[ 72%] built target jpegtran-static[ 73%] built target tjunittest-static[ 74%] built target rdjpgcom[ 75%] built target tjunittest[ 75%] built target tjbench-static[ 76%] built target cjpeg16-static[ 76%] built target strtest[ 77%] built target cjpeg12-static[ 79%] built target cjpeg-static[ 80%] built target wrjpgcom[ 81%] built target tjbench[ 81%] built target cjpeg12[ 81%] built target cjpeg16[ 93%] built target jpeg[ 94%] built target cjpeg[ 94%] built target djpeg16[ 94%] built target djpeg12[ 96%] built target djpeg[ 97%] built target jpegtran[ 98%] built target example[ 99%] built target jcstest[100%] built target md5cmpinstall the project...-- install configuration: release-- installing: /opt/libjpeg-turbo/lib64/libturbojpeg.so.0.3.0-- installing: /opt/libjpeg-turbo/lib64/libturbojpeg.so.0-- set runtime path of /opt/libjpeg-turbo/lib64/libturbojpeg.so.0.3.0 to /opt/libjpeg-turbo/lib64-- installing: /opt/libjpeg-turbo/lib64/libturbojpeg.so-- installing: /opt/libjpeg-turbo/bin/tjbench-- set runtime path of /opt/libjpeg-turbo/bin/tjbench to /opt/libjpeg-turbo/lib64-- installing: /opt/libjpeg-turbo/lib64/libturbojpeg.a-- installing: /opt/libjpeg-turbo/include/turbojpeg.h-- installing: /opt/libjpeg-turbo/lib64/libjpeg.a-- installing: /opt/libjpeg-turbo/bin/rdjpgcom-- set runtime path of /opt/libjpeg-turbo/bin/rdjpgcom to /opt/libjpeg-turbo/lib64-- installing: /opt/libjpeg-turbo/bin/wrjpgcom-- set runtime path of /opt/libjpeg-turbo/bin/wrjpgcom to /opt/libjpeg-turbo/lib64-- installing: /opt/libjpeg-turbo/doc/readme.ijg-- installing: /opt/libjpeg-turbo/doc/readme.md-- installing: /opt/libjpeg-turbo/doc/example.c-- installing: /opt/libjpeg-turbo/doc/tjexample.c-- installing: /opt/libjpeg-turbo/doc/libjpeg.txt-- installing: /opt/libjpeg-turbo/doc/structure.txt-- installing: /opt/libjpeg-turbo/doc/usage.txt-- installing: /opt/libjpeg-turbo/doc/wizard.txt-- installing: /opt/libjpeg-turbo/doc/license.md-- installing: /opt/libjpeg-turbo/man/man1/cjpeg.1-- installing: /opt/libjpeg-turbo/man/man1/djpeg.1-- installing: /opt/libjpeg-turbo/man/man1/jpegtran.1-- installing: /opt/libjpeg-turbo/man/man1/rdjpgcom.1-- installing: /opt/libjpeg-turbo/man/man1/wrjpgcom.1-- installing: /opt/libjpeg-turbo/lib64/pkgconfig/libjpeg.pc-- installing: /opt/libjpeg-turbo/lib64/pkgconfig/libturbojpeg.pc-- installing: /opt/libjpeg-turbo/lib64/cmake/libjpeg-turbo/libjpeg-turboconfig.cmake-- installing: /opt/libjpeg-turbo/lib64/cmake/libjpeg-turbo/libjpeg-turboconfigversion.cmake-- installing: /opt/libjpeg-turbo/lib64/cmake/libjpeg-turbo/libjpeg-turbotargets.cmake-- installing: /opt/libjpeg-turbo/lib64/cmake/libjpeg-turbo/libjpeg-turbotargets-release.cmake-- installing: /opt/libjpeg-turbo/include/jconfig.h-- installing: /opt/libjpeg-turbo/include/jerror.h-- installing: /opt/libjpeg-turbo/include/jmorecfg.h-- installing: /opt/libjpeg-turbo/include/jpeglib.h-- installing: /opt/libjpeg-turbo/lib64/libjpeg.so.62.4.0-- installing: /opt/libjpeg-turbo/lib64/libjpeg.so.62-- set runtime path of /opt/libjpeg-turbo/lib64/libjpeg.so.62.4.0 to /opt/libjpeg-turbo/lib64-- installing: /opt/libjpeg-turbo/lib64/libjpeg.so-- installing: /opt/libjpeg-turbo/bin/cjpeg-- set runtime path of /opt/libjpeg-turbo/bin/cjpeg to /opt/libjpeg-turbo/lib64-- installing: /opt/libjpeg-turbo/bin/djpeg-- set runtime path of /opt/libjpeg-turbo/bin/djpeg to /opt/libjpeg-turbo/lib64-- installing: /opt/libjpeg-turbo/bin/jpegtran-- set runtime path of /opt/libjpeg-turbo/bin/jpegtran to /opt/libjpeg-turbo/lib64六.测试lhj@lhj:~/libjpeg-turbo/build$ sudo make test
running tests...test project /home/lhj/libjpeg-turbo/build start 1: tjunittest-shared 1/590 test #1: tjunittest-shared ................................... passed 3.48 sec start 2: tjunittest-shared-alloc 2/590 test #2: tjunittest-shared-alloc ............................. passed 3.48 sec...... start 590: example-12bit-static-decompress-cmp590/590 test #590: example-12bit-static-decompress-cmp ................. passed 0.00 sec100% tests passed, 0 tests failed out of 590total test time (real) = 79.40 sec七.yuv422p转jpg代码
#include #include #include #include #include #include #include /* y = 0.298r + 0.612g + 0.117b; [13,235] u = -0.168r - 0.330g + 0.498b + 128; [16,239] v = 0.449r - 0.435g - 0.083b + 128; [16,239]*/uint8_t* yuv422p(uint32_t w, uint32_t h, uint32_t color){ uint8_t* p = (uint8_t*)malloc(w*h*2); uint8_t* ret = p; if(p == null) { return null; } int y = 0; int u = 0; int v = 0; uint8_t r = 0; uint8_t g = 0; uint8_t b = 0; r = (color > > 16) & 0xff; g = (color > > 8) & 0xff; b = (color > > 0) & 0xff; y = (0.298*r + 0.612*g + 0.117*b); u = (-0.168*r - 0.330*g + 0.498*b + 128); v = (0.449*r - 0.435*g - 0.083*b + 128); if(y >235) { y=235; } if(y239) { u=239; } if(u239) { v=239; } if(v< 16) { v=16; } for(int i=0;i< w*h;i++) { *p++ = y; } for(int i=0;i< w*h/2;i++) { *p++ = u; } for(int i=0;i< w*h/2;i++) { *p++ = v; } return ret;}/*写内存到文件*/void write_buffer2file(char *filename, uint8_t *buffer, int size){ file *fd = fopen(filename,wb); if (null == fd) { return; } fwrite(buffer,1,size,fd); fclose(fd);}int tyuv2jpeg(unsigned char* yuv_buffer, int yuv_size, int width, int height, int subsample, unsigned char** jpeg_buffer, unsigned long* jpeg_size, int quality,char *name){ tjhandle handle = null; int flags = 0; int padding = 16; // 1或4均可,但不能是0 int need_size = 0; int ret = 0; handle = tjinitcompress(); flags |= 0; need_size = tjbufsizeyuv2(width, padding, height, subsample); if (need_size != yuv_size) { printf(we detect yuv size: %d, but you give: %d, check again.n, need_size, yuv_size); return 0; } ret = tjcompressfromyuv(handle, yuv_buffer, width, padding, height, subsample, jpeg_buffer, jpeg_size, quality, flags); if (ret < 0) { printf(compress to jpeg failed: %sn, tjgeterrorstr()); } write_buffer2file(name,*jpeg_buffer,*jpeg_size); tjdestroy(handle); return ret;}int main(){ unsigned long jpeg_size; unsigned char* yuv_buffer; unsigned char* jpeg_buffer; yuv_buffer = yuv422p(800, 480, 0xffff00); tyuv2jpeg(yuv_buffer, 800*480*2, 800, 480, tjsamp_422, &jpeg_buffer, &jpeg_size, 90, out.jpg); free(yuv_buffer);}编译
gcc test.c -o test -lturbojpeg -i/opt/libjpeg-turbo/include -l/opt/libjpeg-turbo/lib64
运行
export ld_library_path=$ld_library_path:/opt/libjpeg-turbo/lib64 && ./test
生成out.jpg
八. 总结以上使用libjpeg实现了yuv422p转jpg,可以导入自己项目用于uvc的mjpeg测试。后面再单独讲将其移植到mcu以实现软jpg的编解码。


智能园区可以让园区变得更智能化,优化体验感
洞悉 Omniverse:Reallusion 通过双向实时同步和 OpenUSD 支持改进角色动画制作流程
偏振光学在生物医学中的应用
华米科技与DSM宣布在可穿戴技术方面进行合作
吴恩达开新课,“全民AI”!
使用libjpeg-turbo进行JPG编解码-YUV422P转JPG为例
华为首款正式商用华为鸿蒙2.0手机操作系统的机型
铭板标签工厂详述轻触开关与薄膜开关
了解DNS的工作原理,了解根域名的管理机制
区块链技术将如何提升互联网保险的安全性
ossutil上传性能调优
商场室内LED显示屏的作用_商场室内LED显示屏的优势
即付即用存储使用模式及其挑战
CA70型无极性固体电解质钽电容器
国家颁布规定禁止大数据杀熟,央视调查后发现仍存在差异化定价
工信部印发了关于加强工业互联网安全工作的指导意见
微型无人机的电力动力系统是由哪些结构组成的
睿创微纳推出KBA12R矿用本安型热成像摄像仪
区块链在航空航天业中的潜在用例有哪些
3D打印生物陶瓷支架表面微纳米结构调控骨-软骨一体化修复研究获进展