- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-IL/src/il_jpeg.c

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2000-2008 by Denton Woods
    00005 // Last modified: 05/26/2002 <--Y2K Compliant! =]
    00006 //
    00007 // Filename: src-IL/src/il_jpeg.c
    00008 //
    00009 // Description: Jpeg (.jpg) functions
    00010 //
    00011 //-----------------------------------------------------------------------------
    00012 //
    00013 // Most of the comments here are sufficient, as we're just using libjpeg.
    00014 //  I have left most of the libjpeg example's comments intact, though.
    00015 //
    00016
    00017 #include "il_internal.h"
    00018
    00019 #ifndef IL_NO_JPG
    00020         #ifndef IL_USE_IJL
    00021                 #ifdef RGB_RED
    00022                         #undef RGB_RED
    00023                         #undef RGB_GREEN
    00024                         #undef RGB_BLUE
    00025                 #endif
    00026                 #define RGB_RED         0
    00027                 #define RGB_GREEN       1
    00028                 #define RGB_BLUE        2
    00029
    00030                 #if defined(_MSC_VER)
    00031                         #pragma warning(push)
    00032                         #pragma warning(disable : 4005)  // Redefinitions in
    00033                         #pragma warning(disable : 4142)  //  jmorecfg.h
    00034                 #endif
    00035
    00036                 #include "jpeglib.h"
    00037
    00038                 #if JPEG_LIB_VERSION < 62
    00039                         #warning DevIL was designed with libjpeg 6b or higher in mind.  Consider upgrading at www.ijg.org
    00040                 #endif
    00041         #else
    00042                 #include <ijl.h>
    00043                 #include <limits.h>
    00044         #endif
    00045
    00046 #include "il_jpeg.h"
    00047 #include "il_manip.h"
    00048 #include <setjmp.h>
    00049
    00050
    00051 #if (defined(_WIN32) || defined(_WIN64)) && defined(IL_USE_PRAGMA_LIBS)
    00052         #if defined(_MSC_VER) || defined(__BORLANDC__)
    00053                 #ifdef IL_USE_IJL
    00054                         //pragma comment(lib, "ijl15.lib")
    00055                 #else
    00056                         #ifndef _DEBUG
    00057                                 #pragma comment(lib, "libjpeg.lib")
    00058                         #else
    00059                                 #pragma comment(lib, "libjpeg-d.lib")
    00060                         #endif
    00061                 #endif//IL_USE_IJL
    00062         #endif
    00063 #endif
    00064
    00065
    00066 static ILboolean jpgErrorOccured = IL_FALSE;
    00067
    00068 // define a protype of ilLoadFromJpegStruct
    00069 ILboolean ilLoadFromJpegStruct(void *_JpegInfo);
    00070
    00071 // Internal function used to get the .jpg header from the current file.
    00072 void iGetJpgHead(ILubyte *Header)
    00073 {
    00074         Header[0] = igetc();
    00075         Header[1] = igetc();
    00076         return;
    00077 }
    00078
    00079
    00080 // Internal function used to check if the HEADER is a valid .Jpg header.
    00081 ILboolean iCheckJpg(ILubyte Header[2])
    00082 {
    00083         if (Header[0] != 0xFF || Header[1] != 0xD8)
    00084                 return IL_FALSE;
    00085         return IL_TRUE;
    00086 }
    00087
    00088
    00089 // Internal function to get the header and check it.
    00090 ILboolean iIsValidJpeg()
    00091 {
    00092         ILubyte Head[2];
    00093
    00094         iGetJpgHead(Head);
    00095         iseek(-2, IL_SEEK_CUR);  // Go ahead and restore to previous state
    00096
    00097         return iCheckJpg(Head);
    00098 }
    00099
    00100
    00102 ILboolean ilIsValidJpeg(ILconst_string FileName)
    00103 {
    00104         ILHANDLE        JpegFile;
    00105         ILboolean       bJpeg = IL_FALSE;
    00106
    00107         if (!iCheckExtension(FileName, IL_TEXT( "jpg" ) ) &&
    00108                 !iCheckExtension(FileName, IL_TEXT( "jpe" ) ) &&
    00109                 !iCheckExtension(FileName, IL_TEXT( "jpeg" ) ) )
    00110         {
    00111                 ilSetError(IL_INVALID_EXTENSION);
    00112                 return bJpeg;
    00113         }
    00114
    00115         JpegFile = iopenr(FileName);
    00116         if (JpegFile == NULL) {
    00117                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00118                 return bJpeg;
    00119         }
    00120
    00121         bJpeg = ilIsValidJpegF(JpegFile);
    00122         icloser(JpegFile);
    00123
    00124         return bJpeg;
    00125 }
    00126
    00127
    00129 ILboolean ilIsValidJpegF(ILHANDLE File)
    00130 {
    00131         ILuint          FirstPos;
    00132         ILboolean       bRet;
    00133
    00134         iSetInputFile(File);
    00135         FirstPos = itell();
    00136         bRet = iIsValidJpeg();
    00137         iseek(FirstPos, IL_SEEK_SET);
    00138
    00139         return bRet;
    00140 }
    00141
    00142
    00143 ILboolean ilIsValidJpegL(const void *Lump, ILuint Size)
    00144 {
    00145         iSetInputLump(Lump, Size);
    00146         return iIsValidJpeg();
    00147 }
    00148
    00149
    00150 #ifndef IL_USE_IJL // Use libjpeg instead of the IJL.
    00151
    00152 // Overrides libjpeg's stupid error/warning handlers. =P
    00153 void ExitErrorHandle (struct jpeg_common_struct *JpegInfo)
    00154 {
    00155         ilSetError(IL_LIB_JPEG_ERROR);
    00156         jpgErrorOccured = IL_TRUE;
    00157         return;
    00158 }
    00159 void OutputMsg(struct jpeg_common_struct *JpegInfo)
    00160 {
    00161         return;
    00162 }
    00163
    00164
    00166 ILboolean ilLoadJpeg(ILconst_string FileName)
    00167 {
    00168         ILHANDLE        JpegFile;
    00169         ILboolean       bJpeg = IL_FALSE;
    00170
    00171         JpegFile = iopenr(FileName);
    00172         if (JpegFile == NULL) {
    00173                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00174                 return bJpeg;
    00175         }
    00176
    00177         bJpeg = ilLoadJpegF(JpegFile);
    00178         icloser(JpegFile);
    00179
    00180         return bJpeg;
    00181 }
    00182
    00183
    00185 ILboolean ilLoadJpegF(ILHANDLE File)
    00186 {
    00187         ILboolean       bRet;
    00188         ILuint          FirstPos;
    00189
    00190         iSetInputFile(File);
    00191         FirstPos = itell();
    00192         bRet = iLoadJpegInternal();
    00193         iseek(FirstPos, IL_SEEK_SET);
    00194
    00195         return bRet;
    00196 }
    00197
    00198
    00199 // Reads from a memory "lump" containing a jpeg
    00200 ILboolean ilLoadJpegL(const void *Lump, ILuint Size)
    00201 {
    00202         iSetInputLump(Lump, Size);
    00203         return iLoadJpegInternal();
    00204 }
    00205
    00206
    00207 typedef struct {
    00208   struct jpeg_source_mgr pub;   /* public fields */
    00209
    00210   JOCTET * buffer;              /* start of buffer */
    00211   boolean start_of_file;        /* have we gotten any data yet? */
    00212 } iread_mgr;
    00213
    00214 typedef iread_mgr * iread_ptr;
    00215
    00216 #define INPUT_BUF_SIZE  4096  // choose an efficiently iread'able size
    00217
    00218
    00219 METHODDEF(void)
    00220 init_source (j_decompress_ptr cinfo)
    00221 {
    00222         iread_ptr src = (iread_ptr) cinfo->src;
    00223         src->start_of_file = TRUE;
    00224 }
    00225
    00226
    00227 METHODDEF(boolean)
    00228 fill_input_buffer (j_decompress_ptr cinfo)
    00229 {
    00230         iread_ptr src = (iread_ptr) cinfo->src;
    00231         ILint nbytes;
    00232
    00233         nbytes = iread(src->buffer, 1, INPUT_BUF_SIZE);
    00234
    00235         if (nbytes <= 0) {
    00236                 if (src->start_of_file) {  // Treat empty input file as fatal error
    00237                         //ERREXIT(cinfo, JERR_INPUT_EMPTY);
    00238                         jpgErrorOccured = IL_TRUE;
    00239                 }
    00240                 //WARNMS(cinfo, JWRN_JPEG_EOF);
    00241                 // Insert a fake EOI marker
    00242                 src->buffer[0] = (JOCTET) 0xFF;
    00243                 src->buffer[1] = (JOCTET) JPEG_EOI;
    00244                 nbytes = 2;
    00245                 return IL_FALSE;
    00246         }
    00247         if (nbytes < INPUT_BUF_SIZE) {
    00248                 ilGetError();  // Gets rid of the IL_FILE_READ_ERROR.
    00249         }
    00250
    00251         src->pub.next_input_byte = src->buffer;
    00252         src->pub.bytes_in_buffer = nbytes;
    00253         src->start_of_file = IL_FALSE;
    00254
    00255         return IL_TRUE;
    00256 }
    00257
    00258
    00259 METHODDEF(void)
    00260 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
    00261 {
    00262         iread_ptr src = (iread_ptr) cinfo->src;
    00263
    00264         if (num_bytes > 0) {
    00265                 while (num_bytes > (long) src->pub.bytes_in_buffer) {
    00266                         num_bytes -= (long) src->pub.bytes_in_buffer;
    00267                         (void) fill_input_buffer(cinfo);
    00268                 }
    00269                 src->pub.next_input_byte += (size_t) num_bytes;
    00270                 src->pub.bytes_in_buffer -= (size_t) num_bytes;
    00271         }
    00272 }
    00273
    00274
    00275 METHODDEF(void)
    00276 term_source (j_decompress_ptr cinfo)
    00277 {
    00278         // no work necessary here
    00279 }
    00280
    00281
    00282 GLOBAL(void)
    00283 devil_jpeg_read_init (j_decompress_ptr cinfo)
    00284 {
    00285         iread_ptr src;
    00286
    00287         if ( cinfo->src == NULL ) {  // first time for this JPEG object?
    00288                 cinfo->src = (struct jpeg_source_mgr *)
    00289                                          (*cinfo->mem->alloc_small)( (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(iread_mgr) );
    00290                 src = (iread_ptr) cinfo->src;
    00291                 src->buffer = (JOCTET *)
    00292                                           (*cinfo->mem->alloc_small)( (j_common_ptr)cinfo, JPOOL_PERMANENT,
    00293                                                                                                   INPUT_BUF_SIZE * sizeof(JOCTET) );
    00294         }
    00295
    00296         src = (iread_ptr) cinfo->src;
    00297         src->pub.init_source = init_source;
    00298         src->pub.fill_input_buffer = fill_input_buffer;
    00299         src->pub.skip_input_data = skip_input_data;
    00300         src->pub.resync_to_restart = jpeg_resync_to_restart;  // use default method
    00301         src->pub.term_source = term_source;
    00302         src->pub.bytes_in_buffer = 0;  // forces fill_input_buffer on first read
    00303         src->pub.next_input_byte = NULL;  // until buffer loaded
    00304 }
    00305
    00306
    00307 jmp_buf JpegJumpBuffer;
    00308
    00309 static void iJpegErrorExit( j_common_ptr cinfo )
    00310 {
    00311         ilSetError( IL_LIB_JPEG_ERROR );
    00312         jpeg_destroy( cinfo );
    00313         longjmp( JpegJumpBuffer, 1 );
    00314 }
    00315
    00316 // Internal function used to load the jpeg.
    00317 ILboolean iLoadJpegInternal()
    00318 {
    00319         struct jpeg_error_mgr                   Error;
    00320         struct jpeg_decompress_struct   JpegInfo;
    00321         ILboolean                                               result;
    00322
    00323         if (iCurImage == NULL)
    00324         {
    00325                 ilSetError(IL_ILLEGAL_OPERATION);
    00326                 return IL_FALSE;
    00327         }
    00328
    00329         JpegInfo.err = jpeg_std_error( &Error );                // init standard error handlers
    00330         Error.error_exit = iJpegErrorExit;                              // add our exit handler
    00331         Error.output_message = OutputMsg;
    00332
    00333         if ((result = setjmp(JpegJumpBuffer) == 0) != IL_FALSE)
    00334         {
    00335                 jpeg_create_decompress( &JpegInfo );
    00336                 JpegInfo.do_block_smoothing = IL_TRUE;
    00337                 JpegInfo.do_fancy_upsampling = IL_TRUE;
    00338
    00339                 //jpeg_stdio_src(&JpegInfo, iGetFile());
    00340
    00341                 devil_jpeg_read_init( &JpegInfo );
    00342                 jpeg_read_header( &JpegInfo, IL_TRUE );
    00343
    00344                 result = ilLoadFromJpegStruct( &JpegInfo );
    00345
    00346                 jpeg_finish_decompress( &JpegInfo );
    00347                 jpeg_destroy_decompress( &JpegInfo );
    00348
    00349         }
    00350         else
    00351         {
    00352                 jpeg_destroy_decompress(&JpegInfo);
    00353         }
    00354
    00355         return result;
    00356
    00357 }
    00358
    00359
    00360
    00361 typedef struct
    00362 {
    00363         struct jpeg_destination_mgr             pub;
    00364         JOCTET                                                  *buffer;
    00365         ILboolean                                               bah;
    00366 } iwrite_mgr;
    00367
    00368 typedef iwrite_mgr *iwrite_ptr;
    00369
    00370 #define OUTPUT_BUF_SIZE 4096
    00371
    00372
    00373 METHODDEF(void)
    00374 init_destination(j_compress_ptr cinfo)
    00375 {
    00376         iwrite_ptr dest = (iwrite_ptr)cinfo->dest;
    00377         dest->buffer = (JOCTET *)
    00378           (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    00379                                   OUTPUT_BUF_SIZE * sizeof(JOCTET));
    00380
    00381         dest->pub.next_output_byte = dest->buffer;
    00382         dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
    00383         return;
    00384 }
    00385
    00386 METHODDEF(boolean)
    00387 empty_output_buffer (j_compress_ptr cinfo)
    00388 {
    00389         iwrite_ptr dest = (iwrite_ptr)cinfo->dest;
    00390         iwrite(dest->buffer, 1, OUTPUT_BUF_SIZE);
    00391         dest->pub.next_output_byte = dest->buffer;
    00392         dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
    00393         return IL_TRUE;
    00394 }
    00395
    00396 METHODDEF(void)
    00397 term_destination (j_compress_ptr cinfo)
    00398 {
    00399         iwrite_ptr dest = (iwrite_ptr)cinfo->dest;
    00400         iwrite(dest->buffer, 1, OUTPUT_BUF_SIZE - (ILuint)dest->pub.free_in_buffer);
    00401         return;
    00402 }
    00403
    00404
    00405 GLOBAL(void)
    00406 devil_jpeg_write_init(j_compress_ptr cinfo)
    00407 {
    00408         iwrite_ptr dest;
    00409
    00410         if (cinfo->dest == NULL) {      // first time for this JPEG object?
    00411                 cinfo->dest = (struct jpeg_destination_mgr *)
    00412                   (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
    00413                                           sizeof(iwrite_mgr));
    00414                 dest = (iwrite_ptr)cinfo->dest;
    00415         }
    00416
    00417         dest = (iwrite_ptr)cinfo->dest;
    00418         dest->pub.init_destination = init_destination;
    00419         dest->pub.empty_output_buffer = empty_output_buffer;
    00420         dest->pub.term_destination = term_destination;
    00421
    00422         return;
    00423 }
    00424
    00425
    00427 ILboolean ilSaveJpeg(const ILstring FileName)
    00428 {
    00429         ILHANDLE        JpegFile;
    00430         ILuint          JpegSize;
    00431
    00432         if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
    00433                 if (iFileExists(FileName)) {
    00434                         ilSetError(IL_FILE_ALREADY_EXISTS);
    00435                         return IL_FALSE;
    00436                 }
    00437         }
    00438
    00439         JpegFile = iopenw(FileName);
    00440         if (JpegFile == NULL) {
    00441                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00442                 return IL_FALSE;
    00443         }
    00444
    00445         JpegSize = ilSaveJpegF(JpegFile);
    00446         iclosew(JpegFile);
    00447
    00448         if (JpegSize == 0)
    00449                 return IL_FALSE;
    00450         return IL_TRUE;
    00451 }
    00452
    00453
    00455 ILuint ilSaveJpegF(ILHANDLE File)
    00456 {
    00457         ILuint Pos;
    00458         iSetOutputFile(File);
    00459         Pos = itellw();
    00460         if (iSaveJpegInternal() == IL_FALSE)
    00461                 return 0;  // Error occurred
    00462         return itellw() - Pos;  // Return the number of bytes written.
    00463 }
    00464
    00465
    00467 ILuint ilSaveJpegL(void *Lump, ILuint Size)
    00468 {
    00469         ILuint Pos = itellw();
    00470         iSetOutputLump(Lump, Size);
    00471         if (iSaveJpegInternal() == IL_FALSE)
    00472                 return 0;  // Error occurred
    00473         return itellw() - Pos;  // Return the number of bytes written.
    00474 }
    00475
    00476
    00477 // Internal function used to save the Jpeg.
    00478 ILboolean iSaveJpegInternal()
    00479 {
    00480         struct          jpeg_compress_struct JpegInfo;
    00481         struct          jpeg_error_mgr Error;
    00482         JSAMPROW        row_pointer[1];
    00483         ILimage         *TempImage;
    00484         ILubyte         *TempData;
    00485         ILenum          Type = 0;
    00486
    00487         if (iCurImage == NULL) {
    00488                 ilSetError(IL_ILLEGAL_OPERATION);
    00489                 return IL_FALSE;
    00490         }
    00491
    00492         /*if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION)
    00493                 Quality = 85;  // Not sure how low we should dare go...
    00494         else
    00495                 Quality = 99;*/
    00496
    00497         if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_LUMINANCE) || iCurImage->Bpc != 1) {
    00498                 TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
    00499                 if (TempImage == NULL) {
    00500                         return IL_FALSE;
    00501                 }
    00502         }
    00503         else {
    00504                 TempImage = iCurImage;
    00505         }
    00506
    00507         if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) {
    00508                 TempData = iGetFlipped(TempImage);
    00509                 if (TempData == NULL) {
    00510                         if (TempImage != iCurImage)
    00511                                 ilCloseImage(TempImage);
    00512                         return IL_FALSE;
    00513                 }
    00514         }
    00515         else {
    00516                 TempData = TempImage->Data;
    00517         }
    00518
    00519
    00520         JpegInfo.err = jpeg_std_error(&Error);
    00521         // Now we can initialize the JPEG compression object.
    00522         jpeg_create_compress(&JpegInfo);
    00523
    00524         //jpeg_stdio_dest(&JpegInfo, JpegFile);
    00525         devil_jpeg_write_init(&JpegInfo);
    00526
    00527         JpegInfo.image_width = TempImage->Width;  // image width and height, in pixels
    00528         JpegInfo.image_height = TempImage->Height;
    00529         JpegInfo.input_components = TempImage->Bpp;  // # of color components per pixel
    00530
    00531         // John Villar's addition
    00532         if (TempImage->Bpp == 1)
    00533                 JpegInfo.in_color_space = JCS_GRAYSCALE;
    00534         else
    00535                 JpegInfo.in_color_space = JCS_RGB;
    00536
    00537         jpeg_set_defaults(&JpegInfo);
    00538
    00539 /*#ifndef IL_USE_JPEGLIB_UNMODIFIED
    00540         Type = iGetInt(IL_JPG_SAVE_FORMAT);
    00541         if (Type == IL_EXIF) {
    00542                 JpegInfo.write_JFIF_header = FALSE;
    00543                 JpegInfo.write_EXIF_header = TRUE;
    00544         }
    00545         else if (Type == IL_JFIF) {
    00546                 JpegInfo.write_JFIF_header = TRUE;
    00547                 JpegInfo.write_EXIF_header = FALSE;
    00548         } //EXIF not present in libjpeg...
    00549 #else*/
    00550         Type = Type;
    00551         JpegInfo.write_JFIF_header = TRUE;
    00552 //#endif//IL_USE_JPEGLIB_UNMODIFIED
    00553
    00554         // Set the quality output
    00555         jpeg_set_quality(&JpegInfo, iGetInt(IL_JPG_QUALITY), IL_TRUE);
    00556         // Sets progressive saving here
    00557         if (ilGetBoolean(IL_JPG_PROGRESSIVE))
    00558                 jpeg_simple_progression(&JpegInfo);
    00559
    00560         jpeg_start_compress(&JpegInfo, IL_TRUE);
    00561
    00562         //row_stride = image_width * 3; // JSAMPLEs per row in image_buffer
    00563
    00564         while (JpegInfo.next_scanline < JpegInfo.image_height) {
    00565                 // jpeg_write_scanlines expects an array of pointers to scanlines.
    00566                 // Here the array is only one element long, but you could pass
    00567                 // more than one scanline at a time if that's more convenient.
    00568                 row_pointer[0] = &TempData[JpegInfo.next_scanline * TempImage->Bps];
    00569                 (void) jpeg_write_scanlines(&JpegInfo, row_pointer, 1);
    00570         }
    00571
    00572         // Step 6: Finish compression
    00573         jpeg_finish_compress(&JpegInfo);
    00574
    00575         // Step 7: release JPEG compression object
    00576
    00577         // This is an important step since it will release a good deal of memory.
    00578         jpeg_destroy_compress(&JpegInfo);
    00579
    00580         if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
    00581                 ifree(TempData);
    00582         if (TempImage != iCurImage)
    00583                 ilCloseImage(TempImage);
    00584
    00585         return IL_TRUE;
    00586 }
    00587
    00588
    00589
    00590 #else // Use the IJL instead of libjpeg.
    00591
    00592
    00593
    00595 ILboolean ilLoadJpeg(ILconst_string FileName)
    00596 {
    00597         if (!iFileExists(FileName)) {
    00598                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00599                 return IL_FALSE;
    00600         }
    00601         return iLoadJpegInternal(FileName, NULL, 0);
    00602 }
    00603
    00604
    00605 // Reads from a memory "lump" containing a jpeg
    00606 ILboolean ilLoadJpegL(void *Lump, ILuint Size)
    00607 {
    00608         return iLoadJpegInternal(NULL, Lump, Size);
    00609 }
    00610
    00611
    00612 // Internal function used to load the jpeg.
    00613 ILboolean iLoadJpegInternal(ILstring FileName, void *Lump, ILuint Size)
    00614 {
    00615     JPEG_CORE_PROPERTIES Image;
    00616
    00617         if (iCurImage == NULL) {
    00618                 ilSetError(IL_ILLEGAL_OPERATION);
    00619                 return IL_FALSE;
    00620         }
    00621
    00622         if (ijlInit(&Image) != IJL_OK) {
    00623                 ilSetError(IL_LIB_JPEG_ERROR);
    00624                 return IL_FALSE;
    00625         }
    00626
    00627         if (FileName != NULL) {
    00628                 Image.JPGFile = FileName;
    00629                 if (ijlRead(&Image, IJL_JFILE_READPARAMS) != IJL_OK) {
    00630                         ilSetError(IL_LIB_JPEG_ERROR);
    00631                         return IL_FALSE;
    00632                 }
    00633         }
    00634         else {
    00635                 Image.JPGBytes = Lump;
    00636                 Image.JPGSizeBytes = Size > 0 ? Size : UINT_MAX;
    00637                 if (ijlRead(&Image, IJL_JBUFF_READPARAMS) != IJL_OK) {
    00638                         ilSetError(IL_LIB_JPEG_ERROR);
    00639                         return IL_FALSE;
    00640                 }
    00641         }
    00642
    00643         switch (Image.JPGChannels)
    00644         {
    00645                 case 1:
    00646                         Image.JPGColor          = IJL_G;
    00647                         Image.DIBChannels       = 1;
    00648                         Image.DIBColor          = IJL_G;
    00649                         iCurImage->Format       = IL_LUMINANCE;
    00650                         break;
    00651
    00652                 case 3:
    00653                         Image.JPGColor          = IJL_YCBCR;
    00654                         Image.DIBChannels       = 3;
    00655                         Image.DIBColor          = IJL_RGB;
    00656                         iCurImage->Format       = IL_RGB;
    00657                         break;
    00658
    00659         case 4:
    00660                         Image.JPGColor          = IJL_YCBCRA_FPX;
    00661                         Image.DIBChannels       = 4;
    00662                         Image.DIBColor          = IJL_RGBA_FPX;
    00663                         iCurImage->Format       = IL_RGBA;
    00664                         break;
    00665
    00666         default:
    00667                         // This catches everything else, but no
    00668                         // color twist will be performed by the IJL.
    00669                         /*Image.DIBColor = (IJL_COLOR)IJL_OTHER;
    00670                         Image.JPGColor = (IJL_COLOR)IJL_OTHER;
    00671                         Image.DIBChannels = Image.JPGChannels;
    00672                         break;*/
    00673                         ijlFree(&Image);
    00674                         ilSetError(IL_LIB_JPEG_ERROR);
    00675                         return IL_FALSE;
    00676         }
    00677
    00678         if (!ilTexImage(Image.JPGWidth, Image.JPGHeight, 1, (ILubyte)Image.DIBChannels, iCurImage->Format, IL_UNSIGNED_BYTE, NULL)) {
    00679                 ijlFree(&Image);
    00680                 return IL_FALSE;
    00681         }
    00682         iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
    00683
    00684         Image.DIBWidth          = Image.JPGWidth;
    00685         Image.DIBHeight         = Image.JPGHeight;
    00686         Image.DIBPadBytes       = 0;
    00687         Image.DIBBytes          = iCurImage->Data;
    00688
    00689         if (FileName != NULL) {
    00690                 if (ijlRead(&Image, IJL_JFILE_READWHOLEIMAGE) != IJL_OK) {
    00691                         ijlFree(&Image);
    00692                         ilSetError(IL_LIB_JPEG_ERROR);
    00693                         return IL_FALSE;
    00694                 }
    00695         }
    00696         else {
    00697                 if (ijlRead(&Image, IJL_JBUFF_READWHOLEIMAGE) != IJL_OK) {
    00698                         ijlFree(&Image);
    00699                         ilSetError(IL_LIB_JPEG_ERROR);
    00700                         return IL_FALSE;
    00701                 }
    00702         }
    00703
    00704         ijlFree(&Image);
    00705         ilFixImage();
    00706
    00707         return IL_TRUE;
    00708 }
    00709
    00710
    00712 ILboolean ilSaveJpeg(ILconst_string FileName)
    00713 {
    00714         if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
    00715                 if (iFileExists(FileName)) {
    00716                         ilSetError(IL_FILE_ALREADY_EXISTS);
    00717                         return IL_FALSE;
    00718                 }
    00719         }
    00720
    00721         return iSaveJpegInternal(FileName, NULL, 0);
    00722 }
    00723
    00724
    00726 ILboolean ilSaveJpegL(void *Lump, ILuint Size)
    00727 {
    00728         return iSaveJpegInternal(NULL, Lump, Size);
    00729 }
    00730
    00731
    00732 // Internal function used to save the Jpeg.
    00733 ILboolean iSaveJpegInternal(ILstring FileName, void *Lump, ILuint Size)
    00734 {
    00735         JPEG_CORE_PROPERTIES    Image;
    00736         ILuint  Quality;
    00737         ILimage *TempImage;
    00738         ILubyte *TempData;
    00739
    00740         imemclear(&Image, sizeof(JPEG_CORE_PROPERTIES));
    00741
    00742         if (iCurImage == NULL) {
    00743                 ilSetError(IL_ILLEGAL_OPERATION);
    00744                 return IL_FALSE;
    00745         }
    00746         if (FileName == NULL && Lump == NULL) {
    00747                 ilSetError(IL_INVALID_PARAM);
    00748                 return IL_FALSE;
    00749         }
    00750
    00751         if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION)
    00752                 Quality = 85;  // Not sure how low we should dare go...
    00753         else
    00754                 Quality = 99;
    00755
    00756         if (ijlInit(&Image) != IJL_OK) {
    00757                 ilSetError(IL_LIB_JPEG_ERROR);
    00758                 return IL_FALSE;
    00759         }
    00760
    00761         if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_RGBA && iCurImage->Format != IL_LUMINANCE)
    00762                 || iCurImage->Bpc != 1) {
    00763                 if (iCurImage->Format == IL_BGRA)
    00764                         Temp = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE);
    00765                 else
    00766                         Temp = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
    00767                 if (Temp == NULL) {
    00768                         return IL_FALSE;
    00769                 }
    00770         }
    00771         else {
    00772                 Temp = iCurImage;
    00773         }
    00774
    00775         if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) {
    00776                 TempData = iGetFlipped(TempImage);
    00777                 if (TempData == NULL) {
    00778                         if (TempImage != iCurImage)
    00779                                 ilCloseImage(TempImage);
    00780                         return IL_FALSE;
    00781                 }
    00782         }
    00783         else {
    00784                 TempData = TempImage->Data;
    00785         }
    00786
    00787         // Setup DIB
    00788         Image.DIBWidth          = TempImage->Width;
    00789         Image.DIBHeight         = TempImage->Height;
    00790         Image.DIBChannels       = TempImage->Bpp;
    00791         Image.DIBBytes          = TempData;
    00792         Image.DIBPadBytes       = 0;
    00793
    00794         // Setup JPEG
    00795         Image.JPGWidth          = TempImage->Width;
    00796         Image.JPGHeight         = TempImage->Height;
    00797         Image.JPGChannels       = TempImage->Bpp;
    00798
    00799         switch (Temp->Bpp)
    00800         {
    00801                 case 1:
    00802                         Image.DIBColor                  = IJL_G;
    00803                         Image.JPGColor                  = IJL_G;
    00804                         Image.JPGSubsampling    = IJL_NONE;
    00805                         break;
    00806                 case 3:
    00807                         Image.DIBColor                  = IJL_RGB;
    00808                         Image.JPGColor                  = IJL_YCBCR;
    00809                         Image.JPGSubsampling    = IJL_411;
    00810                         break;
    00811                 case 4:
    00812                         Image.DIBColor                  = IJL_RGBA_FPX;
    00813                         Image.JPGColor                  = IJL_YCBCRA_FPX;
    00814                         Image.JPGSubsampling    = IJL_4114;
    00815                         break;
    00816         }
    00817
    00818         if (FileName != NULL) {
    00819                 Image.JPGFile = FileName;
    00820                 if (ijlWrite(&Image, IJL_JFILE_WRITEWHOLEIMAGE) != IJL_OK) {
    00821                         if (TempImage != iCurImage)
    00822                                 ilCloseImage(TempImage);
    00823                         ilSetError(IL_LIB_JPEG_ERROR);
    00824                         return IL_FALSE;
    00825                 }
    00826         }
    00827         else {
    00828                 Image.JPGBytes = Lump;
    00829                 Image.JPGSizeBytes = Size;
    00830                 if (ijlWrite(&Image, IJL_JBUFF_WRITEWHOLEIMAGE) != IJL_OK) {
    00831                         if (TempImage != iCurImage)
    00832                                 ilCloseImage(TempImage);
    00833                         ilSetError(IL_LIB_JPEG_ERROR);
    00834                         return IL_FALSE;
    00835                 }
    00836         }
    00837
    00838         ijlFree(&Image);
    00839
    00840         if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
    00841                 ifree(TempData);
    00842         if (Temp != iCurImage)
    00843                 ilCloseImage(Temp);
    00844
    00845         return IL_TRUE;
    00846 }
    00847
    00848 #endif//IL_USE_IJL
    00849
    00850
    00851 // Access point for applications wishing to use the jpeg library directly in
    00852 // conjunction with DevIL.
    00853 //
    00854 // The decompressor must be set up with an input source and all desired parameters
    00855 // this function is called. The caller must call jpeg_finish_decompress because
    00856 // the caller may still need decompressor after calling this for e.g. examining
    00857 // saved markers.
    00858 ILboolean ilLoadFromJpegStruct(void *_JpegInfo)
    00859 {
    00860 #ifndef IL_NO_JPG
    00861 #ifndef IL_USE_IJL
    00862         // sam. void (*errorHandler)(j_common_ptr);
    00863         ILubyte *TempPtr[1];
    00864         ILuint  Returned;
    00865         j_decompress_ptr JpegInfo = (j_decompress_ptr)_JpegInfo;
    00866
    00867         //added on 2003-08-31 as explained in sf bug 596793
    00868         jpgErrorOccured = IL_FALSE;
    00869
    00870         // sam. errorHandler = JpegInfo->err->error_exit;
    00871         // sam. JpegInfo->err->error_exit = ExitErrorHandle;
    00872         jpeg_start_decompress((j_decompress_ptr)JpegInfo);
    00873
    00874         if (!ilTexImage(JpegInfo->output_width, JpegInfo->output_height, 1, (ILubyte)JpegInfo->output_components, 0, IL_UNSIGNED_BYTE, NULL)) {
    00875                 return IL_FALSE;
    00876         }
    00877         iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
    00878
    00879         switch (iCurImage->Bpp)
    00880         {
    00881                 case 1:
    00882                         iCurImage->Format = IL_LUMINANCE;
    00883                         break;
    00884                 case 3:
    00885                         iCurImage->Format = IL_RGB;
    00886                         break;
    00887                 case 4:
    00888                         iCurImage->Format = IL_RGBA;
    00889                         break;
    00890                 default:
    00891                         //@TODO: Anyway to get here?  Need to error out or something...
    00892                         break;
    00893         }
    00894
    00895         TempPtr[0] = iCurImage->Data;
    00896         while (JpegInfo->output_scanline < JpegInfo->output_height) {
    00897                 Returned = jpeg_read_scanlines(JpegInfo, TempPtr, 1);  // anyway to make it read all at once?
    00898                 TempPtr[0] += iCurImage->Bps;
    00899                 if (Returned == 0)
    00900                         break;
    00901         }
    00902
    00903         // sam. JpegInfo->err->error_exit = errorHandler;
    00904
    00905         if (jpgErrorOccured)
    00906                 return IL_FALSE;
    00907
    00908         ilFixImage();
    00909         return IL_TRUE;
    00910 #endif
    00911 #endif
    00912         return IL_FALSE;
    00913 }
    00914
    00915
    00916
    00917 // Access point for applications wishing to use the jpeg library directly in
    00918 // conjunction with DevIL.
    00919 //
    00920 // The caller must set up the desired parameters by e.g. calling
    00921 // jpeg_set_defaults and overriding the parameters the caller wishes
    00922 // to change, such as quality, before calling this function. The caller
    00923 // is also responsible for calling jpeg_finish_compress in case the
    00924 // caller still needs to compressor for something.
    00925 //
    00926 ILboolean ilSaveFromJpegStruct(void *_JpegInfo)
    00927 {
    00928 #ifndef IL_NO_JPG
    00929 #ifndef IL_USE_IJL
    00930         void (*errorHandler)();
    00931         JSAMPROW        row_pointer[1];
    00932         ILimage         *TempImage;
    00933         ILubyte         *TempData;
    00934         j_compress_ptr JpegInfo = (j_compress_ptr)_JpegInfo;
    00935
    00936         if (iCurImage == NULL) {
    00937                 ilSetError(IL_ILLEGAL_OPERATION);
    00938                 return IL_FALSE;
    00939         }
    00940
    00941         //added on 2003-08-31 as explained in SF bug 596793
    00942         jpgErrorOccured = IL_FALSE;
    00943
    00944         errorHandler = JpegInfo->err->error_exit;
    00945         JpegInfo->err->error_exit = ExitErrorHandle;
    00946
    00947
    00948         if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_LUMINANCE) || iCurImage->Bpc != 1) {
    00949                 TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
    00950                 if (TempImage == NULL) {
    00951                         return IL_FALSE;
    00952                 }
    00953         }
    00954         else {
    00955                 TempImage = iCurImage;
    00956         }
    00957
    00958         if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) {
    00959                 TempData = iGetFlipped(TempImage);
    00960                 if (TempData == NULL) {
    00961                         if (TempImage != iCurImage)
    00962                                 ilCloseImage(TempImage);
    00963                         return IL_FALSE;
    00964                 }
    00965         }
    00966         else {
    00967                 TempData = TempImage->Data;
    00968         }
    00969
    00970         JpegInfo->image_width = TempImage->Width;  // image width and height, in pixels
    00971         JpegInfo->image_height = TempImage->Height;
    00972         JpegInfo->input_components = TempImage->Bpp;  // # of color components per pixel
    00973
    00974         jpeg_start_compress(JpegInfo, IL_TRUE);
    00975
    00976         //row_stride = image_width * 3; // JSAMPLEs per row in image_buffer
    00977
    00978         while (JpegInfo->next_scanline < JpegInfo->image_height) {
    00979                 // jpeg_write_scanlines expects an array of pointers to scanlines.
    00980                 // Here the array is only one element long, but you could pass
    00981                 // more than one scanline at a time if that's more convenient.
    00982                 row_pointer[0] = &TempData[JpegInfo->next_scanline * TempImage->Bps];
    00983                 (void) jpeg_write_scanlines(JpegInfo, row_pointer, 1);
    00984         }
    00985
    00986         if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
    00987                 ifree(TempData);
    00988         if (TempImage != iCurImage)
    00989                 ilCloseImage(TempImage);
    00990
    00991         return (!jpgErrorOccured);
    00992 #endif//IL_USE_IJL
    00993 #endif//IL_NO_JPG
    00994         return IL_FALSE;
    00995 }
    00996
    00997
    00998 #if defined(_MSC_VER)
    00999         #pragma warning(pop)
    01000         //#pragma warning(disable : 4756)  // Disables 'named type definition in parentheses' warning
    01001 #endif
    01002
    01003 #endif//IL_NO_JPG