使用libjpeg-turbo的TurboJPEG的示例或教程

这里的libjpeg-turbo指令描述了TurboJPEG API:“这个API包装了libjpeg-turbo,并提供了一个易于使用的界面,用于压缩和解压缩内存中的JPEG图像”。 很好,但是有一些使用此API的可靠实例吗? 只是想在内存中解压一个相当香草的jpeg。

我找到了一些比如https://github.com/erlyvideo/jpeg/blob/master/c_src/jpeg.c ,它似乎使用的是TurboJPEG API,但还有更多可靠/多变的例子吗?

libjpeg-turbo的来源已有详细记录,因此确实有帮助。

好的,我知道你已经解决了你的问题,但正如有些人,就像我一样,可能会搜索一些简单的例子,我会分享我创建的内容。 这是一个压缩和解压缩RGB图像的例子。 否则我认为TurboJPEG的API文档很容易理解!

压缩:

#include  const int JPEG_QUALITY = 75; const int COLOR_COMPONENTS = 3; int _width = 1920; int _height = 1080; long unsigned int _jpegSize = 0; unsigned char* _compressedImage = NULL; //!< Memory is allocated by tjCompress2 if _jpegSize == 0 unsigned char buffer[_width*_height*COLOR_COMPONENTS]; //!< Contains the uncompressed image tjhandle _jpegCompressor = tjInitCompress(); tjCompress2(_jpegCompressor, buffer, _width, 0, _height, TJPF_RGB, &_compressedImage, &_jpegSize, TJSAMP_444, JPEG_QUALITY, TJFLAG_FASTDCT); tjDestroy(_jpegCompressor); //to free the memory allocated by TurboJPEG (either by tjAlloc(), //or by the Compress/Decompress) after you are done working on it: tjFree(&_compressedImage); 

之后,您将在_compressedImage中获得压缩图像。 要解压缩,您必须执行以下操作:

减压:

 #include  long unsigned int _jpegSize; //!< _jpegSize from above unsigned char* _compressedImage; //!< _compressedImage from above int jpegSubsamp, width, height; unsigned char buffer[width*height*COLOR_COMPONENTS]; //!< will contain the decompressed image tjhandle _jpegDecompressor = tjInitDecompress(); tjDecompressHeader2(_jpegDecompressor, _compressedImage, _jpegSize, &width, &height, &jpegSubsamp); tjDecompress2(_jpegDecompressor, _compressedImage, _jpegSize, buffer, width, 0/*pitch*/, height, TJPF_RGB, TJFLAG_FASTDCT); tjDestroy(_jpegDecompressor); 

一些随意的想法:

我刚刚写完我的学士论文,我注意到如果你在循环中运行压缩,最好存储JPEG缓冲区的最大大小,而不必每回合分配一个新的。 基本上,而不是做:

 long unsigned int _jpegSize = 0; tjCompress2(_jpegCompressor, buffer, _width, 0, _height, TJPF_RGB, &_compressedImage, &_jpegSize, TJSAMP_444, JPEG_QUALITY, TJFLAG_FASTDCT); 

我们将添加一个对象变量,保持已分配内存的大小long unsigned int _jpegBufferSize = 0; 在每次压缩循环之前,我们将jpegSize设置回该值:

 long unsigned int jpegSize = _jpegBufferSize; tjCompress2(_jpegCompressor, buffer, _width, 0, _height, TJPF_RGB, &_compressedImage, &jpegSize, TJSAMP_444, JPEG_QUALITY, TJFLAG_FASTDCT); _jpegBufferSize = _jpegBufferSize >= jpegSize? _jpegBufferSize : jpegSize; 

在压缩之后,可以将内存大小与实际的jpegSize进行比较,如果它高于先前的内存大小,则将其设置为jpegSize。

