2010-12-30 9 views
21

He encontrado esta función que utiliza libjpeg escribir en un archivo:Escribir en el búfer de memoria en lugar de archivo con 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; 
} 

De hecho, me tiene que escribir la imagen JPEG comprimido sólo para búfer de memoria, sin guardar en un archivo, para ahorrar tiempo. ¿Alguien podría darme un ejemplo de cómo hacerlo?

He estado buscando en la web por un tiempo, pero la documentación es muy rara si hay alguna y los ejemplos también son difíciles de encontrar.

Respuesta

15

Puede definir su propio administrador de destinos con bastante facilidad. El jpeg_compress_struct contiene un puntero a una jpeg_destination_mgr, que contiene un puntero a un tampón, un recuento del espacio que queda en la memoria intermedia, y 3 punteros a funciones:

init_destination (j_compress_ptr cinfo) 
empty_output_buffer (j_compress_ptr cinfo) 
term_destination (j_compress_ptr cinfo) 

Es necesario rellenar los punteros de función antes de hacer la primera llamada a la biblioteca jpeg, y deja que esas funciones manejen el búfer. Si crea un búfer que es más grande que el mayor resultado posible que espera, esto se vuelve trivial; init_destination solo rellena el puntero del búfer y cuenta, y empty_output_buffer y term_destination no hacen nada.

He aquí algunos ejemplos de código:

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; 
+0

Imagino que estos indicadores de función son a lo que 'jpeg_stdio_dest' afecta? –

+0

@Ben Voigt, mirando la fuente a 'jpeg_stdio_dest' eso es exactamente lo que hace. Asigna una estructura y la establece en 'cinfo-> dest', luego establece los punteros.Creo que mi propio código de muestra puede estar un poco incompleto ya que no crea una estructura 'jpeg_destination_mgr', pero lo investigaré más adelante. –

+0

Oh, por supuesto. Puede [almacenar sus propios datos (el 'std :: vector'] inmediatamente después de los punteros a la función y no necesita variables globales] (http://blogs.msdn.com/b/oldnewthing/archive/2010/12/20/ 10107027.aspx). –

0

Todo lo que necesita hacer es pasar un objeto similar a FILE al jpeg_stdio_dest().

9

hay una función predefinida jpeg_mem_src definido en jdatasrc.c. El ejemplo de uso más simple:

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 

No olvide desasignar su memoria intermedia.

+0

No en mi' jdatasrc.c' (libjpeg-6b). –

+2

La última versión estable de libjpeg es 9, puede obtenerla aquí http://www.ijg.org/files/jpegsr9.zip y contiene jpeg_mem_src. – dmitriykovalev

+0

¿Llamas gratis o eliminas en el buffer de mem? Llamé a delete [] y valgrind me dio una advertencia de eliminación no coincidente. Usado gratis() y la advertencia desapareció. – shehzan

3

He intentado la solución de Marcos y en mi plataforma que siempre da error falut SEGMENTACIÓN cuando se ejecuta

cinfo->dest->term_destination = &my_term_destination; 

Y volvió a los códigos fuente (jpeglib jdatadst.c) y se encontró lo siguiente:

jpeg_mem_dest (j_compress_ptr cinfo, unsigned char ** outbuffer, unsigned long * outsize) 

justo debajo del método jpeg_stdio_dest(), y lo he intentado simplemente llene la dirección del buffer (char *) y la dirección del tamaño del buffer (int). El administrador de destino asigna automáticamente memoria para el búfer y el programa necesita liberar la memoria después de su uso.

Se ejecuta con éxito en mi plataforma, Beaglebone Black con el Angstrom Linux preinstalado. Mi versión libjpeg es 8d.

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

Esto es todo lo que necesita para leer.

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



           } 

Y esto es todo lo que necesita para escribir.

+8

** Advertencia **: no utilice obscenidades en sus publicaciones. Lo he eliminado por ti. Tenga en cuenta que otros usuarios pueden haber marcado su publicación como "grosera o abusiva", lo que puede ocasionar la posible pérdida o suspensión de la reputación. Por favor, lea [Be Nice] (http://superuser.com/help/be-nice): "Evite los términos vulgares y cualquier cosa sexualmente sugestiva" – DavidPostill

Cuestiones relacionadas