diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plJPEG/plJPEG.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plJPEG/plJPEG.cpp index a16485af..a97d9cc1 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plJPEG/plJPEG.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plJPEG/plJPEG.cpp @@ -41,23 +41,54 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "hsUtils.h" #include "../plGImage/plMipmap.h" +#ifdef IJL_SDK_AVAILABLE #ifndef HS_BUILD_FOR_WIN32 #error Currently the JPEG libraries don't build for anything but Win32. If you're building this on a non-Win32 platform....WHY?? #endif #include "../../../../../StaticSDKs/Win32/IJL/include/ijl.h" +#else +#include "jpeglib.h" +#include "jerror.h" +#endif //// Local Statics //////////////////////////////////////////////////////////// // Done this way so we don't have to declare them in the .h file and pull in // the platform-specific library +#ifdef IJL_SDK_AVAILABLE static IJLERR sLastErrCode = IJL_OK; +#else +// It is not thread-safe to use a static char buffer, but it wasn't really +// thread-safe to use a static int either. The char buffer is slightly +// worse since you could get mangled strings instead of just a stale error. +static char jpegmsg[JMSG_LENGTH_MAX]; + +// jpeglib error handlers +static void plJPEG_error_exit( j_common_ptr cinfo ) +{ + (*cinfo->err->format_message) ( cinfo, jpegmsg ); + throw ( false ); +} +static void plJPEG_emit_message( j_common_ptr cinfo, int msg_level ) +{ + // log NOTHING +} +static void clear_jpegmsg() +{ + // "Success" is what IJL produced for no error + strcpy( jpegmsg, "Success" ); +} +#endif //// Instance ///////////////////////////////////////////////////////////////// plJPEG &plJPEG::Instance( void ) { +#ifndef IJL_SDK_AVAILABLE + clear_jpegmsg(); +#endif static plJPEG theInstance; return theInstance; } @@ -66,7 +97,11 @@ plJPEG &plJPEG::Instance( void ) const char *plJPEG::GetLastError( void ) { +#ifdef IJL_SDK_AVAILABLE return ijlErrorStr( sLastErrCode ); +#else + return jpegmsg; +#endif } //// IRead //////////////////////////////////////////////////////////////////// @@ -87,17 +122,33 @@ plMipmap *plJPEG::IRead( hsStream *inStream ) UInt8 *jpegSourceBuffer = nil; UInt32 jpegSourceSize; +#ifdef IJL_SDK_AVAILABLE JPEG_CORE_PROPERTIES jcProps; +#else + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; +#endif +#ifdef IJL_SDK_AVAILABLE sLastErrCode = IJL_OK; +#else + clear_jpegmsg(); + cinfo.err = jpeg_std_error( &jerr ); + jerr.error_exit = plJPEG_error_exit; + jerr.emit_message = plJPEG_emit_message; +#endif try { +#ifdef IJL_SDK_AVAILABLE /// Init the IJL library sLastErrCode = ijlInit( &jcProps ); if( sLastErrCode != IJL_OK ) throw( false ); +#else + jpeg_create_decompress( &cinfo ); +#endif /// Read in the JPEG header if ( inStream->GetEOF() == 0 ) @@ -111,19 +162,32 @@ plMipmap *plJPEG::IRead( hsStream *inStream ) jpegSourceBuffer = TRACKED_NEW UInt8[ jpegSourceSize ]; if( jpegSourceBuffer == nil ) { +#ifdef IJL_SDK_AVAILABLE sLastErrCode = IJL_MEMORY_ERROR; throw( false ); +#else + // waah. + ERREXIT1( &cinfo, JERR_OUT_OF_MEMORY, 0 ); +#endif } inStream->Read( jpegSourceSize, jpegSourceBuffer ); +#ifdef IJL_SDK_AVAILABLE jcProps.JPGFile = nil; jcProps.JPGBytes = jpegSourceBuffer; jcProps.JPGSizeBytes = jpegSourceSize; +#else + jpeg_mem_src( &cinfo, jpegSourceBuffer, jpegSourceSize ); +#endif +#ifdef IJL_SDK_AVAILABLE sLastErrCode = ijlRead( &jcProps, IJL_JBUFF_READPARAMS ); if( sLastErrCode != IJL_OK ) throw( false ); +#else + (void) jpeg_read_header( &cinfo, TRUE ); +#endif /// So we got lots of data to play with now. First, set the JPEG color /// space to read in from/as... @@ -137,8 +201,13 @@ plMipmap *plJPEG::IRead( hsStream *inStream ) // are in the YCbCr color space and 1 channel images are // in the Y color space." +#ifdef IJL_SDK_AVAILABLE switch( jcProps.JPGChannels ) +#else + switch( cinfo.jpeg_color_space ) +#endif { +#ifdef IJL_SDK_AVAILABLE case 1: jcProps.JPGColor = IJL_G; jcProps.DIBColor = IJL_RGBA_FPX; @@ -150,25 +219,48 @@ plMipmap *plJPEG::IRead( hsStream *inStream ) jcProps.DIBColor = IJL_RGBA_FPX; jcProps.DIBChannels = 4; break; +#else + case JCS_GRAYSCALE: + case JCS_YCbCr: + cinfo.out_color_space = JCS_RGBA; + break; +#endif default: // We should probably assert here, since we're pretty sure we WON'T get ARGB. hsAssert( false, "Unknown JPEG stream format in ReadFromStream()" ); +#ifdef IJL_SDK_AVAILABLE jcProps.JPGColor = IJL_OTHER; jcProps.DIBColor = IJL_OTHER; jcProps.DIBChannels = jcProps.JPGChannels; +#else + cinfo.out_color_space = JCS_UNKNOWN; +#endif break; } +#ifndef IJL_SDK_AVAILABLE + (void) jpeg_start_decompress( &cinfo ); +#endif + /// Construct a new mipmap to hold everything +#ifdef IJL_SDK_AVAILABLE newMipmap = TRACKED_NEW plMipmap( jcProps.JPGWidth, jcProps.JPGHeight, plMipmap::kRGB32Config, 1, plMipmap::kJPEGCompression ); +#else + newMipmap = TRACKED_NEW plMipmap( cinfo.output_width, cinfo.output_height, plMipmap::kRGB32Config, 1, plMipmap::kJPEGCompression ); +#endif if( newMipmap == nil || newMipmap->GetImage() == nil ) { +#ifdef IJL_SDK_AVAILABLE sLastErrCode = IJL_MEMORY_ERROR; throw( false ); +#else + ERREXIT1( &cinfo, JERR_OUT_OF_MEMORY, 0 ); +#endif } /// Set up to read in to that buffer we now have +#ifdef IJL_SDK_AVAILABLE jcProps.DIBWidth = newMipmap->GetWidth(); jcProps.DIBHeight = newMipmap->GetHeight(); jcProps.DIBPadBytes = 0; @@ -177,6 +269,13 @@ plMipmap *plJPEG::IRead( hsStream *inStream ) sLastErrCode = ijlRead( &jcProps, IJL_JBUFF_READWHOLEIMAGE ); if( sLastErrCode != IJL_OK ) throw( false ); +#else + while( cinfo.output_scanline < cinfo.output_height ) + { + UInt8 *startp = newMipmap->GetAddr8( 0, cinfo.output_scanline ); + (void) jpeg_read_scanlines( &cinfo, &startp, 1 ); + } +#endif // Sometimes life just sucks ISwapRGBAComponents( (UInt32 *)newMipmap->GetImage(), newMipmap->GetWidth() * newMipmap->GetHeight() ); @@ -191,7 +290,11 @@ plMipmap *plJPEG::IRead( hsStream *inStream ) delete [] jpegSourceBuffer; // Clean up the IJL Library +#ifdef IJL_SDK_AVAILABLE ijlFree( &jcProps ); +#else + jpeg_destroy_decompress( &cinfo ); +#endif MemPopDisableTracking(); // All done! @@ -226,56 +329,116 @@ hsBool plJPEG::IWrite( plMipmap *source, hsStream *outStream ) UInt8 *jpgBuffer = nil; UInt32 jpgBufferSize = 0; +#ifdef IJL_SDK_AVAILABLE JPEG_CORE_PROPERTIES jcProps; +#else + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; +#endif +#ifndef IJL_SDK_AVAILABLE + clear_jpegmsg(); + cinfo.err = jpeg_std_error( &jerr ); + jerr.error_exit = plJPEG_error_exit; + jerr.emit_message = plJPEG_emit_message; +#endif + try { +#ifdef IJL_SDK_AVAILABLE // Init the IJL Library sLastErrCode = ijlInit( &jcProps ); if( sLastErrCode != IJL_OK ) throw( false ); +#else + jpeg_create_compress( &cinfo ); +#endif // Create a buffer to hold the data jpgBufferSize = source->GetWidth() * source->GetHeight() * 3; jpgBuffer = TRACKED_NEW UInt8[ jpgBufferSize ]; if( jpgBuffer == nil ) { +#ifdef IJL_SDK_AVAILABLE sLastErrCode = IJL_MEMORY_ERROR; throw( false ); +#else + ERREXIT1( &cinfo, JERR_OUT_OF_MEMORY, 0 ); +#endif } +#ifdef IJL_SDK_AVAILABLE jcProps.JPGFile = nil; jcProps.JPGBytes = jpgBuffer; jcProps.JPGSizeBytes = jpgBufferSize; +#else + UInt8 *bufferAddr = jpgBuffer; + UInt32 bufferSize = jpgBufferSize; + jpeg_mem_dest( &cinfo, &bufferAddr, &bufferSize ); +#endif +#ifdef IJL_SDK_AVAILABLE jcProps.DIBWidth = source->GetWidth(); jcProps.DIBHeight = source->GetHeight(); jcProps.DIBBytes = (UInt8 *)source->GetImage(); jcProps.DIBPadBytes = 0; jcProps.DIBChannels = 4; jcProps.DIBColor = IJL_RGB; +#else + cinfo.image_width = source->GetWidth(); + cinfo.image_height = source->GetHeight(); + cinfo.input_components = 4; + cinfo.in_color_space = JCS_RGBA; + jpeg_set_defaults( &cinfo ); +#endif + +#ifdef IJL_SDK_AVAILABLE jcProps.JPGWidth = source->GetWidth(); jcProps.JPGHeight = source->GetHeight(); jcProps.JPGChannels = 3; jcProps.JPGColor = IJL_YCBCR; jcProps.JPGSubsampling = IJL_411; // 4:1:1 subsampling jcProps.jquality = fWriteQuality; +#else + cinfo.jpeg_width = source->GetWidth(); // default + cinfo.jpeg_width = source->GetHeight(); // default + cinfo.jpeg_color_space = JCS_YCbCr; // default + // not sure how to set 4:1:1 but supposedly it's the default + jpeg_set_quality( &cinfo, fWriteQuality, TRUE ); + + jpeg_start_compress( &cinfo, TRUE ); +#endif // Sometimes life just sucks ISwapRGBAComponents( (UInt32 *)source->GetImage(), source->GetWidth() * source->GetHeight() ); swapped = true; // Write it! +#ifdef IJL_SDK_AVAILABLE sLastErrCode = ijlWrite( &jcProps, IJL_JBUFF_WRITEWHOLEIMAGE ); if( sLastErrCode != IJL_OK ) throw( false ); +#else + while( cinfo.next_scanline < cinfo.image_height ) + { + UInt8 *startp = source->GetAddr8( 0, cinfo.next_scanline ); + (void) jpeg_write_scanlines( &cinfo, &startp, 1 ); + } + jpeg_finish_compress( &cinfo ); +#endif +#ifdef IJL_SDK_AVAILABLE // On output, the IJL fills our image buffer with the JPEG stream, plus changes JPGSizeBytes to // the length of the stream outStream->WriteSwap32( jcProps.JPGSizeBytes ); outStream->Write( jcProps.JPGSizeBytes, jcProps.JPGBytes ); +#else + // jpeglib similarly changes bufferSize and bufferAddr + outStream->WriteSwap32( bufferSize ); + outStream->Write( bufferSize, bufferAddr ); +#endif } catch( ... ) { @@ -285,7 +448,11 @@ hsBool plJPEG::IWrite( plMipmap *source, hsStream *outStream ) // Cleanup if ( jpgBuffer ) delete [] jpgBuffer; +#ifdef IJL_SDK_AVAILABLE ijlFree( &jcProps ); +#else + jpeg_destroy_compress( &cinfo ); +#endif if( swapped ) ISwapRGBAComponents( (UInt32 *)source->GetImage(), source->GetWidth() * source->GetHeight() );