📄 dim_jpeg_format_io.cpp
字号:
/*****************************************************************************
JPEG IO
Copyright (c) 2004 by Dmitry V. Fedorov <www.dimin.net> <dima@dimin.net>
IMPLEMENTATION
Programmer: Dima V. Fedorov <mailto:dima@dimin.net> <http://www.dimin.net/>
History:
03/29/2004 22:23 - First creation
08/04/2004 22:25 - Update to FMT_IFS 1.2, support for io protorypes
Ver : 2
*****************************************************************************/
#include "dim_jpeg_format.h"
struct my_error_mgr : public jpeg_error_mgr { jmp_buf setjmp_buffer;};
extern "C" {static void my_error_exit (j_common_ptr cinfo){ my_error_mgr* myerr = (my_error_mgr*) cinfo->err; char buffer[JMSG_LENGTH_MAX]; (*cinfo->err->format_message)(cinfo, buffer); longjmp(myerr->setjmp_buffer, 1);}}static const int max_buf = 4096;
//****************************************************************************
// READ STUFF
//****************************************************************************/*struct my_jpeg_source_mgr : public jpeg_source_mgr { // Nothing dynamic - cannot rely on destruction over longjump FILE* stream; JOCTET buffer[max_buf];public: my_jpeg_source_mgr(FILE* new_stream);};extern "C" {static void dimjpeg_init_source(j_decompress_ptr){}static boolean dimjpeg_fill_input_buffer(j_decompress_ptr cinfo){ int num_read; my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src; src->next_input_byte = src->buffer;
num_read = fread( src->buffer, 1, max_buf, src->stream); if ( num_read <= 0 )
{ // Insert a fake EOI marker - as per jpeglib recommendation src->buffer[0] = (JOCTET) 0xFF; src->buffer[1] = (JOCTET) JPEG_EOI; src->bytes_in_buffer = 2; }
else
src->bytes_in_buffer = num_read;
return TRUE;}static void dimjpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes){ my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src; // `dumb' implementation from jpeglib // Just a dumb implementation for now. Could use fseek() except // it doesn't work on pipes. Not clear that being smart is worth // any trouble anyway --- large skips are infrequent. if (num_bytes > 0)
{ while (num_bytes > (long) src->bytes_in_buffer)
{ num_bytes -= (long) src->bytes_in_buffer; (void) dimjpeg_fill_input_buffer(cinfo); // note we assume that qt_fill_input_buffer will never return FALSE, // so suspension need not be handled. } src->next_input_byte += (size_t) num_bytes; src->bytes_in_buffer -= (size_t) num_bytes; }}static void dimjpeg_term_source(j_decompress_ptr){}} // extern Cinline my_jpeg_source_mgr::my_jpeg_source_mgr(FILE* new_stream){ jpeg_source_mgr::init_source = dimjpeg_init_source; jpeg_source_mgr::fill_input_buffer = dimjpeg_fill_input_buffer; jpeg_source_mgr::skip_input_data = dimjpeg_skip_input_data; jpeg_source_mgr::resync_to_restart = jpeg_resync_to_restart; jpeg_source_mgr::term_source = dimjpeg_term_source; stream = new_stream; bytes_in_buffer = 0; next_input_byte = buffer;}*/
struct my_jpeg_source_mgr : public jpeg_source_mgr {
// Nothing dynamic - cannot rely on destruction over longjump
TDimFormatHandle *fmtHndl;
JOCTET buffer[max_buf];
public:
my_jpeg_source_mgr(TDimFormatHandle *new_hndl);
};
extern "C" {
static void dimjpeg_init_source(j_decompress_ptr)
{
}
static boolean dimjpeg_fill_input_buffer(j_decompress_ptr cinfo)
{
int num_read;
my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src;
src->next_input_byte = src->buffer;
//num_read = fread( src->buffer, 1, max_buf, src->stream);
num_read = dimRead( src->fmtHndl, src->buffer, 1, max_buf );
if ( num_read <= 0 )
{
// Insert a fake EOI marker - as per jpeglib recommendation
src->buffer[0] = (JOCTET) 0xFF;
src->buffer[1] = (JOCTET) JPEG_EOI;
src->bytes_in_buffer = 2;
}
else
src->bytes_in_buffer = num_read;
return TRUE;
}
static void dimjpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
{
my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src;
// `dumb' implementation from jpeglib
// Just a dumb implementation for now. Could use fseek() except
// it doesn't work on pipes. Not clear that being smart is worth
// any trouble anyway --- large skips are infrequent.
if (num_bytes > 0)
{
while (num_bytes > (long) src->bytes_in_buffer)
{
num_bytes -= (long) src->bytes_in_buffer;
(void) dimjpeg_fill_input_buffer(cinfo);
// note we assume that qt_fill_input_buffer will never return FALSE,
// so suspension need not be handled.
}
src->next_input_byte += (size_t) num_bytes;
src->bytes_in_buffer -= (size_t) num_bytes;
}
}
static void dimjpeg_term_source(j_decompress_ptr)
{
}
} // extern C
inline my_jpeg_source_mgr::my_jpeg_source_mgr(TDimFormatHandle *new_hndl)
{
jpeg_source_mgr::init_source = dimjpeg_init_source;
jpeg_source_mgr::fill_input_buffer = dimjpeg_fill_input_buffer;
jpeg_source_mgr::skip_input_data = dimjpeg_skip_input_data;
jpeg_source_mgr::resync_to_restart = jpeg_resync_to_restart;
jpeg_source_mgr::term_source = dimjpeg_term_source;
fmtHndl = new_hndl;
bytes_in_buffer = 0;
next_input_byte = buffer;
}
//----------------------------------------------------------------------------
// READ PROC
//----------------------------------------------------------------------------
static int read_jpeg_image(TDimFormatHandle *fmtHndl)
{
JSAMPROW row_pointer[1];
TDimImageBitmap *image = fmtHndl->image; struct jpeg_decompress_struct cinfo; //struct my_jpeg_source_mgr *iod_src = new my_jpeg_source_mgr( fmtHndl->stream );
struct my_jpeg_source_mgr *iod_src = new my_jpeg_source_mgr( fmtHndl ); struct my_error_mgr jerr; jpeg_create_decompress(&cinfo); cinfo.src = iod_src; cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = my_error_exit;
if (!setjmp(jerr.setjmp_buffer)) {
(void) jpeg_read_header(&cinfo, TRUE); (void) jpeg_start_decompress(&cinfo);
if (allocImg( image, cinfo.output_width, cinfo.output_height, cinfo.output_components, 8 ) != 0)
{
jpeg_destroy_decompress(&cinfo);
return 1;
}
if (cinfo.output_components == 1) { while (cinfo.output_scanline < cinfo.output_height)
{ row_pointer[0] = ((uchar *) image->bits[0]) + (cinfo.output_width*cinfo.output_scanline);
(void) jpeg_read_scanlines( &cinfo, row_pointer, 1 );
} } // if 1 component
if ( cinfo.output_components == 3 )
{
row_pointer[0] = new uchar[cinfo.output_width*cinfo.output_components];
while (cinfo.output_scanline < cinfo.output_height)
{
register unsigned int i;
(void) jpeg_read_scanlines( &cinfo, row_pointer, 1 );
uchar *row = row_pointer[0];
uchar* pix1 = ((uchar *) image->bits[0]) + cinfo.output_width * (cinfo.output_scanline-1);
uchar* pix2 = ((uchar *) image->bits[1]) + cinfo.output_width * (cinfo.output_scanline-1);
uchar* pix3 = ((uchar *) image->bits[2]) + cinfo.output_width * (cinfo.output_scanline-1);
for (i=0; i<cinfo.output_width; i++)
{
*pix1++ = *row++;
*pix2++ = *row++;
*pix3++ = *row++;
}
} // while scanlines
delete row_pointer[0];
} // if 3 components
if ( cinfo.output_components == 4 )
{
row_pointer[0] = new uchar[cinfo.output_width*cinfo.output_components];
while (cinfo.output_scanline < cinfo.output_height)
{
register unsigned int i;
(void) jpeg_read_scanlines( &cinfo, row_pointer, 1 );
uchar *row = row_pointer[0];
uchar* pix1 = ((uchar *) image->bits[0]) + cinfo.output_width * (cinfo.output_scanline-1);
uchar* pix2 = ((uchar *) image->bits[1]) + cinfo.output_width * (cinfo.output_scanline-1);
uchar* pix3 = ((uchar *) image->bits[2]) + cinfo.output_width * (cinfo.output_scanline-1);
uchar* pix4 = ((uchar *) image->bits[3]) + cinfo.output_width * (cinfo.output_scanline-1);
for (i=0; i<cinfo.output_width; i++)
{
*pix1++ = *row++;
*pix2++ = *row++;
*pix3++ = *row++;
*pix4++ = *row++;
}
} // while scanlines
delete row_pointer[0];
} // if 4 components
(void) jpeg_finish_decompress(&cinfo);
}
jpeg_destroy_decompress(&cinfo); delete iod_src;
return 0;}
//****************************************************************************
// WRITE STUFF
//****************************************************************************
/*
struct my_jpeg_destination_mgr : public jpeg_destination_mgr { // Nothing dynamic - cannot rely on destruction over longjump FILE* stream; JOCTET buffer[max_buf];public: my_jpeg_destination_mgr(FILE* stream);};extern "C" {static void dimjpeg_init_destination(j_compress_ptr){}static void dimjpeg_exit_on_error(j_compress_ptr cinfo, FILE* stream){ // cinfo->err->msg_code = JERR_FILE_WRITE; fflush( stream );
(*cinfo->err->error_exit)((j_common_ptr)cinfo);
}static boolean dimjpeg_empty_output_buffer(j_compress_ptr cinfo){ my_jpeg_destination_mgr* dest = (my_jpeg_destination_mgr*)cinfo->dest;
if ( fwrite((char*)dest->buffer, 1, max_buf, dest->stream) != max_buf )
dimjpeg_exit_on_error(cinfo, dest->stream);
fflush( dest->stream ); dest->next_output_byte = dest->buffer; dest->free_in_buffer = max_buf; return TRUE;}static void dimjpeg_term_destination(j_compress_ptr cinfo){ my_jpeg_destination_mgr* dest = (my_jpeg_destination_mgr*)cinfo->dest; unsigned int n = max_buf - dest->free_in_buffer;
if ( fwrite((char*)dest->buffer, 1, n, dest->stream) != n )
dimjpeg_exit_on_error(cinfo, dest->stream);
fflush( dest->stream ); dimjpeg_exit_on_error( cinfo, dest->stream );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -