Записать в буфер памяти вместо файла с libjpeg?
Я нашел эту функцию, которая использует 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 %sn!", 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;
}
Мне действительно нужно будет записать сжатое изображение jpeg только в буфер памяти, не сохраняя его в файл, чтобы сэкономить время. Может кто-нибудь дать мне пример, как это сделать?
Я искал в интернете некоторое время, но документация очень редка, если таковые имеются, и примеры также трудно найти.
5 ответов
вы можете определить свой собственный менеджер пункта назначения довольно легко. The 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)
вам нужно заполнить указатели функций перед первым вызовом в библиотеку jpeg и позволить этим функциям обрабатывать буфер. Если вы создаете буфер, который больше, чем максимально возможный выход, который вы ожидаете, это становится тривиальным; init_destination
просто заполняет указатель буфера и счетчик, и empty_output_buffer
и term_destination
ничего не делать.
вот пример кода:
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;
существует предопределенная функция 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
не забудьте освободить буфер.
Я пробовал решение Марка, и на моей платформе он всегда дает ошибку FALUT сегментации при выполнении
cinfo->dest->term_destination = &my_term_destination;
и я обратился к исходным кодам jpeglib (jdatadst.C) и нашел это:
jpeg_mem_dest (j_compress_ptr cinfo, unsigned char ** outbuffer, unsigned long * outsize)
чуть ниже метода jpeg_stdio_dest (), и я попробовал его, просто заполнив адрес буфера(char*) и адрес размера буфера (int). Диспетчер назначения автоматически выделяет память для буфера, и программе необходимо освободить память после использования.
он успешно работает на моей платформе, BeagleBone Black с предустановленным Angstrom Linux. Моя версия libjpeg-8d.
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;
Это все, что вам нужно читать.
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);
}
и это все, что вам нужно написать.