1. jpeg-turbo的编译安装
使用标准的cmake的编译安装方式即可。
下面以 windows 平台为例说明编译安装过程,其他平台过程类似。
1.1 先安装NASM
NASM是个汇编工具,后面编译 jpeg-turbo 需要用到,所以先安装
NASM的官网: https://www.nasm.us/index.php
可以从下载页 https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D 中选择适合自己系统的版本进行安装
1.2 下载 jpeg-turbo 源码
jpeg-turbo的github仓库网址: https://github.com/libjpeg-turbo/libjpeg-turbo
可以从中下载最新的master版本。
也可以从 https://github.com/libjpeg-turbo/libjpeg-turbo/releases 中下载历史版本
这里下载2.1.0版本得到文件"libjpeg-turbo-2.1.0.zip"
解压到文件夹"D:\test\libjpeg-turbo-2.1.0"
新建文件夹"D:\test\libjpeg-turbo-2.1.0\build",作为后续的编译文件夹
新建文件夹"D:\test\jpeg-turbo_install",作为安装文件夹
1.3 cmake 配置编译工程
这里用 cmake-gui,本质就是cmake,只是方便查看设置的选项。
如下设置源码文件夹、编译文件夹、安装文件夹
1.4 打开工程编译安装
依次点击"Generate"和"Open Project",打开编译工程。
如下编译"INSTALL"工程
编译完成之后,就在指定安装路径下生成了如下文件,如此便完成了jpeg-turbo的编译安装
2. 使用
2.1 通过 cmake 进行 jpeg-turbo 库引用的关键语句
写在CMakeLists.txt的关键语句如下:
set(libjpeg-turbo_DIR "D:/test/jpeg-turbo_install/lib/cmake/libjpeg-turbo")
find_package(libjpeg-turbo REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} libjpeg-turbo::turbojpeg-static)
这里是使用了静态库,使用其他形式可以去更改target_link_libraries
的后面部分
2.2 压缩语句
bool Compress(unsigned char *data_uncompressed, unsigned char* &out_compressed, unsigned long *out_size, int width, int height, int pixel_format)
{
if (nullptr == data_uncompressed) {
return false;
}
tjhandle compressor = tjInitCompress();
if (nullptr == compressor) {
return false;
}
//pixel_format : TJPF::TJPF_BGR or other
const int JPEG_QUALITY = 75;
int pitch = tjPixelSize[pixel_format] * width;
int status = tjCompress2(compressor, data_uncompressed, width, pitch, height, pixel_format,
&out_compressed, out_size, TJSAMP_444, JPEG_QUALITY, TJFLAG_FASTDCT);
if (status != 0) {
tjDestroy(compressor);
return false;
}
tjDestroy(compressor);
return true;
}
2.3 解压缩语句
bool Decompress(uint8_t* data_compressed, uint32_t size, uint8_t* &out_uncompressed, int pixel_format)
{
if (nullptr == data_compressed || nullptr == out_uncompressed) {
return false;
}
int width = 0, height = 0, jpegsubsamp = 0;
void* decompressor = tjInitDecompress();
if (nullptr == decompressor) {
return false;
}
if (tjDecompressHeader2(decompressor, data_compressed, size, &width, &height, &jpegsubsamp) != 0) {
tjDestroy(decompressor);
return false;
}
// pixel_format : TJPF::TJPF_BGR or other
int pitch = tjPixelSize[pixel_format] * width;
uint32_t len = pitch * height;
int flags = TJFLAG_FASTDCT;
int status = tjDecompress2(decompressor, data_compressed, len, out_uncompressed, width, pitch,
height, pixel_format, flags);
if ( status != 0) {
tjDestroy(decompressor);
return false;
}
tjDestroy(decompressor);
return true;
}
2.4 测试程序
int main()
{
cv::Mat image = cv::imread("../lena.jpg");
unsigned char *data_uncompressed = image.data;
unsigned char* out_compressed = nullptr;
unsigned long out_size = 0;
int pixel_format = TJPF::TJPF_BGR;
int width = image.cols;
int height = image.rows;
int channels = image.channels();
bool status = Compress(data_uncompressed, out_compressed, &out_size, width, height, pixel_format);
if (false == status) {
std::cout << "Compress failed" << std::endl;
}
uint8_t* out_uncompressed = new uint8_t[width*height*channels];
status = Decompress(out_compressed, out_size, out_uncompressed, pixel_format);
if (false == status) {
std::cout << "Decompress failed" << std::endl;
}
cv::Mat image_decompress(height, width, CV_8UC3, out_uncompressed);
cv::imshow("out_uncompressed", image_decompress);
cv::waitKey(0);
delete[] out_compressed;
delete[] out_uncompressed;
return 0;
}
上面的程序压缩了lena.jpg
图片,然后再解压。
可以调试查看是否压缩成功和是否解压成原图。
2.5 以上程序汇总
2.5.1 CMakeLists.txt
cmake_minimum_required(VERSION 3.6)
project(demo_jpeg-turbo)
#---------------------------------------------------------------------------------------
# jpeg turbo
#---------------------------------------------------------------------------------------
set(libjpeg-turbo_DIR "D:/test/jpeg-turbo_install/lib/cmake/libjpeg-turbo")
find_package(libjpeg-turbo REQUIRED)
#---------------------------------------------------------------------------------------
# OpenCV
#---------------------------------------------------------------------------------------
find_package( OpenCV REQUIRED )
#---------------------------------------------------------------------------------------
# ${PROJECT_NAME}
#---------------------------------------------------------------------------------------
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} libjpeg-turbo::turbojpeg-static)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} )
## set ${PROJECT_NAME} as startup project
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME})
2.5.2 main.cpp
#include <iostream>
#include "opencv2/opencv.hpp"
#include <turbojpeg.h>
bool Compress(unsigned char *data_uncompressed, unsigned char* &out_compressed, unsigned long *out_size, int width, int height, int pixel_format)
{
if (nullptr == data_uncompressed) {
return false;
}
tjhandle compressor = tjInitCompress();
if (nullptr == compressor) {
return false;
}
//pixel_format : TJPF::TJPF_BGR or other
const int JPEG_QUALITY = 75;
int pitch = tjPixelSize[pixel_format] * width;
int status = tjCompress2(compressor, data_uncompressed, width, pitch, height, pixel_format,
&out_compressed, out_size, TJSAMP_444, JPEG_QUALITY, TJFLAG_FASTDCT);
if (status != 0) {
tjDestroy(compressor);
return false;
}
tjDestroy(compressor);
return true;
}
bool Decompress(uint8_t* data_compressed, uint32_t size, uint8_t* &out_uncompressed, int pixel_format)
{
if (nullptr == data_compressed || nullptr == out_uncompressed) {
return false;
}
int width = 0, height = 0, jpegsubsamp = 0;
void* decompressor = tjInitDecompress();
if (nullptr == decompressor) {
return false;
}
if (tjDecompressHeader2(decompressor, data_compressed, size, &width, &height, &jpegsubsamp) != 0) {
tjDestroy(decompressor);
return false;
}
// pixel_format : TJPF::TJPF_BGR or other
int pitch = tjPixelSize[pixel_format] * width;
uint32_t len = pitch * height;
int flags = TJFLAG_FASTDCT;
int status = tjDecompress2(decompressor, data_compressed, len, out_uncompressed, width, pitch,
height, pixel_format, flags);
if ( status != 0) {
tjDestroy(decompressor);
return false;
}
tjDestroy(decompressor);
return true;
}
int main()
{
cv::Mat image = cv::imread("../lena.jpg");
unsigned char *data_uncompressed = image.data;
unsigned char* out_compressed = nullptr;
unsigned long out_size = 0;
int pixel_format = TJPF::TJPF_BGR;
int width = image.cols;
int height = image.rows;
int channels = image.channels();
bool status = Compress(data_uncompressed, out_compressed, &out_size, width, height, pixel_format);
if (false == status) {
std::cout << "Compress failed" << std::endl;
}
uint8_t* out_uncompressed = new uint8_t[width*height*channels];
status = Decompress(out_compressed, out_size, out_uncompressed, pixel_format);
if (false == status) {
std::cout << "Decompress failed" << std::endl;
}
cv::Mat image_decompress(height, width, CV_8UC3, out_uncompressed);
cv::imshow("out_uncompressed", image_decompress);
cv::waitKey(0);
delete[] out_compressed;
delete[] out_uncompressed;
return 0;
}