libjpeg 使用
libjpeg
http://libjpeg.sourceforge.net/
libjpeg 是 libjpeg-turbo 和 MozJPEG 的祖宗,这三个库的应用层代码通用。libjpeg使用方法是直接添加 .c 和 .h 文件到工程,其他两个库是通过 cmake 组织源代码,然后通过编译器生成静态链接库和头文件添加到工程
STM32CUBEMX 有 libjpeg 组件,已经整理好 .c 和 .h
libjpeg 库,第一个要阅读的文件就是 README
libjpeg-turbo
https://github.com/libjpeg-turbo/libjpeg-turbo
libjpeg-turbo图像编解码器,使用了SIMD指令(MMX,SSE2,NEON,AltiVec)来加速x86,x86-64,ARM和PowerPC系统上的JPEG压缩和解压缩。在这样的系统上,libjpeg-turbo的速度通常是libjpeg的2-6倍,其他条件相同。在其他类型的系统上,凭借其高度优化的霍夫曼编码,libjpeg-turbo仍然可以大大超过libjpeg。在许多情况下,libjpeg-turbo的性能可与专有的高速JPEG编解码器相媲美。
MozJPEG
https://github.com/mozilla/mozjpeg
MozJPEG 是 libjpeg-turbo 的补丁,包含了 libjpeg-turbo 所有的功能,并且新增了一些功能。
使用 jpeg 指南:
使用 .a文件和 .h文件
编译源码库,生成静态链接库,比如 libjpeg.a,在链接步骤会引用这个库。如果只使用压缩或者解压缩,只会链接相应的部分,不会整个库都链接进去。
不建议用共享库(动态链接库)
注意:
1、编译器的路径要添加到环境PATH中,否则会提示:找不到 libwinpthread-1.dll 无法继续执行代码,因为libwinpthread-1.dll在编译器 bin 文件夹下(比如QT的编译器:D:\Qt\Qt5.14.2\Tools\mingw730_64\bin)
2、cmake需要用到make工具,windows下可以用QT编译器路径下的 mingw32-make.exe
3、RGB data (three components per pixel) or grayscale data (one component per pixel)
编译配置:
CMAKE_BUILD_TYPE: Release或者Debug,默认是Release
ENABLE_STATIC: 设置是否生成静态库
ENABLE_SHARED: 设置是否生成动态库
WITH_SIMD: 设置是否使用 SIMD 指令
WITH_TURBOJPEG: 是否生成 turbo版本的 jpeg库
http://www.voidcn.com/article/p-fwyrdlmp-bdp.html
https://blog.csdn.net/zhizhengguan/article/details/107560858
https://blog.csdn.net/jcq521045349/article/details/79578124
使用 make 编译源文件
在 ”Where to build the binaries“ 中打开 cmd,执行 make,然后执行 make install
最后生成的文件放在如下目录:
最后生成的文件如下:
bin文件夹下是各个例子的可执行文件
libjpeg.a
libjpeg API的静态链接库
libjpeg-{version}.dll
DLL的libjpeg API的动态链接库(DLL)
libjpeg.dll.a
libjpeg API的导入库
注:libjpeg-{version}.dll 和 libjpeg.dll.a 配套使用,libjpeg.a单独使用
libturbojpeg.a
TurboJPEG API的静态链接库
libturbojpeg.dll
TurboJPEG API的动态链接库(DLL)
libturbojpeg.dll.a
TurboJPEG API的导入库
其中“{version}” 是 62,7,或8,取决于libjpeg v6b (默认),v7,或v8的emulation是否启用。
libjpeg.txt
库使用说明书
tjexample.c
是测试编解码的demo,这里面会先将jpg文件解码到YUV或者BGR,再将其编码成jpg文件
参考代码:
YUV422 YUYU 转 JPG
#include "mainwindow.h" #include "ui_mainwindow.h" #include "libjpeg-turbo-gcc64/include/jpeglib.h" #include "libjpeg-turbo-gcc64/include/jconfig.h" #include "libjpeg-turbo-gcc64/include/jerror.h" #include "libjpeg-turbo-gcc64/include/jmorecfg.h" #include <QDir> #include <QTextStream> #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); g_str_dir = QDir::currentPath(); // g_str_dir = "."; qDebug() << g_str_dir; uint16_t width = 400; uint16_t height = 300; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; int i = 0; unsigned char *pY, *pU, *pV; uchar inputYuv[width * height * 2]; unsigned char yuvbuf[width * 3];//每个像素3个字节 uchar *outJpeg = NULL; //初始化非常重要!!! unsigned long outSize = 0; //初始化非常重要!!! read_data_from_YUV_file(inputYuv, width, height); qDebug("%02X %02X %02X %02X", inputYuv[0], inputYuv[1], inputYuv[2], inputYuv[3]); qDebug("%02X %02X %02X %02X", inputYuv[4], inputYuv[5], inputYuv[6], inputYuv[7]); cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, &outJpeg, &outSize); cinfo.image_width = width;//设置输入图片宽度 cinfo.image_height = height;//设置图片高度 cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr;//设置输入图片的格式,支持RGB/YUV/YCC等等 // cinfo.dct_method = JDCT_ISLOW; jpeg_set_defaults(&cinfo);//其它参数设置为默认的! jpeg_set_quality(&cinfo, 40, TRUE);//设置转化图片质量,范围0-100 jpeg_start_compress(&cinfo, TRUE); pY = inputYuv; pU = inputYuv + 1; pV = inputYuv + 3; /* 0 1 2 3 4 5 6 7 * Y00 U00 Y01 V00 Y02 U01 Y03 V01 * Y10 U10 Y11 V10 Y12 U11 Y13 V11 */ while (cinfo.next_scanline < cinfo.image_height) { uint16_t index = 0; for (i = 0; i < width; i += 2) {//输入的YUV图片格式为标准的YUV444格式,所以需要把YUV422转化成YUV444. yuvbuf[index++] = *pY; yuvbuf[index++] = *pU; yuvbuf[index++] = *pV; pY += 2; yuvbuf[index++] = *pY; yuvbuf[index++] = *pU; yuvbuf[index++] = *pV; pY += 2; pU += 4; pV += 4; } row_pointer[0] = yuvbuf; jpeg_write_scanlines(&cinfo, row_pointer, 1);//单行图片转换压缩 } jpeg_finish_compress(&cinfo); QFile fileBin_write_crc("./test.jpg"); if(!fileBin_write_crc.open(QIODevice::WriteOnly)) { qDebug() << "fail: open test.jpg"; return; } fileBin_write_crc.write((const char *)outJpeg, outSize); fileBin_write_crc.close(); if(NULL != outJpeg) { free(outJpeg); outJpeg = NULL; } jpeg_destroy_compress(&cinfo); } MainWindow::~MainWindow() { delete ui; } void MainWindow::read_data_from_YUV_file(uchar *buffer, uint16_t width, uint16_t height) { uchar *buf = buffer; QFile yuv_file(g_str_dir + "/YUV422_YUYV.yuv"); if(!yuv_file.open(QIODevice::ReadOnly)) { qDebug() << "bin 文件未找到!!!!!!!!!!!"; return; } QByteArray data; unsigned long i = 0; while(!yuv_file.atEnd()) { data = yuv_file.read(4); *(buf++) = static_cast<uchar>(data[0]); *(buf++) = static_cast<uchar>(data[1]); *(buf++) = static_cast<uchar>(data[2]); *(buf++) = static_cast<uchar>(data[3]); i = i + 4; if(i >= width * height * 2) break; } yuv_file.close(); }
toolchain file for cross-compiling
set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_VERSION 1) set(CMAKE_SYSTEM_PROCESSOR cortex-r5) set(GCC_INSTALL_ROOT D:/company/document/EC600S/ql-sdk/ql-cross-tool/win32/owtoolchain/gcc-arm-none-eabi) set(CMAKE_SYSROOT ${GCC_INSTALL_ROOT}/arm-none-eabi) set(CMAKE_C_COMPILER ${GCC_INSTALL_ROOT}/bin/arm-none-eabi-gcc.exe) set(CMAKE_CXX_COMPILER ${GCC_INSTALL_ROOT}/bin/arm-none-eabi-g++.exe) set(CMAKE_C_FLAGS "--specs=nosys.specs") set(STDLIB ${GCC_INSTALL_ROOT}/arm-none-eabi/lib/thumb/v7/nofp/libm.a) link_libraries("${STDLIB}") set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)