home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #4 / amigamamagazinepolishissue1998.iso / datatypes / gifanimdtc201.lha / gifanim_datatype / encoder.c < prev    next >
C/C++ Source or Header  |  1998-03-23  |  33KB  |  1,065 lines

  1.  
  2. /*
  3. **
  4. **  $VER: encoder.c 2.1 (23.3.98)
  5. **  gifanim.datatype 2.1
  6. **
  7. **  GIF Encoder of gifanim.datatype
  8. **
  9. **  Written 1997/1998 by Roland 'Gizzy' Mainz
  10. **  Original example source from David N. Junod
  11. **
  12. */
  13.  
  14. /* main includes */
  15. #include "classbase.h"
  16. #include "classdata.h"
  17.  
  18. /* ansi includes */
  19. #include <limits.h>
  20. #include <ctype.h>
  21.  
  22. /*****************************************************************************/
  23.  
  24. /* a code_int must be able to hold 2**BITS values of type int, and also -1 */
  25. typedef int      code_int;
  26. typedef long int count_int;
  27.  
  28. /* General DEFINEs */
  29. #define HSIZE  (5003)            /* 80% occupancy */
  30.  
  31. /*****************************************************************************/
  32.  
  33. /* encoder context data */
  34. struct GIFEncoder
  35. {
  36.     struct ClassBase   *classbase;
  37.  
  38.     Object             *object;
  39.     struct adtFrame     loadmsg;
  40.     struct BitMap      *srcbm[ 2 ];
  41.     UWORD               whichbm; /* which source bm ? */
  42.     struct RastPort     rp;
  43.  
  44.     ULONG               animwidth,
  45.                         animheight,
  46.                         animdepth,
  47.                         numcolors;
  48.     ULONG               tpf;
  49.     BPTR                outfile;
  50.  
  51.     int                 Width,
  52.                         Height;
  53.     int                 curx,
  54.                         cury;
  55.     long                CountDown;
  56.     int                 Pass/* = 0*/;
  57.     int                 Interlace;
  58.  
  59.     int                 n_bits;             /* number of bits/code */
  60.     code_int            maxcode;            /* maximum code, given n_bits */
  61.  
  62.     count_int           htab[ HSIZE ];
  63.     unsigned short      codetab[ HSIZE ];
  64.  
  65.     code_int            free_ent /* = 0*/;  /* first unused entry */
  66.  
  67.     /* block compression parameters -- after all codes are used up, and compression rate changes, start over. */
  68.     BOOL                clear_flg   /*  = 0*/;
  69.     int                 g_init_bits;
  70.     int                 ClearCode;
  71.     int                 EOFCode;
  72.  
  73.     unsigned long       cur_accum/* = 0*/;
  74.              int        cur_bits/*  = 0*/;
  75.  
  76.     char                accum[ 256 ]; /* Define the storage for the packet accumulator */
  77.     int                 a_count;      /* Number of characters so far in this 'packet'  */
  78. };
  79.  
  80. #define fputc( c, fh ) FPutC( (fh), (long)(c) )
  81. #define EOF            (-1)
  82.  
  83. static const int      maxbits    = MAX_LWZ_BITS;                  /* user settable max # bits/code */
  84. static const code_int maxmaxcode = (code_int)1UL << MAX_LWZ_BITS; /* should NEVER generate this code */
  85.  
  86. #define MAXCODE( nbits ) (((code_int) 1 << (nbits)) - 1)
  87.  
  88. #define HashTabOf( i )    (genc -> htab[ i ])
  89. #define CodeTabOf( i )    (genc -> codetab[ i ])
  90.  
  91. static const code_int hsize = HSIZE;                 /* for dynamic table sizing */
  92.  
  93. /* To save much memory, we overlay the table used by compress() with those
  94.  * used by decompress().  The tab_prefix table is the same size and type
  95.  * as the codetab.  The tab_suffix table needs 2**MAX_LWZ_BITS characters.  We
  96.  * get this from the beginning of htab.  The output stack uses the rest
  97.  * of htab, and contains characters.  There is plenty of room for any
  98.  * possible stack (stack used to be 8000 characters).
  99.  */
  100.  
  101. #define tab_prefixof(i) CodeTabOf(i)
  102. #define tab_suffixof(i) ((UBYTE *)(genc -> htab))[i]
  103. #define de_stack        ((UBYTE *)&tab_suffixof((code_int)1<<MAX_LWZ_BITS))
  104.  
  105.  
  106. /*****************************************************************************/
  107.  
  108. /* local prototypes */
  109. static struct GIFEncoder *CreateGIFEncoder( struct ClassBase *, Object *, struct GIFAnimInstData *, ULONG, ULONG, ULONG, ULONG, ULONG, BPTR );
  110. static void               DeleteGIFEncoder( struct ClassBase *, struct GIFEncoder *  );
  111.  
  112. static int                GetPixel( struct GIFEncoder *, int x, int y );
  113. static void               BumpPixel( struct GIFEncoder * );
  114. static int                GIFNextPixel( struct GIFEncoder * );
  115. static BOOL               GIFEncode( struct GIFEncoder *, struct GIFAnimInstData *, BOOL, WORD, WORD, struct ColorRegister *, ULONG, ULONG, ULONG );
  116. static void               Putword( struct GIFEncoder *, int );
  117. static void               compress( struct GIFEncoder *, int init_bits );
  118. static void               output( struct GIFEncoder *, code_int );
  119. static void               cl_block( struct GIFEncoder * );
  120. static void               cl_hash( struct GIFEncoder *, count_int hsize );
  121. static void               char_init( struct GIFEncoder * );
  122.  
  123. static void               char_out( struct GIFEncoder *, int );
  124. static void               flush_char( struct GIFEncoder * );
  125.  
  126. /*****************************************************************************/
  127.  
  128.  
  129. ULONG SaveGIFAnim( struct ClassBase *cb, struct IClass *cl, Object *o, struct dtWrite *dtw )
  130. {
  131.     ULONG retval = 0UL;
  132.     LONG  error  = 0L;
  133.  
  134.     /* A NULL file handle is a nop (GMultiView uses this to test if a datatype supports RAW writing) */
  135.     if( dtw -> dtw_FileHandle )
  136.     {
  137.       struct GIFAnimInstData *gaid = (struct GIFAnimInstData *)INST_DATA( cl, o );
  138.  
  139.       ULONG                 modeid;
  140.       struct ColorRegister *cm;
  141.       ULONG                 numcolors;
  142.       ULONG                 startframe = 0UL,
  143.                             numframes  = 0UL,
  144.                             framestep  = 1UL;
  145.       ULONG                 tpf        = 0UL;
  146.       ULONG                 animwidth,
  147.                             animheight,
  148.                             animdepth;
  149.  
  150.       if( GetDTAttrs( o, ADTA_ModeID,           (&modeid),
  151.                          ADTA_ColorRegisters,   (&cm),
  152.                          ADTA_NumColors,        (&numcolors),
  153.                          ADTA_Width,            (&animwidth),
  154.                          ADTA_Height,           (&animheight),
  155.                          ADTA_Depth,            (&animdepth),
  156.                          ADTA_Frame,            (&startframe),
  157.                          ADTA_Frames,           (&numframes),
  158.                          ADTA_TicksPerFrame,    (&tpf),
  159.                          TAG_DONE ) == 9UL )
  160.       {
  161.         verbose_printf( cb, gaid, "anim %lu*%lu*%lu, %lu colors, %lu frames, tpf %lu\n",
  162.                                   animwidth, animheight, animdepth, numcolors, numframes, tpf );
  163.  
  164.         /* GIF only supports up to 256 colors (8 bit) */
  165.         if( animdepth <= 8UL )
  166.         {
  167.           /* HAM cannot be implemented; EHB would be possible (on request) */
  168.           if( !(modeid & (HAM | EXTRA_HALFBRITE)) )
  169.           {
  170.             struct GIFEncoder *genc;
  171.  
  172.             if( genc = CreateGIFEncoder( cb, o, gaid, animwidth, animheight, animdepth, numcolors, tpf, (dtw -> dtw_FileHandle) ) )
  173.             {
  174.               struct TagItem *tstate,
  175.                              *ti;
  176.  
  177.               numframes -= startframe;
  178.  
  179.               tstate = dtw -> dtw_AttrList;
  180.  
  181.               while( ti = NextTagItem( (&tstate) ) )
  182.               {
  183.                 switch( ti -> ti_Tag )
  184.                 {
  185.                   case ADTA_Frame:            startframe = ti -> ti_Data; break;
  186.                   case ADTA_Frames:           numframes  = ti -> ti_Data; break;
  187.                   case ADTA_FrameIncrement:   framestep  = ti -> ti_Data; break;
  188.                 }
  189.               }
  190.  
  191.               if( framestep == 0UL ) framestep = 1UL;
  192.  
  193.               error_printf( cb, gaid, "saving gif anim %lu %lu %lu\n", startframe, numframes, framestep );
  194.  
  195.               if( numframes )
  196.               {
  197.                 retval = (LONG)GIFEncode( genc, gaid, FALSE, 0, -1, cm, startframe, numframes, framestep );
  198.                 error = IoErr();
  199.               }
  200.  
  201.               DeleteGIFEncoder( cb, genc );
  202.             }
  203.             else
  204.             {
  205.               /* Can't alloc gif encoder context data */
  206.               error = ERROR_NO_FREE_STORE;
  207.               error_printf( cb, gaid, "no memory for encoder context data\n" );
  208.             }
  209.           }
  210.           else
  211.           {
  212.             error_printf( cb, gaid, "HAM/EHB not supported by the GIF format\n" );
  213.             error = (modeid & EXTRA_HALFBRITE)?(ERROR_NOT_IMPLEMENTED):(DTERROR_INVALID_DATA);
  214.           }
  215.         }
  216.         else
  217.         {
  218.           error_printf( cb, gaid, "Object is too deep (%lu planes), gif encoder works only with depth <= 8\n", animdepth );
  219.           error = DTERROR_INVALID_DATA;
  220.         }
  221.       }
  222.       else
  223.       {
  224.         /* can't get required attributes from object */
  225.         error_printf( cb, gaid, "not enougth attributes\n" );
  226.         error = ERROR_OBJECT_WRONG_TYPE;
  227.       }
  228.  
  229.       /* Some info... */
  230.       if( retval )
  231.       {
  232.         verbose_printf( cb, gaid, "GIF Animation successfully created\n" );
  233.       }
  234.       else
  235.       {
  236.         error_printf( cb, gaid, "GIF Animation creation failed, error %ld\n", error );
  237.       }
  238.     }
  239.  
  240.     SetIoErr( error );
  241.  
  242.     return( retval );
  243. }
  244.  
  245.  
  246. /*****************************************************************************/
  247.  
  248. static
  249. struct GIFEncoder *CreateGIFEncoder( struct ClassBase *cb, Object *o, struct GIFAnimInstData *gaid, ULONG animwidth, ULONG animheight, ULONG animdepth, ULONG numcolors, ULONG tpf, BPTR out )
  250. {
  251.     struct GIFEncoder *genc;
  252.  
  253.     if( genc = (struct GIFEncoder *)AllocVec( (ULONG)sizeof( struct GIFEncoder ), (MEMF_PUBLIC | MEMF_CLEAR) ) )
  254.     {
  255.       /* Idiot testing... */
  256.       if( o && animwidth && animheight && animdepth && (numcolors > 0UL) && (numcolors <= MAXCOLORMAPSIZE) && tpf )
  257.       {
  258.         genc -> srcbm[ 0 ] = AllocBitMap( animwidth, animheight, animdepth, BMF_MINPLANES, NULL );
  259.         genc -> srcbm[ 1 ] = AllocBitMap( animwidth, animheight, animdepth, BMF_MINPLANES, NULL );
  260.  
  261.         if( (genc -> srcbm[ 0 ]) && (genc -> srcbm[ 1 ]) )
  262.         {
  263.           genc -> classbase  = cb;
  264.           genc -> object     = o;
  265.           genc -> outfile    = out;
  266.           genc -> animwidth  = animwidth;
  267.           genc -> animheight = animheight;
  268.           genc -> animdepth  = animdepth;
  269.           genc -> numcolors  = numcolors;
  270.           genc -> tpf        = tpf;
  271.  
  272.           /* Init source rastport */
  273.           InitRastPort( (&(genc -> rp)) );
  274.           genc -> rp . BitMap = genc -> srcbm[ 0 ]; /* genc -> whichbm is 0 here... */
  275.  
  276.           return( genc );
  277.         }
  278.         else
  279.         {
  280.           error_printf( cb, gaid, "no memory for bitmap\n" );
  281.         }
  282.  
  283.         FreeBitMap( (genc -> srcbm[ 1 ]) );
  284.         FreeBitMap( (genc -> srcbm[ 0 ]) );
  285.       }
  286.       else
  287.       {
  288.         error_printf( cb, gaid, "invalid arguments\n" );
  289.       }
  290.  
  291.       FreeVec( genc );
  292.     }
  293.  
  294.     return( NULL );
  295. }
  296.  
  297.  
  298. static
  299. void DeleteGIFEncoder( struct ClassBase *cb, struct GIFEncoder *genc )
  300. {
  301.     if( genc )
  302.     {
  303.       /* Unload any loaded frame... */
  304.       if( genc -> loadmsg . alf_UserData )
  305.       {
  306.         genc -> loadmsg . MethodID = ADTM_UNLOADFRAME;
  307.         DoMethodA( (genc -> object), (Msg)(&(genc -> loadmsg)) );
  308.       }
  309.  
  310.       FreeBitMap( (genc -> srcbm[ 1 ]) );
  311.       FreeBitMap( (genc -> srcbm[ 0 ]) );
  312.  
  313.       FreeVec( genc );
  314.     }
  315. }
  316.  
  317. /*****************************************************************************/
  318.  
  319. /* here begins the real encoder code... */
  320. #define cb (genc -> classbase)
  321.  
  322. static
  323. int GetPixel( struct GIFEncoder *genc, int x, int y )
  324. {
  325.     int pixel = (int)ReadPixel( (&(genc -> rp)), (long)x, (long)y );
  326.  
  327.     /* Should not occur, but... */
  328.     if( pixel >= (1UL << (genc -> animdepth)) )
  329.     {
  330.       pixel = 0;
  331.     }
  332.  
  333.     return( pixel );
  334. }
  335.  
  336.  
  337. /* Bump the 'curx' and 'cury' to point to the next pixel */
  338. static
  339. void BumpPixel( struct GIFEncoder *genc )
  340. {
  341.     /* Bump the current X position */
  342.     genc -> curx++;
  343.  
  344.     /* If we are at the end of a scan line, set curx back to the beginning
  345.      * If we are interlaced, bump the cury to the appropriate spot,
  346.      * otherwise, just increment it.
  347.      */
  348.     if( (genc -> curx) == (genc -> Width) )
  349.     {
  350.       genc -> curx = 0;
  351.  
  352.       if( genc -> Interlace )
  353.       {
  354.         switch( genc -> Pass )
  355.         {
  356.           case 0:
  357.           {
  358.               genc -> cury += 8;
  359.  
  360.               if( (genc -> cury) >= (genc -> Height) )
  361.               {
  362.                 genc -> Pass++;
  363.                 genc -> cury = 4;
  364.               }
  365.           }
  366.               break;
  367.  
  368.           case 1:
  369.           {
  370.               genc -> cury += 8;
  371.  
  372.               if( (genc -> cury) >= (genc -> Height) )
  373.               {
  374.                 genc -> Pass++;
  375.                 genc -> cury = 2;
  376.               }
  377.           }
  378.               break;
  379.  
  380.           case 2:
  381.           {
  382.               genc -> cury += 4;
  383.  
  384.               if( (genc -> cury) >= (genc -> Height) )
  385.               {
  386.                 genc -> Pass++;
  387.                 genc -> cury = 1;
  388.               }
  389.           }
  390.               break;
  391.  
  392.           case 3:
  393.           {
  394.               genc -> cury += 2;
  395.           }
  396.               break;
  397.         }
  398.       }
  399.       else
  400.       {
  401.         genc -> cury++;
  402.       }
  403.     }
  404. }
  405.  
  406.  
  407. /* Return the next pixel from the image */
  408. static
  409. int GIFNextPixel( struct GIFEncoder *genc )
  410. {
  411.     int r;
  412.  
  413.     if( (genc -> CountDown) == 0 )
  414.       return( EOF );
  415.  
  416.     --genc -> CountDown;
  417.  
  418.     r = GetPixel( genc, (genc -> curx), (genc -> cury) );
  419.  
  420.     BumpPixel( genc );
  421.  
  422.     return( r );
  423. }
  424.  
  425.  
  426. /* public */
  427. static
  428. BOOL GIFEncode( struct GIFEncoder *genc, struct GIFAnimInstData *gaid,
  429.                 BOOL GInterlace, WORD Background, WORD Transparent,
  430.                 struct ColorRegister *cm, ULONG startframe, ULONG numframes, ULONG framestep )
  431. {
  432.     ULONG                timestamp;
  433.     int                  B;
  434.     int                  RWidth,
  435.                          RHeight;
  436.     int                  Resolution;
  437.     int                  ColorMapSize;
  438.     int                  InitCodeSize;
  439.     int                  i;
  440.     BPTR                 fp               = genc -> outfile;
  441.     LONG                 gif_delay        = 0L;
  442.     BOOL                 save_frame;
  443.     struct ColorRegister localcolormap[ MAXCOLORMAPSIZE ];
  444.     BOOL                 save_localcolormap;
  445.     BOOL                 firstframe       = TRUE; /* the first frame has not been written yet */
  446.  
  447.     genc -> Interlace = GInterlace;
  448.  
  449.     ColorMapSize = 1UL << (genc -> animdepth);
  450.  
  451.     RWidth  = genc -> Width  = genc -> animwidth;
  452.     RHeight = genc -> Height = genc -> animheight;
  453.  
  454.     Resolution = genc -> animdepth;
  455.  
  456.     /* The initial code size */
  457.     if( (genc -> animdepth) <= 1 )
  458.       InitCodeSize = 2;
  459.     else
  460.       InitCodeSize = (genc -> animdepth);
  461.  
  462.     /* Write the GIF signature */
  463.     FWrite( fp, "GIF", 1, 3 );
  464.  
  465.     /* Write the GIF version number (only "89a" because of the "Graphics Control Extension" used for timing) */
  466.     FWrite( fp, "89a", 1, 3 );
  467.  
  468.     /* Write out the screen width and height */
  469.     Putword( genc, RWidth  );
  470.     Putword( genc, RHeight );
  471.  
  472.     /* Flag field */
  473.     {
  474.       /* Indicate that there is a global colour map */
  475.       B = LOCALCOLORMAP; /* Yes, there is a global color map */
  476.  
  477.       /* OR in the resolution */
  478.       B |= (Resolution - 1) << 5;
  479.  
  480.       /* OR in the Bits per Pixel (Size of global color map) */
  481.       B |= ((genc -> animdepth) - 1);
  482.  
  483.       /* Write it out */
  484.       fputc( B, fp );
  485.     }
  486.  
  487.     /* Write out the Background colour */
  488.     fputc( Background, fp );
  489.  
  490.     /* Write pixel aspect ratio (not implemented yet, therefore 0 here) */
  491.     fputc( 0, fp );
  492.  
  493.     /* Write out the Global Colour Map */
  494.     for( i = 0 ; i < ColorMapSize ; i++ )
  495.     {
  496.       fputc( (cm[ i ] . red),   fp );
  497.       fputc( (cm[ i ] . green), fp );
  498.       fputc( (cm[ i ] . blue),  fp );
  499.     }
  500.  
  501.     /* Write comment extensions for each DTA_Obj#? attribute we found... */
  502.     {
  503.       /* ti_Tag is the attribute to check; ti_Data is the label written in front of the data */
  504.       struct TagItem commentstags[] =
  505.       {
  506.         { DTA_ObjName,       (ULONG)"name: "       },
  507.         { DTA_ObjAuthor,     (ULONG)"author: "     },
  508.         { DTA_ObjAnnotation, (ULONG)"annotation: " },
  509.         { DTA_ObjCopyright,  (ULONG)"copyright: "  },
  510.         { DTA_ObjVersion,    (ULONG)"version: "    },
  511.         { TAG_DONE,          0UL                   }
  512.       };
  513.  
  514.       struct TagItem *tstate = commentstags,
  515.                      *ti;
  516.  
  517.       while( ti = NextTagItem( (&tstate) ) )
  518.       {
  519.         STRPTR string,
  520.                label = (STRPTR)(ti -> ti_Data);
  521.  
  522.         (void)GetDTAttrs( (genc -> object), (ti -> ti_Tag), (&string), TAG_DONE );
  523.  
  524.         if( string )
  525.         {
  526.           UBYTE *c;
  527.  
  528.           fputc( '!',   fp ); /* Extension */
  529.           fputc( 0xfe,  fp ); /* GIF89a Comment extension */
  530.  
  531.           c = label;  while( *c ) char_out( genc, *c++ ); /* write comment label            */
  532.           c = string; while( *c ) char_out( genc, *c++ ); /* write DTA_Obj#? attribute data */
  533.  
  534.           flush_char( genc );
  535.  
  536.           fputc( 0, fp ); /* Block terminator */
  537.         }
  538.       }
  539.     }
  540.  
  541.     for( timestamp = startframe ; numframes > 0UL ; timestamp += framestep, numframes-- )
  542.     {
  543.       /* reset some values */
  544.       save_frame         = FALSE;
  545.       save_localcolormap = FALSE;
  546.  
  547.       /* Check for abort... */
  548.       if( CheckSignal( SIGBREAKF_CTRL_D ) )
  549.       {
  550.         SetIoErr( ERROR_BREAK );
  551.         return( FALSE );
  552.       }
  553.  
  554.       genc -> loadmsg . MethodID      = ADTM_LOADFRAME;
  555.       genc -> loadmsg . alf_TimeStamp = timestamp;
  556.       genc -> loadmsg . alf_Frame     = timestamp; /* CBM anim.datatype compatibility ONLY */
  557.  
  558.       if( DoMethodA( (genc -> object), (Msg)(&(genc -> loadmsg)) ) )
  559.       {
  560.         /* print frame contents */
  561.         verbose_printf( cb, gaid, "frame: timestamp %lu frame %lu duration %lu bitmap %lx cmap %lx sample %lx len %lu period %lu\n",
  562.                         timestamp,
  563.                         (genc -> loadmsg . alf_Frame),
  564.                         (genc -> loadmsg . alf_Duration),
  565.                         (genc -> loadmsg . alf_BitMap),
  566.                         (genc -> loadmsg . alf_CMap),
  567.                         (genc -> loadmsg . alf_Sample),
  568.                         (genc -> loadmsg . alf_SampleLength),
  569.                         (genc -> loadmsg . alf_Period) );
  570.  
  571.         /* If we got a bitmap (should always be TRUE), compare it with the previous one
  572.          * If there was a change of the contents, write a matching gif image out...
  573.          */
  574.         if( genc -> loadmsg . alf_BitMap )
  575.         {
  576.           struct BitMap *bm;
  577.  
  578.           /* swap bitmaps */
  579.           genc -> whichbm = !(genc -> whichbm); /* 0 to 1 or 1 to 0 */
  580.  
  581.           bm = (genc -> srcbm[ (genc -> whichbm) ]); /* shortcut */
  582.  
  583.           /* Following GetPixel calls should use this bitmap */
  584.           genc -> rp . BitMap = bm;
  585.  
  586.           CopyBitMap( cb, bm, (genc -> loadmsg . alf_BitMap), (genc -> animwidth), (genc -> animheight) );
  587.  
  588.           /* The first frame must be written because ther's no previous frame to compare... */
  589.           if( firstframe )
  590.           {
  591.             firstframe = FALSE;
  592.             save_frame = TRUE;
  593.           }
  594.           else
  595.           {
  596.             /* Compare old and new bitmap and check if they're equal
  597.              * If they're equal, there's no need to write them out...
  598.              */
  599.             save_frame = !CmpBitMap( cb, (genc -> srcbm[ (genc -> whichbm) ]), (genc -> srcbm[ !(genc -> whichbm) ]), (genc -> animwidth), (genc -> animheight) );
  600.           }
  601.         }
  602.         else
  603.         {
  604.           /* Should not occur */
  605.           error_printf( cb, gaid, "WARNING: no bitmap\n" );
  606.           SetIoErr( ERROR_OBJECT_WRONG_TYPE ); /* not very meaningfull */
  607.           return( FALSE );
  608.         }
  609.  
  610.         /* If we got a local colormap, check if it is different from the global one.
  611.          * If there is a difference, set "save_localcolormap" to TRUE that a local colormap is saved below
  612.          */
  613.         if( genc -> loadmsg . alf_CMap )
  614.         {
  615.           ULONG color;
  616.           ULONG rgb[ 3 ];
  617.  
  618.           for( color = 0UL ; color < ColorMapSize ; color++ )
  619.           {
  620.             GetRGB32( (genc -> loadmsg . alf_CMap), color, 1UL, rgb );
  621.  
  622.             localcolormap[ color ] . red   = (UBYTE)(rgb[ 0 ] >> 24UL);
  623.             localcolormap[ color ] . green = (UBYTE)(rgb[ 1 ] >> 24UL);
  624.             localcolormap[ color ] . blue  = (UBYTE)(rgb[ 2 ] >> 24UL);
  625.  
  626.             /* Any different between alf_CMap and global color map (e.g. ADTA_ColorRegisters) ? */
  627.             if( ((localcolormap[ color ] . red)   != (cm[ color ] . red))   ||
  628.                 ((localcolormap[ color ] . green) != (cm[ color ] . green)) ||
  629.                 ((localcolormap[ color ] . blue)  != (cm[ color ] . blue)) )
  630.             {
  631.               /* Save local colormap */
  632.               save_localcolormap = TRUE;
  633.             }
  634.           }
  635.         }
  636.  
  637.         /* Any change in the data ? */
  638.         if( save_frame || save_localcolormap )
  639.         {
  640.           verbose_printf( cb, gaid, "saving gif image%s, %ld/100 sec delay\n",
  641.                           ((save_localcolormap)?(" with local colormap"):("")),
  642.                           gif_delay );
  643.  
  644.           /* Calculate number of bits we are expecting */
  645.           genc -> CountDown = (long)(genc -> Width) * (long)(genc -> Height);
  646.  
  647.           /* Set up the current x and y position */
  648.           genc -> curx = genc -> cury = 0;
  649.  
  650.           /* Indicate which pass we are on (if interlace) */
  651.           genc -> Pass = 0;
  652.  
  653.           /* Reset */
  654.           genc -> cur_accum = 0;
  655.           genc -> cur_bits  = 0;
  656.  
  657.           genc -> a_count   = 0;
  658.  
  659.           /* Write out Graphic Control Extension for timing (and transparent colour index, if necessary.) */
  660.           {
  661.             UBYTE packed = 0U;
  662.  
  663.             fputc( '!',                                  fp );  /* Extension */
  664.             fputc( 0xf9,                                 fp );  /* GIF89a Graphic Control Extension */
  665.             fputc( 4,                                    fp );  /* Block size */
  666.  
  667.             if( Transparent >= 0 )
  668.             {
  669.               packed |= 0x01;                                   /* has transparent color ! */
  670.             }
  671.  
  672.             fputc( packed,                               fp );
  673.  
  674.             Putword( genc, (int)gif_delay );                    /* Delay in 1/100 sec */
  675.  
  676.             fputc( (Transparent >= 0)?(Transparent):(0), fp );
  677.             fputc( 0,                                    fp );  /* Block terminator */
  678.  
  679.             gif_delay = 0L; /* delay time written... */
  680.           }
  681.  
  682.           /* Write GIF Image Descriptor */
  683.           {
  684.             UBYTE packed = 0U;
  685.  
  686.             /* Write: "Start of raster data" */
  687.             fputc( ',', fp );
  688.  
  689.             /* Write the Image header (does currently not support deltas) */
  690.             Putword( genc, 0                 );
  691.             Putword( genc, 0                 );
  692.             Putword( genc, (genc -> Width)   );
  693.             Putword( genc, (genc -> Height)  );
  694.  
  695.             /* Write out whether or not the image is interlaced */
  696.             if( genc -> Interlace )
  697.             {
  698.               packed |= INTERLACE;
  699.             }
  700.  
  701.             /* Write out whether or not the image has an own colormap */
  702.             if( save_localcolormap )
  703.             {
  704.               packed |= LOCALCOLORMAP;
  705.  
  706.               /* OR in the Bits per Pixel (Size of local color map) */
  707.               packed |= ((genc -> animdepth) - 1);
  708.             }
  709.  
  710.             fputc( packed, fp );
  711.           }
  712.  
  713.           /* Write local color map ? */
  714.           if( save_localcolormap )
  715.           {
  716.             ULONG color;
  717.  
  718.             /* Write out the Local Colour Map */
  719.             for( color = 0UL ; color < ColorMapSize ; color++ )
  720.             {
  721.               fputc( (localcolormap[ color ] . red),    fp );
  722.               fputc( (localcolormap[ color ] . green),  fp );
  723.               fputc( (localcolormap[ color ] . blue),   fp );
  724.             }
  725.           }
  726.  
  727.           /* Write out the initial code size */
  728.           fputc( InitCodeSize, fp );
  729.  
  730.           /* Go and actually compress the data */
  731.           compress( genc, (InitCodeSize + 1) );
  732.  
  733.           /* Write out a Zero-length packet (to end the series) */
  734.           fputc( 0, fp );
  735.         }
  736.  
  737.         /* Sum here the time to wait for this frame...
  738.          * (and Scale from 1/1200 units (realtime.library && ADTA_TicksPerFrame) to GIF delay (1/100) units)
  739.          */
  740.         gif_delay += INTDIVR( (100UL * (genc -> tpf)), TICK_FREQ );
  741.       }
  742.       else
  743.       {
  744.         /* ADTM_LOADFRAME failed: Result2 contains the error cause */
  745.         return( FALSE );
  746.       }
  747.     }
  748.  
  749.     /* Write the GIF file terminator */
  750.     fputc( ';', fp );
  751.  
  752.     return( TRUE );
  753. }
  754.  
  755.  
  756. /* Write out a LITTLE_ENDIAN word to the GIF file */
  757. static
  758. void Putword( struct GIFEncoder *genc, int w )
  759. {
  760.     fputc( (w & 0xff),         (genc -> outfile) );
  761.     fputc( ((w / 256) & 0xff), (genc -> outfile) );
  762. }
  763.  
  764.  
  765. /***************************************************************************
  766.  *
  767.  *  GIFCOMPR.C       - GIF Image compression routines
  768.  *
  769.  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
  770.  *  David Rowley (mgardi@watdcsu.waterloo.edu)
  771.  *
  772.  ***************************************************************************/
  773.  
  774.  
  775. /*
  776.  *
  777.  * GIF Image compression - modified 'compress'
  778.  *
  779.  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
  780.  *
  781.  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
  782.  *              Jim McKie               (decvax!mcvax!jim)
  783.  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
  784.  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
  785.  *              James A. Woods          (decvax!ihnp4!ames!jaw)
  786.  *              Joe Orost               (decvax!vax135!petsd!joe)
  787.  *
  788.  */
  789.  
  790.  
  791. /*
  792.  * compress stdin to stdout
  793.  *
  794.  * Algorithm:  use open addressing double hashing (no chaining) on the
  795.  * prefix code / next character combination.  We do a variant of Knuth's
  796.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  797.  * secondary probe.  Here, the modular division first probe is gives way
  798.  * to a faster exclusive-or manipulation.  Also do block compression with
  799.  * an adaptive reset, whereby the code table is cleared when the compression
  800.  * ratio decreases, but after the table fills.  The variable-length output
  801.  * codes are re-sized at this point, and a special CLEAR code is generated
  802.  * for the decompressor.  Late addition:  construct the table according to
  803.  * file size for noticeable speed improvement on small files.  Please direct
  804.  * questions about this implementation to ames!jaw.
  805.  */
  806.  
  807. static
  808. void compress( struct GIFEncoder *genc, int init_bits )
  809. {
  810.     register long     fcode;
  811.     register code_int i /* = 0 */;
  812.     register int      c;
  813.     register code_int ent;
  814.     register code_int disp;
  815.     register code_int hsize_reg;
  816.     register int      hshift;
  817.  
  818.     /* Set up the globals:  g_init_bits - initial number of bits */
  819.     genc -> g_init_bits = init_bits;
  820.  
  821.     /* Set up the necessary values */
  822.     genc -> clear_flg = FALSE;
  823.     genc -> maxcode   = MAXCODE((genc -> n_bits) = (genc -> g_init_bits));
  824.  
  825.     genc -> ClearCode  = (1 << (init_bits - 1));
  826.     genc -> EOFCode    = genc -> ClearCode + 1;
  827.     genc -> free_ent   = genc -> ClearCode + 2;
  828.  
  829.     char_init( genc );
  830.  
  831.     ent = GIFNextPixel( genc );
  832.  
  833.     for( fcode = (long)hsize, hshift = 0 ;  fcode < 65536L ; fcode *= 2L )
  834.     {
  835.       hshift++;
  836.     }
  837.  
  838.     hshift = 8 - hshift;                /* set hash code range bound */
  839.  
  840.     hsize_reg = hsize;
  841.     cl_hash( genc, (count_int)hsize_reg );            /* clear hash table */
  842.  
  843.     output( genc, (code_int)(genc -> ClearCode) );
  844.  
  845.     while( (c = GIFNextPixel( genc )) != EOF )
  846.     {
  847.         fcode = (long) (((long) c << maxbits) + ent);
  848.         i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
  849.  
  850.         if( HashTabOf (i) == fcode )
  851.         {
  852.             ent = CodeTabOf (i);
  853.             continue;
  854.         }
  855.         else
  856.           if ( (long)HashTabOf (i) < 0 )      /* empty slot */
  857.             goto nomatch;
  858.  
  859.         disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
  860.         if ( i == 0 )
  861.           disp = 1;
  862. probe:
  863.         if ( (i -= disp) < 0 )
  864.           i += hsize_reg;
  865.  
  866.         if ( HashTabOf (i) == fcode )
  867.         {
  868.           ent = CodeTabOf (i);
  869.           continue;
  870.         }
  871.  
  872.         if( (long)HashTabOf (i) > 0 )
  873.           goto probe;
  874.  
  875. nomatch:
  876.         output( genc, (code_int) ent );
  877.         ent = c;
  878.         if( (genc -> free_ent) < maxmaxcode )
  879.         {
  880.           CodeTabOf( i ) = genc -> free_ent++; /* code -> hashtable */
  881.           HashTabOf( i ) = fcode;
  882.         }
  883.         else
  884.         {
  885.           cl_block( genc );
  886.         }
  887.     }
  888.  
  889.     /* Put out the final code. */
  890.     output( genc, (code_int)ent );
  891.     output( genc, (code_int)(genc -> EOFCode) );
  892. }
  893.  
  894. /*****************************************************************
  895.  * TAG( output )
  896.  *
  897.  * Output the given code.
  898.  * Inputs:
  899.  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  900.  *              that n_bits =< (long)wordsize - 1.
  901.  * Outputs:
  902.  *      Outputs code to the file.
  903.  * Assumptions:
  904.  *      Chars are 8 bits long.
  905.  * Algorithm:
  906.  *      Maintain a BITS character long buffer (so that 8 codes will
  907.  * fit in it exactly).  Use the VAX insv instruction to insert each
  908.  * code in turn.  When the buffer fills up empty it and start over.
  909.  */
  910.  
  911. static const
  912. unsigned long masks[] =
  913. {
  914.   0x0000, 0x0001, 0x0003, 0x0007,
  915.   0x000F, 0x001F, 0x003F, 0x007F,
  916.   0x00FF, 0x01FF, 0x03FF, 0x07FF,
  917.   0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF,
  918.   0xFFFF
  919. };
  920.  
  921.  
  922. static
  923. void output( struct GIFEncoder *genc, code_int code )
  924. {
  925.     genc -> cur_accum &= masks[ genc -> cur_bits ];
  926.  
  927.     if( genc -> cur_bits > 0 )
  928.       genc -> cur_accum |= ((long)code << genc -> cur_bits);
  929.     else
  930.       genc -> cur_accum = code;
  931.  
  932.     genc -> cur_bits += genc -> n_bits;
  933.  
  934.     while( genc -> cur_bits >= 8 )
  935.     {
  936.       char_out( genc, (unsigned int)(genc -> cur_accum & 0xff) );
  937.       genc -> cur_accum >>= 8;
  938.       genc -> cur_bits -= 8;
  939.     }
  940.  
  941.     /* If the next entry is going to be too big for the code size,
  942.      * then increase it, if possible.
  943.      */
  944.     if( ((genc -> free_ent) > (genc -> maxcode)) || (genc -> clear_flg) )
  945.     {
  946.       if( genc -> clear_flg )
  947.       {
  948.         genc -> maxcode = MAXCODE ((genc -> n_bits) = (genc -> g_init_bits));
  949.         genc -> clear_flg = FALSE;
  950.       }
  951.       else
  952.       {
  953.         ++genc -> n_bits;
  954.  
  955.         if( (genc -> n_bits) == maxbits )
  956.           genc -> maxcode = maxmaxcode;
  957.         else
  958.           genc -> maxcode = MAXCODE(genc -> n_bits);
  959.       }
  960.     }
  961.  
  962.     if( code == (genc -> EOFCode) )
  963.     {
  964.       /* At EOF, write the rest of the buffer. */
  965.       while( genc -> cur_bits > 0 )
  966.       {
  967.         char_out( genc, (unsigned int)(genc -> cur_accum & 0xff) );
  968.         genc -> cur_accum >>= 8;
  969.         genc -> cur_bits -= 8;
  970.       }
  971.  
  972.       flush_char( genc );
  973.     }
  974. }
  975.  
  976.  
  977. /* Clear out the hash table */
  978. static
  979. void cl_block( struct GIFEncoder *genc )             /* table clear for block compress */
  980. {
  981.     cl_hash ( genc, (count_int) hsize );
  982.     genc -> free_ent  = (genc -> ClearCode) + 2;
  983.     genc -> clear_flg = TRUE;
  984.  
  985.     output( genc, (code_int)(genc -> ClearCode) );
  986. }
  987.  
  988.  
  989. static
  990. void cl_hash( struct GIFEncoder *genc, register count_int hsize )          /* reset code table */
  991. {
  992.     register count_int *htab_p = (genc -> htab) + hsize;
  993.  
  994.     register long i;
  995.     register long m1 = -1;
  996.  
  997.     i = hsize - 16;
  998.     do /* might use Sys V memset(3) here */
  999.     {
  1000.       *(htab_p-16) = m1;
  1001.       *(htab_p-15) = m1;
  1002.       *(htab_p-14) = m1;
  1003.       *(htab_p-13) = m1;
  1004.       *(htab_p-12) = m1;
  1005.       *(htab_p-11) = m1;
  1006.       *(htab_p-10) = m1;
  1007.       *(htab_p- 9) = m1;
  1008.       *(htab_p- 8) = m1;
  1009.       *(htab_p- 7) = m1;
  1010.       *(htab_p- 6) = m1;
  1011.       *(htab_p- 5) = m1;
  1012.       *(htab_p- 4) = m1;
  1013.       *(htab_p- 3) = m1;
  1014.       *(htab_p- 2) = m1;
  1015.       *(htab_p- 1) = m1;
  1016.       htab_p -= 16;
  1017.     } while ((i -= 16) >= 0);
  1018.  
  1019.     for ( i += 16; i > 0; --i )
  1020.       *--htab_p = m1;
  1021. }
  1022.  
  1023.  
  1024. /******************************************************************************
  1025.  *
  1026.  * GIF Specific routines
  1027.  *
  1028.  ******************************************************************************/
  1029.  
  1030.  
  1031. /* Set up the 'byte output' routine */
  1032. static
  1033. void char_init( struct GIFEncoder *genc )
  1034. {
  1035.     genc -> a_count = 0;
  1036. }
  1037.  
  1038.  
  1039. /* Add a character to the end of the current packet, and if it is 254
  1040.  * characters, flush the packet to disk.
  1041.  */
  1042. static
  1043. void char_out( struct GIFEncoder *genc, int c )
  1044. {
  1045.     genc -> accum[ (genc -> a_count)++ ] = c;
  1046.  
  1047.     if( (genc -> a_count) >= 254 )
  1048.       flush_char( genc );
  1049. }
  1050.  
  1051.  
  1052. /* Flush the packet to disk, and reset the accumulator */
  1053. static
  1054. void flush_char( struct GIFEncoder *genc )
  1055. {
  1056.     if( (genc -> a_count) > 0 )
  1057.     {
  1058.       fputc( (genc -> a_count), (genc -> outfile) );
  1059.       FWrite( (genc -> outfile), (genc -> accum), 1UL, (ULONG)(genc -> a_count) );
  1060.       genc -> a_count = 0;
  1061.     }
  1062. }
  1063.  
  1064.  
  1065.