EGIFLIB.C

Go to the documentation of this file.
00001 /* --
00002 OpenFX version 2.0 - Modelling, Animation and Rendering Package
00003 Copyright (C) 2000 - 2007 OpenFX Development Team
00004 -- */
00005 
00006 /*    file   EGIFLIB.C    */
00007 
00008 #pragma warning( disable : 4244)
00009 
00010 #include "render.h"
00011 #undef OK
00012 #include "giflib.h"
00013 #include "gifhash.h"
00014 
00015 
00016 #define COMMENT_EXT_FUNC_CODE  'C'
00017 #define GIF_STAMP87     "GIF87a"   /* First chars in file - GIF stamp */
00018 #define GIF_STAMP89     "GIF89a"   /* First chars in file - GIF stamp */
00019 #define ZL_MAX_CODE 4095           /* Biggest code possible in 12 bits. */
00020 
00021 #define FILE_STATE_WRITE  0x01/* 1 write, 0 read - DGIF_LIB compatible */
00022 #define FILE_STATE_SCREEN 0x02
00023 #define FILE_STATE_IMAGE  0x04
00024 
00025 #define FLUSH_OUTPUT      4096 /* Impossible code, to signal flush */
00026 #define FIRST_CODE        4097  /* Impossible code, to signal first */
00027 
00028 #define IS_WRITEABLE(Private) (Private -> FileState & FILE_STATE_WRITE)
00029 
00037 typedef struct GifFilePrivateType {
00038   long FileState,
00039   FileHandle,   /* Where old this data goes to! */
00040   BitsPerPixel, /* Bits per pixel (Codes uses at list this + 1) */
00041   ClearCode,    /* The CLEAR LZ code */
00042   EOFCode,      /* The EOF LZ code */
00043   RunningCode,  /* The next code algorithm can generate */
00044   RunningBits,  /* The number of bits required to represent RunningCode */
00045   MaxCode1,     /* 1 bigger than maximum possible code, in RunningBits bits */
00046   CrntCode,                     /* Current algorithm code */
00047   CrntShiftState;               /* Number of bits in CrntShiftDWord */
00048   unsigned long CrntShiftDWord, /* For bytes decomposition into codes */
00049            PixelCount;
00050   FILE *File;              /* File as stream */
00051   ByteType Buf[256];       /* Compressed output is buffered here */
00052   GifHashTableType *HashTable;
00053 } GifFilePrivateType;
00054 
00055 long _GifError;
00056 
00057 /* Masks given codes to BitsPerPixel, to make sure all codes are in range: */
00058 static PixelType CodeMask[] = {
00059     0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
00060 };
00061 
00062 #ifdef _SUNSTYLE
00063 static long EGifPutWord();
00064 static long EGifSetupCompress();
00065 static long EGifCompressLine();
00066 static long EGifCompressOutput();
00067 static long EGifBufferedOutput();
00068 #else
00069 static long EGifPutWord(long Word, FILE *File);
00070 static long EGifSetupCompress(GifFileType *GifFile);
00071 static long EGifCompressLine(GifFileType *GifFile, PixelType *Line, long LineLen);
00072 static long EGifCompressOutput(GifFilePrivateType *Private, long Code);
00073 static long EGifBufferedOutput(FILE *File, ByteType *Buf, long c);
00074 #endif
00075 
00076 #ifdef _SUNSTYLE
00077 GifFileType *EGifOpenFileName(FileName,TestExistance)
00078 char *FileName; long TestExistance;{
00079 #else
00080 GifFileType *EGifOpenFileName(char *FileName, long TestExistance, long version){
00081 #endif
00082     long FileHandle;
00083     FileHandle=1;
00084     return EGifOpenFileHandle(FileName,version);
00085 }
00086 
00087 #ifdef _SUNSTYLE
00088 GifFileType *EGifOpenFileHandle(filename, version) char *filename; long version;{
00089 #else
00090 GifFileType *EGifOpenFileHandle(char *filename, long version){
00091 #endif
00092     char *vers;
00093     long FileHandle;
00094     GifFileType *GifFile;
00095     GifFilePrivateType *Private;
00096     FILE *f;
00097     FileHandle=0;
00098     if((f = fopen((char *)strlwr(filename), "wb")) == NULL)return NULL;
00099     if ((GifFile = (GifFileType *) X__Malloc(sizeof(GifFileType))) == NULL) {
00100        _GifError = E_GIF_ERR_NotEnoughMem;
00101        return ERROR;
00102     }
00103     GifFile -> SWidth = GifFile -> SHeight =
00104     GifFile -> SColorResolution = GifFile -> SBitsPerPixel =
00105     GifFile -> SBackGroundColor =
00106     GifFile -> ILeft = GifFile -> ITop = GifFile -> IWidth = GifFile -> IHeight =
00107     GifFile -> IInterlace =
00108     GifFile -> IBitsPerPixel = 0;
00109     GifFile -> SColorMap = GifFile -> IColorMap = NULL;
00110     if(version)vers=GIF_STAMP89;
00111     else       vers=GIF_STAMP87;
00112     if(fwrite(vers,1,strlen(vers),f) != strlen(vers)) {
00113       _GifError = E_GIF_ERR_WriteFailed;
00114       X__Free((char *) GifFile);
00115       return NULL;
00116     }
00117     if ((Private = (GifFilePrivateType *) X__Malloc(sizeof(GifFilePrivateType)))
00118        == NULL) {
00119        _GifError = E_GIF_ERR_NotEnoughMem;
00120        return NULL;
00121     }
00122     GifFile -> Private = (VoidPtr)Private;
00123     Private -> FileHandle = FileHandle;
00124     Private -> File = f;
00125     Private -> FileState = FILE_STATE_WRITE;
00126     if ((Private -> HashTable = _InitHashTable()) == NULL) {
00127       _GifError = E_GIF_ERR_NotEnoughMem;
00128       return NULL;
00129     }
00130     _GifError = 0;
00131     return GifFile;
00132 }
00133 
00134 #ifdef _SUNSTYLE
00135 long EGifPutScreenDesc(GifFile,Width,Height,ColorRes,BackGround,BitsPerPixel,
00136        ColorMap) GifFileType *GifFile; long Width;
00137        long Height; long ColorRes; long BackGround; long BitsPerPixel;
00138        GifColorType *ColorMap; {
00139 #else
00140 long EGifPutScreenDesc(GifFileType *GifFile,
00141  long Width, long Height, long ColorRes, long BackGround,
00142  long BitsPerPixel, GifColorType *ColorMap){
00143 #endif
00144     long i, Size;
00145     ByteType Buf[3];
00146     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
00147 
00148     if (Private -> FileState & FILE_STATE_SCREEN) {
00149        /* If already has screen descriptor - something is wrong! */
00150        _GifError = E_GIF_ERR_HasScrnDscr;
00151        return ERROR;
00152     }
00153     if (!IS_WRITEABLE(Private)) {
00154       /* This file was NOT open for writing: */
00155       _GifError = E_GIF_ERR_NotWriteable;
00156       return ERROR;
00157     }
00158 
00159     GifFile -> SWidth = Width;
00160     GifFile -> SHeight = Height;
00161     GifFile -> SColorResolution = ColorRes;
00162     GifFile -> SBitsPerPixel = BitsPerPixel;
00163     GifFile -> SBackGroundColor = BackGround;
00164     if (ColorMap) {
00165       Size = sizeof(GifColorType) * (1 << BitsPerPixel);
00166       if((GifFile -> SColorMap = (GifColorType *) X__Malloc(Size)) == NULL){
00167         return ERROR;
00168       }
00169       memcpy(GifFile -> SColorMap, ColorMap, Size);
00170     }
00171     /* Put the screen descriptor into the file: */
00172     EGifPutWord(Width, Private -> File);
00173     EGifPutWord(Height, Private -> File);
00174     Buf[0] = (ColorMap ? 0x80 : 0x00) |
00175              ((ColorRes - 1) << 4) |
00176              (BitsPerPixel - 1);
00177     Buf[1] = BackGround;
00178     Buf[2] = 0;
00179 #ifndef DEBUG_NO_PREFIX
00180     fwrite(Buf, 1, 3, Private -> File);
00181 #endif /* DEBUG_NO_PREFIX */
00182     /* If we have Global color map - dump it also: */
00183 #ifndef DEBUG_NO_PREFIX
00184     if (ColorMap != NULL)for (i=0; i<(1 << BitsPerPixel); i++) {
00185        /* Put the ColorMap out also: */
00186       Buf[0] = ColorMap[i].Red;
00187       Buf[1] = ColorMap[i].Green;
00188       Buf[2] = ColorMap[i].Blue;
00189       if (fwrite(Buf, 1, 3, Private -> File) != 3) {
00190         _GifError = E_GIF_ERR_WriteFailed;
00191         return ERROR;
00192       }
00193     }
00194 #endif /* DEBUG_NO_PREFIX */
00195 
00196     /* Mark this file as has screen descriptor, and no pixel written yet: */
00197     Private -> FileState |= FILE_STATE_SCREEN;
00198     return OK;
00199 }
00200 
00201 #ifdef _SUNSTYLE
00202 long EGifPutImageDesc(GifFile,Left,Top,Width,Height,Interlace,BitsPerPixel,
00203                       ColorMap)
00204 GifFileType *GifFile; long Left; long Top; long Width; long Height;
00205 long Interlace; long BitsPerPixel; GifColorType *ColorMap; {
00206 #else
00207 long EGifPutImageDesc(GifFileType *GifFile,
00208      long Left, long Top, long Width, long Height, long Interlace,
00209      long BitsPerPixel, GifColorType *ColorMap){
00210 #endif
00211     long i, Size;
00212     ByteType Buf[3];
00213     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
00214 
00215     if (Private -> FileState & FILE_STATE_IMAGE &&
00216         Private -> PixelCount > 0) {
00217       /* If already has active image descriptor - something is wrong! */
00218       _GifError = E_GIF_ERR_HasImagDscr;
00219       return ERROR;
00220     }
00221     if (!IS_WRITEABLE(Private)) {
00222       /* This file was NOT open for writing: */
00223       _GifError = E_GIF_ERR_NotWriteable;
00224       return ERROR;
00225     }
00226     GifFile -> ILeft = Left;
00227     GifFile -> ITop = Top;
00228     GifFile -> IWidth = Width;
00229     GifFile -> IHeight = Height;
00230     GifFile -> IBitsPerPixel = BitsPerPixel;
00231     GifFile -> IInterlace = Interlace;
00232     if (ColorMap) {
00233       Size = sizeof(GifColorType) * (1 << BitsPerPixel);
00234       if (GifFile -> IColorMap){
00235         X__Free((char *) GifFile -> IColorMap);
00236       }
00237       if((GifFile -> IColorMap = (GifColorType *) X__Malloc(Size)) == NULL){
00238         return ERROR;
00239       }
00240       memcpy(GifFile -> IColorMap, ColorMap, Size);
00241     }
00242     /* Put the image descriptor into the file: */
00243     Buf[0] = ',';               /* Image seperator character */
00244 #ifndef DEBUG_NO_PREFIX
00245     fwrite(Buf, 1, 1, Private -> File);
00246 #endif /* DEBUG_NO_PREFIX */
00247     EGifPutWord(Left, Private -> File);
00248     EGifPutWord(Top, Private -> File);
00249     EGifPutWord(Width, Private -> File);
00250     EGifPutWord(Height, Private -> File);
00251     Buf[0] = (ColorMap ? 0x80 : 0x00) |
00252              (Interlace ? 0x40 : 0x00) |
00253              (BitsPerPixel - 1);
00254 #ifndef DEBUG_NO_PREFIX
00255     fwrite(Buf, 1, 1, Private -> File);
00256 #endif /* DEBUG_NO_PREFIX */
00257     /* If we have Global color map - dump it also: */
00258 #ifndef DEBUG_NO_PREFIX
00259     if (ColorMap != NULL)for (i=0; i<(1 << BitsPerPixel); i++) {
00260       /* Put the ColorMap out also: */
00261       Buf[0] = ColorMap[i].Red;
00262       Buf[1] = ColorMap[i].Green;
00263       Buf[2] = ColorMap[i].Blue;
00264       if (fwrite(Buf, 1, 3, Private -> File) != 3) {
00265         _GifError = E_GIF_ERR_WriteFailed;
00266         return ERROR;
00267       }
00268     }
00269 #endif /* DEBUG_NO_PREFIX */
00270     if (GifFile -> SColorMap == NULL && GifFile -> IColorMap == NULL){
00271       _GifError = E_GIF_ERR_NoColorMap;
00272       return ERROR;
00273     }
00274     /* Mark this file as has screen descriptor: */
00275     Private -> FileState |= FILE_STATE_IMAGE;
00276     Private -> PixelCount = (long) Width * (long) Height;
00277     EGifSetupCompress(GifFile);       /* Reset compress algorithm parameters */
00278     return OK;
00279 }
00280 
00281 long EGifPutControlDesc(GifFileType *GifFile,
00282     long transp, ByteType transpid, long delay, long dummy){
00283     ByteType Buf[3];
00284     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile -> Private;
00285     if (!IS_WRITEABLE(Private)) {
00286       /* This file was NOT open for writing: */
00287       _GifError = E_GIF_ERR_NotWriteable;
00288       return ERROR;
00289     }
00290     Buf[0] = 0x21;               /* Extension introducer */
00291     fwrite(Buf, 1, 1, Private -> File);
00292     Buf[0] = 0xF9;               /* Control label */
00293     fwrite(Buf, 1, 1, Private -> File);
00294     Buf[0] = 4;
00295     fwrite(Buf, 1, 1, Private -> File);
00296     Buf[0] = (transp ? 0x01 : 0x00) |
00297              (dummy  ? 0x02 : 0x00);
00298     fwrite(Buf, 1, 1, Private -> File);
00299     EGifPutWord(delay, Private -> File);
00300     Buf[0]=(ByteType)transpid;
00301     fwrite(Buf, 1, 1, Private -> File);
00302     Buf[0]=0;
00303     fwrite(Buf, 1, 1, Private -> File); /* Block Terminator */
00304     return OK;
00305 }
00306 
00307 long EGifPutBrowserControlDesc(GifFileType *GifFile,long repeat){
00308     ByteType Buf[16];
00309     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile -> Private;
00310     if (!IS_WRITEABLE(Private)) {
00311       /* This file was NOT open for writing: */
00312       _GifError = E_GIF_ERR_NotWriteable;
00313       return ERROR;
00314     }
00315     Buf[0] = 0x21;               /* Extension introducer */
00316     fwrite(Buf, 1, 1, Private -> File);
00317     Buf[0] = 0xFF;               /* Control label */
00318     fwrite(Buf, 1, 1, Private -> File);
00319     Buf[0] = 11;
00320     fwrite(Buf, 1, 1, Private -> File);
00321     strcpy((char *)Buf,"NETSCAPE2.0");
00322     fwrite(Buf, 1, 11, Private -> File);
00323     Buf[0] = 0x03;
00324     fwrite(Buf, 1, 1, Private -> File);
00325     Buf[0] = 0x01;
00326     fwrite(Buf, 1, 1, Private -> File);
00327     EGifPutWord(repeat, Private -> File);
00328     Buf[0]=0;
00329     fwrite(Buf, 1, 1, Private -> File); /* Block Terminator */
00330     return OK;
00331 }
00332 
00333 #ifdef _SUNSTYLE
00334 long EGifPutLine(GifFile,Line,LineLen) GifFileType *GifFile;
00335 PixelType *Line; long LineLen; {
00336 #else
00337 long EGifPutLine(GifFileType *GifFile, PixelType *Line, long LineLen){
00338 #endif
00339     long i;
00340     PixelType Mask;
00341     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
00342     if (!IS_WRITEABLE(Private)) {
00343       /* This file was NOT open for writing: */
00344       _GifError = E_GIF_ERR_NotWriteable;
00345       return ERROR;
00346     }
00347     if (!LineLen) LineLen = GifFile -> IWidth;
00348     /* (long) added by RSF to satisfy the WATCOM compiler */
00349     if ((long)(Private -> PixelCount -= LineLen) < 0) {
00350        _GifError = E_GIF_ERR_DataTooBig;
00351        return ERROR;
00352     }
00353     /* Make sure the codes are not out of bit range, as we might generate    */
00354     /* wrong code (because of overflow when we combine them) in this case:   */
00355     Mask = CodeMask[Private -> BitsPerPixel];
00356     for (i=0; i<LineLen; i++) Line[i] &= Mask;
00357     return EGifCompressLine(GifFile, Line, LineLen);
00358 }
00359 
00360 #ifdef _SUNSTYLE
00361 long EGifPutCode(GifFile,CodeSize,CodeBlock) GifFileType *GifFile;
00362      long CodeSize; ByteType *CodeBlock; {
00363 #else
00364 long EGifPutCode(GifFileType *GifFile, long CodeSize, ByteType *CodeBlock){
00365 #endif
00366     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
00367     if (!IS_WRITEABLE(Private)) {
00368       /* This file was NOT open for writing: */
00369       _GifError = E_GIF_ERR_NotWriteable;
00370       return ERROR;
00371     }
00372     /* No need to dump code size as Compression set up does any for us: */
00373     /*
00374     Buf = CodeSize;
00375     if (fwrite(&Buf, 1, 1, Private -> File) != 1) {
00376       _GifError = E_GIF_ERR_WriteFailed;
00377       return ERROR;
00378     }
00379     */
00380     return EGifPutCodeNext(GifFile, CodeBlock);
00381 }
00382 
00383 #ifdef _SUNSTYLE
00384 long EGifPutCodeNext(GifFile,CodeBlock) GifFileType *GifFile;
00385 ByteType *CodeBlock; {
00386 #else
00387 long EGifPutCodeNext(GifFileType *GifFile, ByteType *CodeBlock){
00388 #endif
00389     ByteType Buf;
00390     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
00391     if (CodeBlock != NULL) {
00392       if (fwrite(CodeBlock, 1, CodeBlock[0] + 1, Private -> File)
00393           != CodeBlock[0] + 1) {
00394         _GifError = E_GIF_ERR_WriteFailed;
00395         return ERROR;
00396       }
00397     }
00398     else {
00399       Buf = 0;
00400       if (fwrite(&Buf, 1, 1, Private -> File) != 1) {
00401         _GifError = E_GIF_ERR_WriteFailed;
00402         return ERROR;
00403       }
00404       Private -> PixelCount = 0;    /* And local info. indicate image read */
00405     }
00406     return OK;
00407 }
00408 
00409 #ifdef _SUNSTYLE
00410 long EGifCloseFile(GifFile) GifFileType *GifFile; {
00411 #else
00412 long EGifCloseFile(GifFileType *GifFile){
00413 #endif
00414     ByteType Buf;
00415     GifFilePrivateType *Private;
00416     FILE *File;
00417 
00418     if (GifFile == NULL) return ERROR;
00419 
00420     Private = (GifFilePrivateType *) GifFile -> Private;
00421     if (!IS_WRITEABLE(Private)) {
00422       /* This file was NOT open for writing: */
00423       _GifError = E_GIF_ERR_NotWriteable;
00424       return ERROR;
00425     }
00426     File = Private -> File;
00427     Buf = ';';
00428     fwrite(&Buf, 1, 1, Private -> File);
00429     if (GifFile -> IColorMap){
00430      X__Free((char *) GifFile -> IColorMap);
00431     }
00432     if (GifFile -> SColorMap){
00433       X__Free((char *) GifFile -> SColorMap);
00434     }
00435     if (Private) {
00436       if (Private -> HashTable){
00437         X__Free((char *) Private -> HashTable);
00438       }
00439       X__Free((char *) Private);
00440     }
00441     X__Free(GifFile);
00442     if (fclose(File) != 0) {
00443        _GifError = E_GIF_ERR_CloseFailed;
00444        return ERROR;
00445     }
00446     return OK;
00447 }
00448 
00449 #ifdef _SUNSTYLE
00450 static long EGifPutWord(Word,File) long Word; FILE *File; {
00451 #else
00452 static long EGifPutWord(long Word, FILE *File){
00453 #endif
00454     char c[2];
00455     c[0] = Word & 0xff;
00456     c[1] = (Word >> 8) & 0xff;
00457 #ifndef DEBUG_NO_PREFIX
00458     if (fwrite(c, 1, 2, File) == 2)return OK;
00459     else return ERROR;
00460 #else
00461     return OK;
00462 #endif /* DEBUG_NO_PREFIX */
00463 }
00464 
00465 #ifdef _SUNSTYLE
00466 static long EGifSetupCompress(GifFile) GifFileType *GifFile; {
00467 #else
00468 static long EGifSetupCompress(GifFileType *GifFile){
00469 #endif
00470     long BitsPerPixel;
00471     ByteType Buf;
00472     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
00473 
00474     /* Test and see what color map to use, and from it # bits per pixel: */
00475     if (GifFile -> IColorMap)
00476          BitsPerPixel = GifFile -> IBitsPerPixel;
00477     else
00478     if (GifFile -> SColorMap)
00479          BitsPerPixel = GifFile -> SBitsPerPixel;
00480     else {
00481         _GifError = E_GIF_ERR_NoColorMap;
00482         return ERROR;
00483     }
00484 
00485     Buf = BitsPerPixel = (BitsPerPixel < 2 ? 2 : BitsPerPixel);
00486     fwrite(&Buf, 1, 1, Private -> File);      /* Write the Code size to file */
00487 
00488     Private -> Buf[0] = 0;                         /* Nothing was output yet */
00489     Private -> BitsPerPixel = BitsPerPixel;
00490     Private -> ClearCode = (1 << BitsPerPixel);
00491     Private -> EOFCode = Private -> ClearCode + 1;
00492     Private -> RunningCode = Private -> EOFCode + 1;
00493     Private -> RunningBits = BitsPerPixel + 1;    /* Number of bits per code */
00494     Private -> MaxCode1 = 1 << Private -> RunningBits;      /* Max. code + 1 */
00495     Private -> CrntCode = FIRST_CODE;      /* Signal that this is first one! */
00496     Private -> CrntShiftState = 0;       /* No information in CrntShiftDWord */
00497     Private -> CrntShiftDWord = 0;
00498 
00499     /* Clear hash table and send Clear to make sure the decoder do the same  */
00500     _ClearHashTable(Private -> HashTable);
00501     if (EGifCompressOutput(Private, Private -> ClearCode) == ERROR) {
00502         _GifError = E_GIF_ERR_DiskIsFull;
00503         return ERROR;
00504     }
00505     return OK;
00506 }
00507 
00508 /******************************************************************************
00509 *   The LZ compression routine:                                               *
00510 *   This version compress the given buffer Line of length LineLen.            *
00511 *   This routine can be called few times (one per scan line, for example), in *
00512 * order the complete the whole image.                                         *
00513 ******************************************************************************/
00514 #ifdef _SUNSTYLE
00515 static long EGifCompressLine(GifFile,Line,LineLen) GifFileType *GifFile;
00516 PixelType *Line; long LineLen; {
00517 #else
00518 static long EGifCompressLine(GifFileType *GifFile, PixelType *Line,
00519                              long LineLen){
00520 #endif
00521     long i = 0, CrntCode, NewCode;
00522     unsigned long NewKey;
00523     PixelType Pixel;
00524     GifHashTableType *HashTable;
00525     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile -> Private;
00526 
00527     HashTable = Private -> HashTable;
00528 
00529     if (Private -> CrntCode == FIRST_CODE)                /* Its first time! */
00530          CrntCode = Line[i++];
00531     else CrntCode = Private -> CrntCode;     /* Get last code in compression */
00532 
00533     while (i < LineLen) {                           /* Decode LineLen items. */
00534         Pixel = Line[i++];                     /* Get next pixel from stream */
00535         /* Form a new unique key to search hash table for the code combines  */
00536         /* CrntCode as Prefix string with Pixel as postfix char.             */
00537         NewKey = (((unsigned long) CrntCode) << 8) + Pixel;
00538         if ((NewCode = _ExistsHashTable(HashTable, NewKey)) >= 0) {
00539             /* This Key is already there, or the string is old one, so       */
00540             /* simple take new code as our CrntCode:                         */
00541             CrntCode = NewCode;
00542         }
00543         else {
00544             /* Put it in hash table, output the prefix code, and make our    */
00545             /* CrntCode equal to Pixel.                                      */
00546             if (EGifCompressOutput(Private, CrntCode)
00547                 == ERROR) {
00548                 _GifError = E_GIF_ERR_DiskIsFull;
00549                 return ERROR;
00550             }
00551             CrntCode = Pixel;
00552 
00553             /* If however the HashTable if full, we send a clear first and   */
00554             /* Clear the hash table.                                         */
00555             if (Private -> RunningCode >= ZL_MAX_CODE) {
00556                 /* Time to do some clearance: */
00557                 if (EGifCompressOutput(Private, Private -> ClearCode)
00558                     == ERROR) {
00559                     _GifError = E_GIF_ERR_DiskIsFull;
00560                     return ERROR;
00561                 }
00562                 Private -> RunningCode = Private -> EOFCode + 1;
00563                 Private -> RunningBits = Private -> BitsPerPixel + 1;
00564                 Private -> MaxCode1 = 1 << Private -> RunningBits;
00565                 _ClearHashTable(HashTable);
00566             }
00567             else {
00568                 /* Put this unique key with its relative Code in hash table: */
00569                 _InsertHashTable(HashTable, NewKey, Private -> RunningCode++);
00570             }
00571         }
00572     }
00573 
00574     /* Preserve the current state of the compression algorithm: */
00575     Private -> CrntCode = CrntCode;
00576 
00577     if (Private -> PixelCount == 0)
00578     {
00579         /* We are done - output last Code and flush output buffers: */
00580         if (EGifCompressOutput(Private, CrntCode)
00581             == ERROR) {
00582             _GifError = E_GIF_ERR_DiskIsFull;
00583             return ERROR;
00584         }
00585         if (EGifCompressOutput(Private, Private -> EOFCode)
00586             == ERROR) {
00587             _GifError = E_GIF_ERR_DiskIsFull;
00588             return ERROR;
00589         }
00590         if (EGifCompressOutput(Private, FLUSH_OUTPUT) == ERROR) {
00591             _GifError = E_GIF_ERR_DiskIsFull;
00592             return ERROR;
00593         }
00594     }
00595 
00596     return OK;
00597 }
00598 
00599 /******************************************************************************
00600 *   The LZ compression output routine:                                        *
00601 *   This routine is responsable for the compression of the bit stream into    *
00602 * 8 bits (bytes) packets.                                                     *
00603 *   Returns OK if written succesfully.                                        *
00604 ******************************************************************************/
00605 #ifdef _SUNSTYLE
00606 static long EGifCompressOutput(Private,Code) GifFilePrivateType *Private;
00607        long Code; {
00608 #else
00609 static long EGifCompressOutput(GifFilePrivateType *Private, long Code){
00610 #endif
00611     long retval = OK;
00612 
00613     if (Code == FLUSH_OUTPUT) {
00614         while (Private -> CrntShiftState > 0) {
00615             /* Get Rid of what is left in DWord, and flush it */
00616             if (EGifBufferedOutput(Private -> File, Private -> Buf,
00617                 (int)Private -> CrntShiftDWord & 0xff) == ERROR) retval = ERROR;
00618             Private -> CrntShiftDWord >>= 8;
00619             Private -> CrntShiftState -= 8;
00620         }
00621         Private -> CrntShiftState = 0;                      /* For next time */
00622         if (EGifBufferedOutput(Private -> File, Private -> Buf,
00623             FLUSH_OUTPUT) == ERROR) retval = ERROR;
00624     }
00625     else {
00626         Private -> CrntShiftDWord |= ((long) Code) << Private -> CrntShiftState;
00627         Private -> CrntShiftState += Private -> RunningBits;
00628         while (Private -> CrntShiftState >= 8) {
00629             /* Dump out full bytes: */
00630             if (EGifBufferedOutput(Private -> File, Private -> Buf,
00631                 (int)Private -> CrntShiftDWord & 0xff) == ERROR) retval = ERROR;
00632             Private -> CrntShiftDWord >>= 8;
00633             Private -> CrntShiftState -= 8;
00634         }
00635     }
00636 
00637     /* If code cannt fit into RunningBits bits, must raise its size. Note */
00638     /* however that codes above 4095 are used for special signaling.      */
00639     if (Private -> RunningCode >= Private -> MaxCode1 && Code <= 4095) {
00640         Private -> MaxCode1 = 1 << ++Private -> RunningBits;
00641     }
00642 
00643     return retval;
00644 }
00645 
00646 /******************************************************************************
00647 *   This routines buffers the given characters until 255 characters are ready *
00648 * to be output. If Code is equal to -1 the buffer is flushed (EOF).           *
00649 *   The buffer is Dumped with first byte as its size, as GIF format requires. *
00650 *   Returns OK if written succesfully.                                        *
00651 ******************************************************************************/
00652 #ifdef _SUNSTYLE
00653 static long EGifBufferedOutput(File,Buf,c) FILE *File;
00654 ByteType *Buf; long c; {
00655 #else
00656 static long EGifBufferedOutput(FILE *File, ByteType *Buf, long c){
00657 #endif
00658     if (c == FLUSH_OUTPUT) {
00659         /* Flush everything out */
00660         if (Buf[0] != 0 && fwrite(Buf, 1, Buf[0]+1, File) != Buf[0] + 1)
00661         {
00662             _GifError = E_GIF_ERR_WriteFailed;
00663             return ERROR;
00664         }
00665         /* Mark end of compressed data, by an empty block (see GIF doc): */
00666         Buf[0] = 0;
00667         if (fwrite(Buf, 1, 1, File) != 1)
00668         {
00669             _GifError = E_GIF_ERR_WriteFailed;
00670             return ERROR;
00671         }
00672     }
00673     else {
00674         if (Buf[0] == 255) {
00675             /* Dump out this buffer - it is full: */
00676             if (fwrite(Buf, 1, Buf[0] + 1, File) != Buf[0] + 1)
00677             {
00678                 _GifError = E_GIF_ERR_WriteFailed;
00679                 return ERROR;
00680             }
00681             Buf[0] = 0;
00682         }
00683         Buf[++Buf[0]] = c;
00684     }
00685 
00686     return OK;
00687 }
00688 

Generated on Sun Apr 27 14:20:13 2014 for OpenFX by  doxygen 1.5.6