C++ 使用 libjpeg 写入内存缓冲区而不是文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4559648/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Write to memory buffer instead of file with libjpeg?
提问by Richard Knop
I have found this function which uses libjpeg to write to a file:
我发现这个函数使用 libjpeg 写入文件:
int write_jpeg_file( char *filename )
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
/* this is a pointer to one row of image data */
JSAMPROW row_pointer[1];
FILE *outfile = fopen( filename, "wb" );
if ( !outfile )
{
printf("Error opening output jpeg file %s\n!", filename );
return -1;
}
cinfo.err = jpeg_std_error( &jerr );
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, outfile);
/* Setting the parameters of the output file here */
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = bytes_per_pixel;
cinfo.in_color_space = color_space;
/* default compression parameters, we shouldn't be worried about these */
jpeg_set_defaults( &cinfo );
/* Now do the compression .. */
jpeg_start_compress( &cinfo, TRUE );
/* like reading a file, this time write one row at a time */
while( cinfo.next_scanline < cinfo.image_height )
{
row_pointer[0] = &raw_image[ cinfo.next_scanline * cinfo.image_width * cinfo.input_components];
jpeg_write_scanlines( &cinfo, row_pointer, 1 );
}
/* similar to read file, clean up after we're done compressing */
jpeg_finish_compress( &cinfo );
jpeg_destroy_compress( &cinfo );
fclose( outfile );
/* success code is 1! */
return 1;
}
I would actually need to write the jpeg compressed image just to memory buffer, without saving it to a file, to save time. Could somebody give me an example how to do it?
我实际上需要将 jpeg 压缩图像写入内存缓冲区,而不将其保存到文件中,以节省时间。有人能给我一个例子吗?
I have been searching the web for a while but the documentation is very rare if any and examples are also difficult to come by.
我已经在网上搜索了一段时间,但是文档非常少见,而且示例也很难找到。
采纳答案by Mark Ransom
You can define your own destination manager quite easily. The jpeg_compress_struct
contains a pointer to a jpeg_destination_mgr
, which contains a pointer to a buffer, a count of space left in the buffer, and 3 pointers to functions:
您可以很容易地定义自己的目的地管理器。的jpeg_compress_struct
包含一个指向一个jpeg_destination_mgr
,其中包含一个指向缓冲区的指针,中剩余的缓冲空间的计数,和3名的指针功能:
init_destination (j_compress_ptr cinfo)
empty_output_buffer (j_compress_ptr cinfo)
term_destination (j_compress_ptr cinfo)
You need to fill in the function pointers before you make the first call into the jpeg library, and let those functions handle the buffer. If you create a buffer that is larger than the largest possible output that you expect, this becomes trivial; init_destination
just fills in the buffer pointer and count, and empty_output_buffer
and term_destination
do nothing.
您需要在第一次调用 jpeg 库之前填充函数指针,并让这些函数处理缓冲区。如果您创建的缓冲区大于您期望的最大可能输出,这将变得微不足道;init_destination
只是填补了缓冲区指针和计数,以及empty_output_buffer
和term_destination
什么也不做。
Here's some sample code:
这是一些示例代码:
std::vector<JOCTET> my_buffer;
#define BLOCK_SIZE 16384
void my_init_destination(j_compress_ptr cinfo)
{
my_buffer.resize(BLOCK_SIZE);
cinfo->dest->next_output_byte = &my_buffer[0];
cinfo->dest->free_in_buffer = my_buffer.size();
}
boolean my_empty_output_buffer(j_compress_ptr cinfo)
{
size_t oldsize = my_buffer.size();
my_buffer.resize(oldsize + BLOCK_SIZE);
cinfo->dest->next_output_byte = &my_buffer[oldsize];
cinfo->dest->free_in_buffer = my_buffer.size() - oldsize;
return true;
}
void my_term_destination(j_compress_ptr cinfo)
{
my_buffer.resize(my_buffer.size() - cinfo->dest->free_in_buffer);
}
cinfo->dest->init_destination = &my_init_destination;
cinfo->dest->empty_output_buffer = &my_empty_output_buffer;
cinfo->dest->term_destination = &my_term_destination;
回答by dmitriykovalev
There is a predefined function jpeg_mem_src
defined in jdatasrc.c
. The simplest usage example:
中jpeg_mem_src
定义了一个预定义的函数jdatasrc.c
。最简单的用法示例:
unsigned char *mem = NULL;
unsigned long mem_size = 0;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_mem_dest(&cinfo, &mem, &mem_size);
// do compression
// use mem buffer
Do not forget to deallocate your buffer.
不要忘记释放缓冲区。
回答by Gus Z
I have tried Mark's solution and on my platform it always gives SEGMENTATION FALUT error when it executes
我已经尝试过 Mark 的解决方案,在我的平台上它总是在执行时出现 SEGMENTATION FALUT 错误
cinfo->dest->term_destination = &my_term_destination;
And I turned to the jpeglib source codes (jdatadst.c) and found this:
我转向 jpeglib 源代码 (jdatadst.c) 并发现:
jpeg_mem_dest (j_compress_ptr cinfo, unsigned char ** outbuffer, unsigned long * outsize)
just below the method jpeg_stdio_dest(), and I've tried it by simply fill in the address of the buffer(char*) and the address of the buffer size(int). The destination manager automatically allocates memory for the buffer and the program need to free the memory after use.
就在方法 jpeg_stdio_dest() 的正下方,我已经通过简单地填写缓冲区的地址 (char*) 和缓冲区大小的地址 (int) 来尝试它。目标管理器自动为缓冲区分配内存,程序使用后需要释放内存。
It successfully runs on my platform, Beaglebone Black with the pre-installed Angstrom Linux. My libjpeg version is 8d.
它成功地在我的平台 Beaglebone Black 上运行,并预装了 Angstrom Linux。我的 libjpeg 版本是 8d。
回答by s kettle
unsigned char ***image_ptr
unsigned char* ptr;
unsigned char** image_buf;
for(int i=0;i<h;i++){
image_buf[i] = new unsigned char[w*o];
}
ptr = image_buf[0];
while (info.output_scanline < info.image_height) {
jpeg_read_scanlines(&info,&ptr,1);
ptr = image_buf[c];
c++;
}
*image_ptr = image_buf;
This is all you need to read.
这就是您需要阅读的全部内容。
JSAMPROW row_pointer;
while (info.next_scanline < info.image_height) {
row_pointer = &image_buf[info.next_scanline][0];
(void) jpeg_write_scanlines(&info, &row_pointer, 1);
}
And this is all you need to write.
这就是您需要编写的全部内容。
回答by Conrad Meyer
All you need to do is pass a FILE
-like object to jpeg_stdio_dest()
.
您需要做的就是将一个类似FILE
对象传递给jpeg_stdio_dest()
.