Подтвердить что ты не робот

Запись в буфер памяти вместо файла с 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 %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;
}

Мне действительно нужно было бы записать сжатый образ jpeg только в буфер памяти, не сохраняя его в файл, чтобы сэкономить время. Может ли кто-нибудь дать мне пример, как это сделать?

Я искал в Интернете какое-то время, но документация очень редка, если что-то и примеры тоже трудно найти.

4b9b3361

Ответ 1

Вы можете легко определить своего менеджера назначения. 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;

Ответ 2

Существует предопределенная функция 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

Не забудьте освободить буфер.

Ответ 3

Я попробовал решение Mark, и на моей платформе он всегда дает ошибку SEGMENTATION 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.

Ответ 4

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);



                                }

И это все, что вам нужно написать.

Ответ 5

Все, что вам нужно сделать, это передать объект FILE -like в jpeg_stdio_dest().