最后,我使用了互联网上的随机代码组合(例如https://github.com/erlyvideo/jpeg/blob/master/c_src/jpeg.c )和libjeg-turbo的.c和头文件,这些都有很好的记录。 这个官方API也是一个很好的信息来源。

我最终使用下面的代码作为JPEG编码和解码的工作示例。 我能找到的最好的例子是,它是自包含的,初始化虚拟图像并将编码图像输出到本地文件。

下面的代码不是我自己的,信用转到https://sourceforge.net/p/libjpeg-turbo/discussion/1086868/thread/e402d36f/#8722 。 再次在这里发布,以帮助任何人发现很难让libjpeg turbo工作。

 #include "turbojpeg.h" #include  #include  #include  using namespace std; int main(void) { unsigned char *srcBuf; //passed in as a param containing pixel data in RGB pixel interleaved format tjhandle handle = tjInitCompress(); if(handle == NULL) { const char *err = (const char *) tjGetErrorStr(); cerr << "TJ Error: " << err << " UNABLE TO INIT TJ Compressor Object\n"; return -1; } int jpegQual =92; int width = 128; int height = 128; int nbands = 3; int flags = 0; unsigned char* jpegBuf = NULL; int pitch = width * nbands; int pixelFormat = TJPF_GRAY; int jpegSubsamp = TJSAMP_GRAY; if(nbands == 3) { pixelFormat = TJPF_RGB; jpegSubsamp = TJSAMP_411; } unsigned long jpegSize = 0; srcBuf = new unsigned char[width * height * nbands]; for(int j = 0; j < height; j++) { for(int i = 0; i < width; i++) { srcBuf[(j * width + i) * nbands + 0] = (i) % 256; srcBuf[(j * width + i) * nbands + 1] = (j) % 256; srcBuf[(j * width + i) * nbands + 2] = (j + i) % 256; } } int tj_stat = tjCompress2( handle, srcBuf, width, pitch, height, pixelFormat, &(jpegBuf), &jpegSize, jpegSubsamp, jpegQual, flags); if(tj_stat != 0) { const char *err = (const char *) tjGetErrorStr(); cerr << "TurboJPEG Error: " << err << " UNABLE TO COMPRESS JPEG IMAGE\n"; tjDestroy(handle); handle = NULL; return -1; } FILE *file = fopen("out.jpg", "wb"); if (!file) { cerr << "Could not open JPEG file: " << strerror(errno); return -1; } if (fwrite(jpegBuf, jpegSize, 1, file) < 1) { cerr << "Could not write JPEG file: " << strerror(errno); return -1; } fclose(file); //write out the compress date to the image file //cleanup int tjstat = tjDestroy(handle); //should deallocate data buffer handle = 0; } 

这是我用来从内存加载jpeg的代码片段。 也许它需要一些修复,因为我从项目中的不同文件中提取它。 它将加载 – 灰度和rgb图像(bpp将设置为1或3)。

 struct Image { int bpp; int width; int height; unsigned char* data; }; struct jerror_mgr { jpeg_error_mgr base; jmp_buf jmp; }; METHODDEF(void) jerror_exit(j_common_ptr jinfo) { jerror_mgr* err = (jerror_mgr*)jinfo->err; longjmp(err->jmp, 1); } METHODDEF(void) joutput_message(j_common_ptr) { } bool Image_LoadJpeg(Image* image, unsigned char* img_data, unsigned int img_size) { jpeg_decompress_struct jinfo; jerror_mgr jerr; jinfo.err = jpeg_std_error(&jerr.base); jerr.base.error_exit = jerror_exit; jerr.base.output_message = joutput_message; jpeg_create_decompress(&jinfo); image->data = NULL; if (setjmp(jerr.jmp)) goto bail; jpeg_mem_src(&jinfo, img_data, img_size); if (jpeg_read_header(&jinfo, TRUE) != JPEG_HEADER_OK) goto bail; jinfo.dct_method = JDCT_FLOAT; // change this to JDCT_ISLOW on Android/iOS if (!jpeg_start_decompress(&jinfo)) goto bail; if (jinfo.num_components != 1 && jinfo.num_components != 3) goto bail; image->data = new (std::nothrow) unsigned char [jinfo.output_width * jinfo.output_height * jinfo.output_components]; if (!image->data) goto bail; { JSAMPROW ptr = image->data; while (jinfo.output_scanline < jinfo.output_height) { if (jpeg_read_scanlines(&jinfo, &ptr, 1) != 1) goto bail; ptr += jinfo.output_width * jinfo.output_components; } } if (!jpeg_finish_decompress(&jinfo)) goto bail; image->bpp = jinfo.output_components; image->width = jinfo.output_width; image->height = jinfo.output_height; jpeg_destroy_decompress(&jinfo); return true; bail: jpeg_destroy_decompress(&jinfo); if (image->data) delete [] data; return false; }