X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bba6f3bd3c8fc28acab21c839523156017b26996..eeccd5d94ce6b11f36af95db4ac528a2e2e0c4c5:/src/common/image.cpp diff --git a/src/common/image.cpp b/src/common/image.cpp index a7d34cce08..2338740986 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -23,13 +23,24 @@ #include "wx/debug.h" #include "wx/log.h" #include "wx/app.h" -#ifdef wxUSE_LIBPNG +#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" +#ifdef __SALFORDC__ +#ifdef FAR +#undef FAR +#endif +#endif + #ifdef __WXMSW__ #include #endif @@ -94,10 +105,12 @@ wxImage::wxImage( const wxString& name, long type ) LoadFile( name, type ); } +#if wxUSE_STREAMS wxImage::wxImage( wxInputStream& stream, long type ) { LoadFile( stream, type ); } +#endif // wxUSE_STREAMS wxImage::wxImage( const wxImage& image ) { @@ -304,6 +317,7 @@ int wxImage::GetHeight() const bool wxImage::LoadFile( const wxString& filename, long type ) { +#if wxUSE_STREAMS if (wxFileExists(filename)) { wxFileInputStream stream(filename); @@ -311,12 +325,28 @@ bool wxImage::LoadFile( const wxString& filename, long type ) } else { - wxLogWarning( "Image file does not exist." ); + wxLogError( "Can't load image from file '%s': file does not exist.", filename.c_str() ); return FALSE; } +#else // !wxUSE_STREAMS + return FALSE; +#endif // wxUSE_STREAMS +} + +bool wxImage::SaveFile( const wxString& filename, int type ) +{ +#if wxUSE_STREAMS + wxFileOutputStream stream(filename); + + if ( stream.LastError() == wxStream_NOERROR ) + return SaveFile(stream, type); + else +#endif // wxUSE_STREAMS + return FALSE; } +#if wxUSE_STREAMS bool wxImage::LoadFile( wxInputStream& stream, long type ) { UnRef(); @@ -335,16 +365,6 @@ bool wxImage::LoadFile( wxInputStream& stream, long type ) return handler->LoadFile( this, stream ); } -bool wxImage::SaveFile( const wxString& filename, int type ) -{ - wxFileOutputStream stream(filename); - - if ( stream.LastError() == wxStream_NOERROR ) - return SaveFile(stream, type); - else - return FALSE; -} - bool wxImage::SaveFile( wxOutputStream& stream, int type ) { wxCHECK_MSG( Ok(), FALSE, "invalid image" ); @@ -360,6 +380,7 @@ bool wxImage::SaveFile( wxOutputStream& stream, int type ) return handler->SaveFile( this, stream ); } +#endif // wxUSE_STREAMS void wxImage::AddHandler( wxImageHandler *handler ) { @@ -395,7 +416,8 @@ wxImageHandler *wxImage::FindHandler( const wxString& name ) while (node) { wxImageHandler *handler = (wxImageHandler*)node->Data(); - if (handler->GetName() == name) return handler; + if (handler->GetName().Cmp(name) == 0) return handler; + node = node->Next(); } return (wxImageHandler *)NULL; @@ -407,7 +429,7 @@ wxImageHandler *wxImage::FindHandler( const wxString& extension, long bitmapType while (node) { wxImageHandler *handler = (wxImageHandler*)node->Data(); - if ( handler->GetExtension() == extension && + if ( (handler->GetExtension().Cmp(extension) == 0) && (bitmapType == -1 || handler->GetType() == bitmapType) ) return handler; node = node->Next(); @@ -430,9 +452,12 @@ wxImageHandler *wxImage::FindHandler( long bitmapType ) void wxImage::InitStandardHandlers() { AddHandler( new wxBMPHandler ); -#ifdef wxUSE_LIBPNG +#if wxUSE_LIBPNG AddHandler( new wxPNGHandler ); #endif +#if wxUSE_LIBJPEG + AddHandler( new wxJPEGHandler ); +#endif } void wxImage::CleanUpHandlers() @@ -456,6 +481,7 @@ void wxImage::CleanUpHandlers() IMPLEMENT_DYNAMIC_CLASS(wxImageHandler,wxObject) #endif +#if wxUSE_STREAMS bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream) ) { return FALSE; @@ -465,18 +491,20 @@ bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSE { return FALSE; } +#endif // wxUSE_STREAMS //----------------------------------------------------------------------------- // wxPNGHandler //----------------------------------------------------------------------------- -#ifdef wxUSE_LIBPNG +#if wxUSE_LIBPNG #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler,wxImageHandler) #endif +#if wxUSE_STREAMS static void _PNG_stream_reader( png_structp png_ptr, png_bytep data, png_size_t length ) { ((wxInputStream*) png_get_io_ptr( png_ptr )) -> Read(data, length); @@ -729,11 +757,226 @@ bool wxPNGHandler::SaveFile( wxImage *image, wxOutputStream& stream ) } return TRUE; } +#endif // wxUSE_STREAMS #endif // 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 //----------------------------------------------------------------------------- @@ -742,6 +985,7 @@ bool wxPNGHandler::SaveFile( wxImage *image, wxOutputStream& stream ) IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler) #endif +#if wxUSE_STREAMS bool wxBMPHandler::LoadFile( wxImage *image, wxInputStream& stream ) { unsigned char *data, *ptr; @@ -1091,6 +1335,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, wxInputStream& stream ) return TRUE; } +#endif // wxUSE_STREAMS #ifdef __WXMSW__ @@ -1700,8 +1945,6 @@ wxImage::wxImage( const wxBitmap &bitmap ) #endif -// TODO - #ifdef __WXMOTIF__ #include