2009-09-18 10 views
5

Mam ten problem. Mam IplImage, które chcę skompresować do JPEG i coś z nim zrobić. Używam libjpeg. Znalazłem wiele odpowiedzi "przeczytaj przykłady i dokumenty" i takie i to zrobiłem. I z powodzeniem napisałem do tego funkcję.Kompresowanie IplImage do JPEG za pomocą libjpeg w OpenCV

FILE* convert2jpeg(IplImage* frame) 
{ 
FILE* outstream = NULL; 
outstream=malloc(frame->imageSize*frame->nChannels*sizeof(char)) 

unsigned char *outdata = (uchar *) frame->imageData; 
struct jpeg_error_mgr jerr; 
struct jpeg_compress_struct cinfo; 
int row_stride; 
JSAMPROW row_ptr[1]; 

jpeg_create_compress(&cinfo); 
jpeg_stdio_dest(&cinfo, outstream); 

cinfo.image_width = frame->width; 
cinfo.image_height = frame->height; 
cinfo.input_components = frame->nChannels; 
cinfo.in_color_space = JCS_RGB; 

jpeg_set_defaults(&cinfo); 
jpeg_start_compress(&cinfo, TRUE); 
row_stride = frame->width * frame->nChannels; 

while (cinfo.next_scanline < cinfo.image_height) { 
    row_ptr[0] = &outdata[cinfo.next_scanline * row_stride]; 
    jpeg_write_scanlines(&cinfo, row_ptr, 1); 
} 

jpeg_finish_compress(&cinfo); 
jpeg_destroy_compress(&cinfo); 

return outstream; 
} 

Teraz ta funkcja jest prosto z przykładów (z wyjątkiem części alokacji pamięci, ale muszę, że skoro nie jestem writnig do pliku), ale nadal nie działa. Umiera na jpeg_start_compress (& cinfo, TRUE); część?

Czy ktoś może pomóc?

Odpowiedz

1

Po walce z libJpeg przez 2 dni (wskaźniki, wchodzenie w pamięć i ciągnięcie za włosy) poddałem się i zastosowałem wszystkie ulubione metody zapisu na dysk, aby załadować pamięć, więc jeśli ktokolwiek jest zainteresowany, to metoda:

char* convert2jpeg(IplImage* frame, int* frame_size) { 

FILE* infile = NULL; 
struct stat fileinfo_buf; 

if (cvSaveImage(name_buf, frame) < 0) { 
    printf("\nCan't save image %s", name_buf); 
    return NULL; 
} 

if (stat(name_buf, &fileinfo_buf) < 0) { 
    printf("\nPLAYER [convert2jpeg] stat"); 
    return NULL; 
} 

*frame_size = fileinfo_buf.st_size; 
char* buffer = (char *) malloc(fileinfo_buf.st_size + 1); 

if ((infile = fopen(name_buf, "rb")) == NULL) { 
    printf("\nPLAYER [convert2jpeg] fopen %s", name_buf); 
    free(buffer); 
    return NULL; 
} 

fread(buffer, fileinfo_buf.st_size, 1, infile); 
fclose(infile); 

return buffer; 
} 

Mam nadzieję, że ktoś uzna to za przydatne. Chciałbym, aby ktoś z twórców OpenCV zobaczył ten wątek i zaimplementował bezpośrednio do buforowania konwersji JPEG w OpenCV i oszczędził nam nieszczęścia i 1 operacji zapisu/ładowania na dysk.

7

Byłem w stanie znaleźć rozwiązanie, korzystając z najnowszego jpeglib dostępnego na ich stronie internetowej. Nowe metody w: jpeg_mem_dest (& cinfo, outbuffer, outlen);

bool ipl2jpeg(IplImage *frame, unsigned char **outbuffer, long unsigned int *outlen) { 
unsigned char *outdata = (uchar *) frame->imageData; 
struct jpeg_compress_struct cinfo = {0}; 
struct jpeg_error_mgr jerr; 
JSAMPROW row_ptr[1]; 
int row_stride; 

*outbuffer = NULL; 
*outlen = 0; 

cinfo.err = jpeg_std_error(&jerr); 
jpeg_create_compress(&cinfo); 
jpeg_mem_dest(&cinfo, outbuffer, outlen); 

cinfo.image_width = frame->width; 
cinfo.image_height = frame->height; 
cinfo.input_components = frame->nChannels; 
cinfo.in_color_space = JCS_RGB; 

jpeg_set_defaults(&cinfo); 
jpeg_start_compress(&cinfo, TRUE); 
row_stride = frame->width * frame->nChannels; 

while (cinfo.next_scanline < cinfo.image_height) { 
    row_ptr[0] = &outdata[cinfo.next_scanline * row_stride]; 
    jpeg_write_scanlines(&cinfo, row_ptr, 1); 
} 

jpeg_finish_compress(&cinfo); 
jpeg_destroy_compress(&cinfo); 

return true; 

} 
3

Mam go do pracy przy użyciu następującego kodu kompresji pamięci do pamięci.

