- Main Page
- Data Structures
- Files

- File List

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

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2000-2009 by Denton Woods
    00005 // Last modified: 01/22/2009
    00006 //
    00007 // Filename: src-IL/src/il_pic.c
    00008 //
    00009 // Description: Softimage Pic (.pic) functions
    00010 //      Lots of this code is taken from Paul Bourke's Softimage Pic code at
    00011 //      http://local.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/
    00012 //
    00013 //-----------------------------------------------------------------------------
    00014
    00015 #include "il_internal.h"
    00016 #ifndef IL_NO_PIC
    00017 #include "il_pic.h"
    00018 #include "il_manip.h"
    00019 #include <string.h>
    00020
    00021
    00023 ILboolean ilIsValidPic(ILconst_string FileName)
    00024 {
    00025         ILHANDLE        PicFile;
    00026         ILboolean       bPic = IL_FALSE;
    00027
    00028         if (!iCheckExtension(FileName, IL_TEXT("pic"))) {
    00029                 ilSetError(IL_INVALID_EXTENSION);
    00030                 return bPic;
    00031         }
    00032
    00033         PicFile = iopenr(FileName);
    00034         if (PicFile == NULL) {
    00035                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00036                 return bPic;
    00037         }
    00038
    00039         bPic = ilIsValidPicF(PicFile);
    00040         icloser(PicFile);
    00041
    00042         return bPic;
    00043 }
    00044
    00045
    00047 ILboolean ilIsValidPicF(ILHANDLE File)
    00048 {
    00049         ILuint          FirstPos;
    00050         ILboolean       bRet;
    00051
    00052         iSetInputFile(File);
    00053         FirstPos = itell();
    00054         bRet = iIsValidPic();
    00055         iseek(FirstPos, IL_SEEK_SET);
    00056
    00057         return bRet;
    00058 }
    00059
    00060
    00062 ILboolean ilIsValidPicL(const void *Lump, ILuint Size)
    00063 {
    00064         iSetInputLump(Lump, Size);
    00065         return iIsValidPic();
    00066 }
    00067
    00068
    00069 // Internal function used to get the .pic header from the current file.
    00070 ILboolean iGetPicHead(PIC_HEAD *Header)
    00071 {
    00072         Header->Magic = GetBigInt();
    00073         Header->Version = GetBigFloat();
    00074         iread(Header->Comment, 1, 80);
    00075         iread(Header->Id, 1, 4);
    00076         Header->Width = GetBigShort();
    00077         Header->Height = GetBigShort();
    00078         Header->Ratio = GetBigFloat();
    00079         Header->Fields = GetBigShort();
    00080         Header->Padding = GetBigShort();
    00081
    00082         return IL_TRUE;
    00083 }
    00084
    00085
    00086 // Internal function to get the header and check it.
    00087 ILboolean iIsValidPic()
    00088 {
    00089         PIC_HEAD        Head;
    00090
    00091         if (!iGetPicHead(&Head))
    00092                 return IL_FALSE;
    00093         iseek(-(ILint)sizeof(PIC_HEAD), IL_SEEK_CUR);  // Go ahead and restore to previous state
    00094
    00095         return iCheckPic(&Head);
    00096 }
    00097
    00098
    00099 // Internal function used to check if the header is a valid .pic header.
    00100 ILboolean iCheckPic(PIC_HEAD *Header)
    00101 {
    00102         if (Header->Magic != 0x5380F634)
    00103                 return IL_FALSE;
    00104         if (strncmp((const char*)Header->Id, "PICT", 4))
    00105                 return IL_FALSE;
    00106         if (Header->Width == 0)
    00107                 return IL_FALSE;
    00108         if (Header->Height == 0)
    00109                 return IL_FALSE;
    00110
    00111         return IL_TRUE;
    00112 }
    00113
    00114
    00116 ILboolean ilLoadPic(ILconst_string FileName)
    00117 {
    00118         ILHANDLE        PicFile;
    00119         ILboolean       bPic = IL_FALSE;
    00120
    00121         PicFile = iopenr(FileName);
    00122         if (PicFile == NULL) {
    00123                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00124                 return bPic;
    00125         }
    00126
    00127         bPic = ilLoadPicF(PicFile);
    00128         icloser(PicFile);
    00129
    00130         return bPic;
    00131 }
    00132
    00133
    00135 ILboolean ilLoadPicF(ILHANDLE File)
    00136 {
    00137         ILuint          FirstPos;
    00138         ILboolean       bRet;
    00139
    00140         iSetInputFile(File);
    00141         FirstPos = itell();
    00142         bRet = iLoadPicInternal();
    00143         iseek(FirstPos, IL_SEEK_SET);
    00144
    00145         return bRet;
    00146 }
    00147
    00148
    00150 ILboolean ilLoadPicL(const void *Lump, ILuint Size)
    00151 {
    00152         iSetInputLump(Lump, Size);
    00153         return iLoadPicInternal();
    00154 }
    00155
    00156
    00157 // Internal function used to load the .pic
    00158 ILboolean iLoadPicInternal()
    00159 {
    00160         ILuint          Alpha = IL_FALSE;
    00161         ILubyte         Chained;
    00162         CHANNEL         *Channel = NULL, *Channels = NULL, *Prev;
    00163         PIC_HEAD        Header;
    00164         ILboolean       Read;
    00165
    00166         if (iCurImage == NULL) {
    00167                 ilSetError(IL_ILLEGAL_OPERATION);
    00168                 return IL_FALSE;
    00169         }
    00170
    00171         if (!iGetPicHead(&Header))
    00172                 return IL_FALSE;
    00173         if (!iCheckPic(&Header)) {
    00174                 ilSetError(IL_INVALID_FILE_HEADER);
    00175                 return IL_FALSE;
    00176         }
    00177
    00178         // Read channels
    00179         do {
    00180                 if (Channel == NULL) {
    00181                         Channel = Channels = (CHANNEL*)ialloc(sizeof(CHANNEL));
    00182                         if (Channels == NULL)
    00183                                 return IL_FALSE;
    00184                 }
    00185                 else {
    00186                         Channels->Next = (CHANNEL*)ialloc(sizeof(CHANNEL));
    00187                         if (Channels->Next == NULL) {
    00188                                 // Clean up the list before erroring out.
    00189                                 while (Channel) {
    00190                                         Prev = Channel;
    00191                                         Channel = (CHANNEL*)Channel->Next;
    00192                                         ifree(Prev);
    00193                                 }
    00194                                 return IL_FALSE;
    00195                         }
    00196                         Channels = (CHANNEL*)Channels->Next;
    00197                 }
    00198                 Channels->Next = NULL;
    00199
    00200                 Chained = igetc();
    00201                 Channels->Size = igetc();
    00202                 Channels->Type = igetc();
    00203                 Channels->Chan = igetc();
    00204                 if (ieof()) {
    00205                         Read = IL_FALSE;
    00206                         goto finish;
    00207                 }
    00208
    00209                 // See if we have an alpha channel in there
    00210                 if (Channels->Chan & PIC_ALPHA_CHANNEL)
    00211                         Alpha = IL_TRUE;
    00212
    00213         } while (Chained);
    00214
    00215         if (Alpha) {  // Has an alpha channel
    00216                 if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
    00217                         Read = IL_FALSE;
    00218                         goto finish;  // Have to destroy Channels first.
    00219                 }
    00220         }
    00221         else {  // No alpha channel
    00222                 if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
    00223                         Read = IL_FALSE;
    00224                         goto finish;  // Have to destroy Channels first.
    00225                 }
    00226         }
    00227         iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
    00228
    00229         Read = readScanlines((ILuint*)iCurImage->Data, Header.Width, Header.Height, Channel, Alpha);
    00230
    00231 finish:
    00232         // Destroy channels
    00233         while (Channel) {
    00234                 Prev = Channel;
    00235                 Channel = (CHANNEL*)Channel->Next;
    00236                 ifree(Prev);
    00237         }
    00238
    00239         if (Read == IL_FALSE)
    00240                 return IL_FALSE;
    00241
    00242         ilFixImage();
    00243
    00244         return IL_TRUE;
    00245 }
    00246
    00247
    00248 ILboolean readScanlines(ILuint *image, ILint width, ILint height, CHANNEL *channel, ILuint alpha)
    00249 {
    00250         ILint   i;
    00251         ILuint  *scan;
    00252
    00253         (void)alpha;
    00254
    00255         for (i = height - 1; i >= 0; i--) {
    00256                 scan = image + i * width;
    00257
    00258                 if (!readScanline((ILubyte *)scan, width, channel, alpha ? 4 : 3)) {
    00259                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00260                         return IL_FALSE;
    00261                 }
    00262         }
    00263
    00264         return IL_TRUE;
    00265 }
    00266
    00267
    00268 ILuint readScanline(ILubyte *scan, ILint width, CHANNEL *channel, ILint bytes)
    00269 {
    00270         ILint           noCol;
    00271         ILint           off[4];
    00272         ILuint          status=0;
    00273
    00274         while (channel) {
    00275                 noCol = 0;
    00276                 if(channel->Chan & PIC_RED_CHANNEL) {
    00277                         off[noCol] = 0;
    00278                         noCol++;
    00279                 }
    00280                 if(channel->Chan & PIC_GREEN_CHANNEL) {
    00281                         off[noCol] = 1;
    00282                         noCol++;
    00283                 }
    00284                 if(channel->Chan & PIC_BLUE_CHANNEL) {
    00285                         off[noCol] = 2;
    00286                         noCol++;
    00287                 }
    00288                 if(channel->Chan & PIC_ALPHA_CHANNEL) {
    00289                         off[noCol] = 3;
    00290                         noCol++;
    00291                         //@TODO: Find out if this is possible.
    00292                         if (bytes == 3)  // Alpha channel in a 24-bit image.  Do not know what to do with this.
    00293                                 return 0;
    00294                 }
    00295
    00296                 switch(channel->Type & 0x0F)
    00297                 {
    00298                         case PIC_UNCOMPRESSED:
    00299                                 status = channelReadRaw(scan, width, noCol, off, bytes);
    00300                                 break;
    00301                         case PIC_PURE_RUN_LENGTH:
    00302                                 status = channelReadPure(scan, width, noCol, off, bytes);
    00303                                 break;
    00304                         case PIC_MIXED_RUN_LENGTH:
    00305                                 status = channelReadMixed(scan, width, noCol, off, bytes);
    00306                                 break;
    00307                 }
    00308                 if (!status)
    00309                         break;
    00310
    00311                 channel = (CHANNEL*)channel->Next;
    00312         }
    00313         return status;
    00314 }
    00315
    00316
    00317 ILboolean channelReadRaw(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes)
    00318 {
    00319         ILint i, j;
    00320
    00321         for (i = 0; i < width; i++) {
    00322                 if (ieof())
    00323                         return IL_FALSE;
    00324                 for (j = 0; j < noCol; j++)
    00325                         if (iread(&scan[off[j]], 1, 1) != 1)
    00326                                 return IL_FALSE;
    00327                 scan += bytes;
    00328         }
    00329         return IL_TRUE;
    00330 }
    00331
    00332
    00333 ILboolean channelReadPure(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes)
    00334 {
    00335         ILubyte         col[4];
    00336         ILint           count;
    00337         int                     i, j, k;
    00338
    00339         for (i = width; i > 0; ) {
    00340                 count = igetc();
    00341                 if (count == IL_EOF)
    00342                         return IL_FALSE;
    00343                 if (count > width)
    00344                         count = width;
    00345                 i -= count;
    00346
    00347                 if (ieof())
    00348                         return IL_FALSE;
    00349
    00350                 for (j = 0; j < noCol; j++)
    00351                         if (iread(&col[j], 1, 1) != 1)
    00352                                 return IL_FALSE;
    00353
    00354                 for (k = 0; k < count; k++, scan += bytes) {
    00355                         for(j = 0; j < noCol; j++)
    00356                                 scan[off[j] + k] = col[j];
    00357                 }
    00358         }
    00359         return IL_TRUE;
    00360 }
    00361
    00362
    00363 ILboolean channelReadMixed(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes)
    00364 {
    00365         ILint   count;
    00366         int             i, j, k;
    00367         ILubyte col[4];
    00368
    00369         for(i = 0; i < width; i += count) {
    00370                 if (ieof())
    00371                         return IL_FALSE;
    00372
    00373                 count = igetc();
    00374                 if (count == IL_EOF)
    00375                         return IL_FALSE;
    00376
    00377                 if (count >= 128) {  // Repeated sequence
    00378                         if (count == 128) {  // Long run
    00379                                 count = GetBigUShort();
    00380                                 if (ieof()) {
    00381                                         ilSetError(IL_FILE_READ_ERROR);
    00382                                         return IL_FALSE;
    00383                                 }
    00384                         }
    00385                         else
    00386                                 count -= 127;
    00387
    00388                         // We've run past...
    00389                         if ((i + count) > width) {
    00390                                 //fprintf(stderr, "ERROR: FF_PIC_load(): Overrun scanline (Repeat) [%d + %d > %d] (NC=%d)\n", i, count, width, noCol);
    00391                                 ilSetError(IL_ILLEGAL_FILE_VALUE);
    00392                                 return IL_FALSE;
    00393                         }
    00394
    00395                         for (j = 0; j < noCol; j++)
    00396                                 if (iread(&col[j], 1, 1) != 1) {
    00397                                         ilSetError(IL_FILE_READ_ERROR);
    00398                                         return IL_FALSE;
    00399                                 }
    00400
    00401                         for (k = 0; k < count; k++, scan += bytes) {
    00402                                 for (j = 0; j < noCol; j++)
    00403                                         scan[off[j]] = col[j];
    00404                         }
    00405                 } else {                                // Raw sequence
    00406                         count++;
    00407                         if ((i + count) > width) {
    00408                                 //fprintf(stderr, "ERROR: FF_PIC_load(): Overrun scanline (Raw) [%d + %d > %d] (NC=%d)\n", i, count, width, noCol);
    00409                                 ilSetError(IL_ILLEGAL_FILE_VALUE);
    00410                                 return IL_FALSE;
    00411                         }
    00412
    00413                         for (k = count; k > 0; k--, scan += bytes) {
    00414                                 for (j = 0; j < noCol; j++)
    00415                                         if (iread(&scan[off[j]], 1, 1) != 1) {
    00416                                                 ilSetError(IL_FILE_READ_ERROR);
    00417                                                 return IL_FALSE;
    00418                                         }
    00419                         }
    00420                 }
    00421         }
    00422
    00423         return IL_TRUE;
    00424 }
    00425
    00426
    00427 #endif//IL_NO_PIC
    00428