Browse Source

The Intel JPEG Library is no longer free. Since we can't just remove all

JPEG handling, replace IJL with the jpeg library from IJG, unless
IJL_SDK_AVAILABLE is defined.
cypythonide
a'moaca' 13 years ago
parent
commit
656b466ad7
  1. 167
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plJPEG/plJPEG.cpp

167
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. <sigh>
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() );

Loading…
Cancel
Save