#include <stdio.h> 
#include "jpeg/jpeglib.h" 

    /* 
This a custom destination manager for jpeglib that 
enables the use of memory to memory compression. 

See IJG documentation for details. 
*/ 
typedef struct { 
struct jpeg_destination_mgr pub; /* base class */ 
JOCTET* buffer; /* buffer start address */ 
int bufsize; /* size of buffer */ 
size_t datasize; /* final size of compressed data */ 
int* outsize; /* user pointer to datasize */ 
int errcount; /* counts up write errors due to 
buffer overruns */ 
} memory_destination_mgr; 

typedef memory_destination_mgr* mem_dest_ptr; 

/* ------------------------------------------------------------- */ 
/* MEMORY DESTINATION INTERFACE METHODS */ 
/* ------------------------------------------------------------- */ 


/* This function is called by the library before any data gets written */ 
METHODDEF(void) 
init_destination (j_compress_ptr cinfo) 
{ 
mem_dest_ptr dest = (mem_dest_ptr)cinfo->dest; 

dest->pub.next_output_byte = dest->buffer; /* set destination buffer */ 
dest->pub.free_in_buffer = dest->bufsize; /* input buffer size */ 
dest->datasize = 0; /* reset output size */ 
dest->errcount = 0; /* reset error count */ 
} 

/* This function is called by the library if the buffer fills up 

I just reset destination pointer and buffer size here. 
Note that this behavior, while preventing seg faults 
will lead to invalid output streams as data is over- 
written. 
*/ 
METHODDEF(boolean) 
empty_output_buffer (j_compress_ptr cinfo) 
{ 
mem_dest_ptr dest = (mem_dest_ptr)cinfo->dest; 
dest->pub.next_output_byte = dest->buffer; 
dest->pub.free_in_buffer = dest->bufsize; 
++dest->errcount; /* need to increase error count */ 

return TRUE; 
} 

/* Usually the library wants to flush output here. 

I will calculate output buffer size here. 
Note that results become incorrect, once 
empty_output_buffer was called. 
This situation is notified by errcount. 
*/ 
METHODDEF(void) 
term_destination (j_compress_ptr cinfo) 
{ 
mem_dest_ptr dest = (mem_dest_ptr)cinfo->dest; 
dest->datasize = dest->bufsize - dest->pub.free_in_buffer; 
if (dest->outsize) *dest->outsize += (int)dest->datasize; 
} 

/* Override the default destination manager initialization 
provided by jpeglib. Since we want to use memory-to-memory 
compression, we need to use our own destination manager. 
*/ 
GLOBAL(void) 
jpeg_memory_dest (j_compress_ptr cinfo, JOCTET* buffer, int bufsize, int* outsize) 
{ 
mem_dest_ptr dest; 

/* first call for this instance - need to setup */ 
if (cinfo->dest == 0) { 
cinfo->dest = (struct jpeg_destination_mgr *) 
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, 
sizeof (memory_destination_mgr)); 
} 

dest = (mem_dest_ptr) cinfo->dest; 
dest->bufsize = bufsize; 
dest->buffer = buffer; 
dest->outsize = outsize; 
/* set method callbacks */ 
dest->pub.init_destination = init_destination; 
dest->pub.empty_output_buffer = empty_output_buffer; 
dest->pub.term_destination = term_destination; 
} 

/* ------------------------------------------------------------- */ 
/* MEMORY SOURCE INTERFACE METHODS */ 
/* ------------------------------------------------------------- */ 

/* Called before data is read */ 
METHODDEF(void) 
init_source (j_decompress_ptr dinfo) 
{ 
/* nothing to do here, really. I mean. I'm not lazy or something, but... 
we're actually through here. */ 
} 

/* Called if the decoder wants some bytes that we cannot provide... */ 
METHODDEF(boolean) 
fill_input_buffer (j_decompress_ptr dinfo) 
{ 
/* we can't do anything about this. This might happen if the provided 
buffer is either invalid with regards to its content or just a to 
small bufsize has been given. */ 

/* fail. */ 
return FALSE; 
} 

/* From IJG docs: "it's not clear that being smart is worth much trouble" 
So I save myself some trouble by ignoring this bit. 
*/ 
METHODDEF(void) 
skip_input_data (j_decompress_ptr dinfo, INT32 num_bytes) 
{ 
/* There might be more data to skip than available in buffer. 
This clearly is an error, so screw this mess. */ 
if ((size_t)num_bytes > dinfo->src->bytes_in_buffer) { 
dinfo->src->next_input_byte = 0; /* no buffer byte */ 
dinfo->src->bytes_in_buffer = 0; /* no input left */ 
} else { 
dinfo->src->next_input_byte += num_bytes; 
dinfo->src->bytes_in_buffer -= num_bytes; 
} 
} 

/* Finished with decompression */ 
METHODDEF(void) 
term_source (j_decompress_ptr dinfo) 
{ 
/* Again. Absolute laziness. Nothing to do here. Boring. */ 
} 

GLOBAL(void) 
jpeg_memory_src (j_decompress_ptr dinfo, unsigned char* buffer, size_t size) 
{ 
struct jpeg_source_mgr* src; 

/* first call for this instance - need to setup */ 
if (dinfo->src == 0) { 
dinfo->src = (struct jpeg_source_mgr *) 
(*dinfo->mem->alloc_small) ((j_common_ptr) dinfo, JPOOL_PERMANENT, 
sizeof (struct jpeg_source_mgr)); 
} 

src = dinfo->src; 
src->next_input_byte = buffer; 
src->bytes_in_buffer = size; 
src->init_source = init_source; 
src->fill_input_buffer = fill_input_buffer; 
src->skip_input_data = skip_input_data; 
src->term_source = term_source; 
/* IJG recommend to use their function - as I don't know **** 
about how to do better, I follow this recommendation */ 
src->resync_to_restart = jpeg_resync_to_restart; 
} 

A w swojej głównej funkcji kompresji wymienić jpeg_stdio_dest z

int numBytes = 0; //size of jpeg after compression 
char * storage = new char[150000]; //storage buffer 
JOCTET *jpgbuff = (JOCTET*)storage; //JOCTET pointer to buffer 
jpeg_memory_dest(&cinfo,jpgbuff,150000,&numBytes); 

150000 jest bufor statyczny rozmiar, prawdopodobnie będzie mieć zdjęcia, które będzie ona przekroczyć, więc przeznaczyć odpowiednio.

3

Mam kompresję w pamięci do pracy. Zobacz następujące

#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite’able size */ 

/* Expanded data destination object for memory output */ 

typedef struct { 
struct jpeg_destination_mgr pub; /* public fields */ 

unsigned char ** outbuffer; /* target buffer */ 
unsigned long * outsize; 
unsigned char * newbuffer; /* newly allocated buffer */ 
JOCTET * buffer; /* start of buffer */ 
size_t bufsize; 
} my_mem_destination_mgr; 

typedef my_mem_destination_mgr * my_mem_dest_ptr; 

void 
init_mem_destination (j_compress_ptr cinfo) 
{ 
/* no work necessary here */ 
} 

boolean 
empty_mem_output_buffer (j_compress_ptr cinfo) 
{ 
size_t nextsize; 
JOCTET * nextbuffer; 
my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; 

/* Try to allocate new buffer with double size */ 
nextsize = dest->bufsize * 2; 
nextbuffer = (JOCTET *)malloc(nextsize); 

if (nextbuffer == NULL) 
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); 

memcpy(nextbuffer, dest->buffer, dest->bufsize); 

if (dest->newbuffer != NULL) 
free(dest->newbuffer); 

dest->newbuffer = nextbuffer; 

dest->pub.next_output_byte = nextbuffer + dest->bufsize; 
dest->pub.free_in_buffer = dest->bufsize; 

dest->buffer = nextbuffer; 
dest->bufsize = nextsize; 

return TRUE; 
} 

void 
term_mem_destination (j_compress_ptr cinfo) 
{ 
my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; 

*dest->outbuffer = dest->buffer; 
*dest->outsize = dest->bufsize – dest->pub.free_in_buffer; 
} 

void 
jpeg_mem_dest (j_compress_ptr cinfo, 
unsigned char ** outbuffer, unsigned long * outsize) 
{ 
my_mem_dest_ptr dest; 

if (outbuffer == NULL || outsize == NULL) /* sanity check */ 
ERREXIT(cinfo, JERR_BUFFER_SIZE); 

/* The destination object is made permanent so that multiple JPEG images 
* can be written to the same buffer without re-executing jpeg_mem_dest. 
*/ 
if (cinfo->dest == NULL) { /* first time for this JPEG object? */ 
cinfo->dest = (struct jpeg_destination_mgr *) 
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, 
sizeof(my_mem_destination_mgr)); 
} 

dest = (my_mem_dest_ptr) cinfo->dest; 
dest->pub.init_destination = init_mem_destination; 
dest->pub.empty_output_buffer = empty_mem_output_buffer; 
dest->pub.term_destination = term_mem_destination; 
dest->outbuffer = outbuffer; 
dest->outsize = outsize; 
dest->newbuffer = NULL; 

if (*outbuffer == NULL || *outsize == 0) { 
/* Allocate initial buffer */ 
dest->newbuffer = *outbuffer = (unsigned char*)malloc(OUTPUT_BUF_SIZE); 
if (dest->newbuffer == NULL) 
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); 
*outsize = OUTPUT_BUF_SIZE; 
} 

dest->pub.next_output_byte = dest->buffer = *outbuffer; 
dest->pub.free_in_buffer = dest->bufsize = *outsize; 
} 
//******************************************************************************************* 

Aby korzystać z tego zrobić coś takiego w głównym

/************/ 

unsigned long outlen; 
unsigned char *outbuffer; 

jpeg_mem_dest (&cinfo,&outbuffer,&outlen); 
printf(“outlen is %lu\n”,(long unsigned int)outlen); 
Powiązane problemy