From 56b9c74101566aa241d1846a148d3a01980b7431 Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Wed, 27 Jan 1999 16:13:16 +0000 Subject: [PATCH] added wxJPEGHandler git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1497 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/gdicmn.h | 2 + include/wx/image.h | 26 +++++ src/common/image.cpp | 222 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 250 insertions(+) diff --git a/include/wx/gdicmn.h b/include/wx/gdicmn.h index 9ea245de1c..fe82c80e4f 100644 --- a/include/wx/gdicmn.h +++ b/include/wx/gdicmn.h @@ -179,6 +179,8 @@ class WXDLLEXPORT wxRegion; #define wxBITMAP_TYPE_GIF_RESOURCE 14 #define wxBITMAP_TYPE_PNG 15 #define wxBITMAP_TYPE_PNG_RESOURCE 16 +#define wxBITMAP_TYPE_JPEG 17 +#define wxBITMAP_TYPE_JPEG_RESOURCE 18 #define wxBITMAP_TYPE_ANY 50 #define wxBITMAP_TYPE_RESOURCE wxBITMAP_TYPE_BMP_RESOURCE diff --git a/include/wx/image.h b/include/wx/image.h index c548f26c91..325c7a9a53 100644 --- a/include/wx/image.h +++ b/include/wx/image.h @@ -31,6 +31,9 @@ class WXDLLEXPORT wxImageHandler; #if wxUSE_LIBPNG class WXDLLEXPORT wxPNGHandler; #endif +#if wxUSE_LIBJPEG +class WXDLLEXPORT wxJPEGHandler; +#endif class WXDLLEXPORT wxBMPHandler; class WXDLLEXPORT wxImage; @@ -92,6 +95,29 @@ public: }; #endif +//----------------------------------------------------------------------------- +// wxJPEGHandler +//----------------------------------------------------------------------------- + +#ifdef wxUSE_LIBJPEG +class WXDLLEXPORT wxJPEGHandler: public wxImageHandler +{ + DECLARE_DYNAMIC_CLASS(wxJPEGHandler) + +public: + + inline wxJPEGHandler() + { + m_name = "JPEG file"; + m_extension = "jpg"; + m_type = wxBITMAP_TYPE_JPEG; + }; + + virtual bool LoadFile( wxImage *image, wxInputStream& stream ); + virtual bool SaveFile( wxImage *image, wxOutputStream& stream ); +}; +#endif + //----------------------------------------------------------------------------- // wxBMPHandler //----------------------------------------------------------------------------- diff --git a/src/common/image.cpp b/src/common/image.cpp index a5b3a74df6..2338740986 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -26,6 +26,11 @@ #if wxUSE_LIBPNG #include "../png/png.h" #endif +#if wxUSE_LIBJPEG +extern "C" { +#include +} +#endif #include "wx/filefn.h" #include "wx/wfstream.h" #include "wx/intl.h" @@ -450,6 +455,9 @@ void wxImage::InitStandardHandlers() #if wxUSE_LIBPNG AddHandler( new wxPNGHandler ); #endif +#if wxUSE_LIBJPEG + AddHandler( new wxJPEGHandler ); +#endif } void wxImage::CleanUpHandlers() @@ -755,6 +763,220 @@ bool wxPNGHandler::SaveFile( wxImage *image, wxOutputStream& stream ) // wxUSE_LIBPNG + +//----------------------------------------------------------------------------- +// wxJPEGHandler +//----------------------------------------------------------------------------- + +#if wxUSE_LIBJPEG + +#if !USE_SHARED_LIBRARIES +IMPLEMENT_DYNAMIC_CLASS(wxJPEGHandler,wxImageHandler) +#endif + +#if wxUSE_STREAMS + + +//------------- JPEG Data Source Manager + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + JOCTET* buffer; /* start of buffer */ +} my_source_mgr; + +typedef my_source_mgr * my_src_ptr; + +METHODDEF(void) my_init_source ( j_decompress_ptr cinfo ) +{ +} + +METHODDEF(boolean) my_fill_input_buffer ( j_decompress_ptr cinfo ) +{ + return TRUE; +} + +METHODDEF(void) my_skip_input_data ( j_decompress_ptr cinfo, long num_bytes ) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; +} + +METHODDEF(void) my_term_source ( j_decompress_ptr cinfo ) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + free (src->buffer); +} + +void jpeg_wxio_src( j_decompress_ptr cinfo, wxInputStream& infile ) +{ + my_src_ptr src; + + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + sizeof(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + } + src = (my_src_ptr) cinfo->src; + src->pub.bytes_in_buffer = infile.StreamSize(); /* forces fill_input_buffer on first read */ + src->buffer = (JOCTET *) malloc (infile.StreamSize()); + src->pub.next_input_byte = src->buffer; /* until buffer loaded */ + infile.Read(src->buffer, infile.StreamSize()); + + src->pub.init_source = my_init_source; + src->pub.fill_input_buffer = my_fill_input_buffer; + src->pub.skip_input_data = my_skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = my_term_source; +} + + + +bool wxJPEGHandler::LoadFile( wxImage *image, wxInputStream& stream ) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + JSAMPARRAY tempbuf; + unsigned char *ptr; + unsigned stride; + + image->Destroy(); + cinfo.err = jpeg_std_error( &jerr ); + jpeg_create_decompress( &cinfo ); + jpeg_wxio_src( &cinfo, stream ); + jpeg_read_header( &cinfo, TRUE ); + cinfo.out_color_space = JCS_RGB; + jpeg_start_decompress( &cinfo ); + + image->Create( cinfo.image_width, cinfo.image_height ); + if (!image->Ok()) { + jpeg_finish_decompress( &cinfo ); + jpeg_destroy_decompress( &cinfo ); + return FALSE; + } + image->SetMask( FALSE ); + ptr = image->GetData(); + stride = cinfo.output_width * 3; + tempbuf = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, stride, 1 ); + + while ( cinfo.output_scanline < cinfo.output_height ) { + jpeg_read_scanlines( &cinfo, tempbuf, 1 ); + memcpy( ptr, tempbuf[0], stride ); + ptr += stride; + } + jpeg_finish_decompress( &cinfo ); + jpeg_destroy_decompress( &cinfo ); + return TRUE; +} + + + + + +typedef struct { + struct jpeg_destination_mgr pub; + + wxOutputStream *stream; + JOCTET * buffer; +} my_destination_mgr; + +typedef my_destination_mgr * my_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + +METHODDEF(void) init_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * sizeof(JOCTET)); + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + +METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + dest->stream->Write(dest->buffer, OUTPUT_BUF_SIZE); + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + return TRUE; +} + +METHODDEF(void) term_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + /* Write any data remaining in the buffer */ + if (datacount > 0) + dest->stream->Write(dest->buffer, datacount); +} + +GLOBAL(void) jpeg_wxio_dest (j_compress_ptr cinfo, wxOutputStream& outfile) +{ + my_dest_ptr 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_destination_mgr)); + } + + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->stream = &outfile; +} + + + +bool wxJPEGHandler::SaveFile( wxImage *image, wxOutputStream& stream ) +{ + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + JSAMPLE *image_buffer; + int stride; /* physical row width in image buffer */ + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + jpeg_wxio_dest(&cinfo, stream); + + cinfo.image_width = image->GetWidth(); + cinfo.image_height = image->GetHeight(); + cinfo.input_components = 3; + cinfo.in_color_space = JCS_RGB; + jpeg_set_defaults(&cinfo); + jpeg_start_compress(&cinfo, TRUE); + + stride = cinfo.image_width * 3; /* JSAMPLEs per row in image_buffer */ + image_buffer = image->GetData(); + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer[0] = &image_buffer[cinfo.next_scanline * stride]; + jpeg_write_scanlines( &cinfo, row_pointer, 1 ); + } + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + return TRUE; +} +#endif // wxUSE_STREAMS + +#endif + + // wxUSE_LIBJPEG + + + //----------------------------------------------------------------------------- // wxBMPHandler //----------------------------------------------------------------------------- -- 2.45.2