私はlibjpegを使ってjpegに画像を圧縮する方法を議論する別の質問を見つけました。動作するようになっている、このコードを、私を発見した:libjpegでoバッファを書くのにもう少し助けてください。
Compressing IplImage to JPEG using libjpeg in OpenCV
ここでは、コード(それはOKコンパイル)です:
/*
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;
}
は私がする必要があるのは、これで私のプログラムでjpeg_stdio_destを交換ですコード:
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);
だから、私は今の代わりにメモリのファイルに動作しますが、書き込みをこの関数に上記の4本のラインを組み込むためにいくつかの助けが必要:
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_stdio_dest(&cinfo, outfile);
これはうまくいかないでしょう。その機能で少し変更する必要があるものがあり、私はそれらのポインタとメモリ管理から少し失われています。 jpeg_memory_destため
私は既にVirtualBoxを閉じました。私は明日もう一度お試しになり、うまくいかなければエラーも投稿します。 –