home *** CD-ROM | disk | FTP | other *** search
/ Dream 44 / Amiga_Dream_44.iso / Linux / Apps / xanim.tgz / xanim / xanim27064 / xa_gif.c < prev    next >
C/C++ Source or Header  |  1997-01-26  |  17KB  |  650 lines

  1.  
  2. /*
  3.  * xa_gif.c
  4.  *
  5.  * Copyright (C) 1990,1991,1992,1993,1994,1995,1996,1997 by Mark Podlipec. 
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified and redistributed without
  9.  * fee for non-commerical purposes provided that this copyright notice is
  10.  * preserved intact on all copies and modified copies.
  11.  * 
  12.  * There is no warranty or other guarantee of fitness of this software.
  13.  * It is provided solely "as is". The author(s) disclaim(s) all
  14.  * responsibility and liability with respect to this software's usage
  15.  * or its effect upon hardware or computer systems.
  16.  *
  17.  */
  18.  
  19. /* REVISIONS ***********
  20.  * 30Mar95  Code made a little more robust to handle GIF images that
  21.  *          violate the spec by not including an EOI and the end
  22.  *          of the image.
  23.  */
  24. #include "xa_gif.h"
  25.  
  26. xaULONG GIF_Read_Anim();
  27. GIF_FRAME *GIF_Read_File();
  28. GIF_FRAME *GIF_Add_Frame();
  29.  
  30. xaULONG GIF_Decompress();
  31. xaULONG GIF_Get_Next_Entry();
  32. void GIF_Add_To_Table();
  33. xaULONG GIF_Send_Data();
  34. void GIF_Init_Table();
  35. void GIF_Clear_Table();
  36. xaULONG GIF_Get_Code();
  37. void GIF_Screen_Header();
  38. void GIF_Image_Header();
  39. void GIF_Read_Extension();
  40.  
  41. XA_ACTION *ACT_Get_Action();
  42. XA_CHDR   *ACT_Get_CMAP();
  43. void ACT_Setup_PIXMAP();
  44. void ACT_Setup_IMAGE();
  45. void ACT_Setup_CLIP();
  46. void ACT_Setup_Mapped();
  47. void ACT_Add_CHDR_To_Action();
  48.  
  49.  
  50. #define MAXVAL  4100            /* maxval of lzw coding size */
  51. #define MAXVALP 4200
  52.  
  53.  
  54. #define GIF_CMAP_SIZE 256
  55. static GIF_Screen_Hdr gifscrn;
  56. static GIF_Image_Hdr gifimage;
  57. static ColorReg gif_cmap[GIF_CMAP_SIZE];
  58. static XA_CHDR *gif_chdr_now;
  59. static GIF_Table table[MAXVALP];
  60.  
  61. static xaULONG root_code_size,code_size,CLEAR,EOI,INCSIZE;
  62. static xaULONG nextab;
  63. static xaULONG gif_mask[16] = {1,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,0,0};
  64. static xaULONG gif_ptwo[16] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,0,0};
  65. static xaUBYTE gif_buff[MAXVALP];
  66. static xaULONG gif_block_size;
  67. static xaLONG gif_bits,num_bits;
  68. static xaULONG gif_lace_flag;
  69.  
  70. static xaLONG gif_max_imagec,gif_max_imagex,gif_max_imagey,gif_max_imaged;
  71. static xaULONG gif_imagex,gif_imagey,gif_imagec,gif_imaged;
  72. static xaULONG gif_screenx,gif_screeny;
  73.  
  74. static xaLONG pic_i,pic_size;
  75.  
  76. /* GIF89a variables */
  77. static xaLONG gif_anim_type;  /* from GIF89 f9 extension */
  78. static xaLONG gif_anim_time;  /* from GIF89 f9 extension */
  79. static xaLONG gif_anim_mask;  /* from GIF89 f9 extension */
  80.  
  81. static GIF_FRAME *gif_frame_start,*gif_frame_cur;
  82. static xaULONG gif_frame_cnt;
  83.  
  84. GIF_FRAME *GIF_Add_Frame(time,act)
  85. xaULONG time;
  86. XA_ACTION *act;
  87. {
  88.   GIF_FRAME *gframe;
  89.  
  90.   gframe = (GIF_FRAME *) malloc(sizeof(GIF_FRAME));
  91.   if (gframe == 0) TheEnd1("GIF_Add_Frame: malloc err");
  92.  
  93.   gframe->time = time;
  94.   gframe->act = act;
  95.   gframe->next = 0;
  96.  
  97.   if (gif_frame_start == 0) gif_frame_start = gframe;
  98.   else gif_frame_cur->next = gframe;
  99.  
  100.   gif_frame_cur = gframe;
  101.   gif_frame_cnt++;
  102.   return(gframe);
  103. }
  104.  
  105. void
  106. GIF_Free_Frame_List(gframes)
  107. GIF_FRAME *gframes;
  108. {
  109.   GIF_FRAME *gtmp;
  110.   while(gframes != 0)
  111.   {
  112.     gtmp = gframes;
  113.     gframes = gframes->next;
  114.     FREE(gtmp,0x3000);
  115.   }
  116. }
  117.  
  118. xaULONG
  119. GIF_Read_Anim(fname,anim_hdr)
  120. char *fname;
  121. XA_ANIM_HDR *anim_hdr;
  122. {
  123.   GIF_FRAME *glist,*gtmp;
  124.   xaULONG frame_cnt,i;
  125.   xaLONG t_time = 0;
  126.  
  127.   glist = GIF_Read_File(fname,anim_hdr,&frame_cnt);
  128.   if (glist==0) return(xaFALSE);
  129.  
  130.   anim_hdr->frame_lst = (XA_FRAME *)malloc(sizeof(XA_FRAME) * (frame_cnt+1));
  131.   if (anim_hdr->frame_lst == NULL)
  132.        TheEnd1("GIF_Read_Anim: malloc err");
  133.  
  134.   gtmp = glist;
  135.   i = 0;
  136.   while(gtmp != 0)
  137.   {
  138.     if (i >= frame_cnt)
  139.     {
  140.       fprintf(stderr,"GIF_Read_Anim: frame inconsistency %d %d\n",
  141.         i,frame_cnt);
  142.       break;
  143.     }
  144.     anim_hdr->frame_lst[i].time_dur = gtmp->time;
  145.     anim_hdr->frame_lst[i].zztime = t_time;
  146.     t_time += gtmp->time;
  147.     anim_hdr->frame_lst[i].act = gtmp->act;
  148.     gtmp = gtmp->next;
  149.     i++;
  150.   }
  151.   if (i > 0) anim_hdr->total_time = anim_hdr->frame_lst[i-1].zztime
  152.                 + anim_hdr->frame_lst[i-1].time_dur;
  153.   else anim_hdr->total_time = 0;
  154.   anim_hdr->frame_lst[i].time_dur = 0;
  155.   anim_hdr->frame_lst[i].zztime = -1;
  156.   anim_hdr->frame_lst[i].act  = 0;
  157.   anim_hdr->loop_frame = 0;
  158.   if (i > 0) anim_hdr->last_frame = i - 1;
  159.   else i = 0;
  160.  
  161.   GIF_Free_Frame_List(glist);
  162.   return(xaTRUE);
  163. }
  164.  
  165. /*
  166.  *
  167.  */
  168. GIF_FRAME *GIF_Read_File(fname,anim_hdr,frame_cnt)
  169. char *fname;
  170. XA_ANIM_HDR *anim_hdr;
  171. xaULONG *frame_cnt;
  172. {
  173.   XA_INPUT *xin = anim_hdr->xin;
  174.   xaLONG i,exit_flag;
  175.   XA_ACTION *act;
  176.  
  177.   gif_frame_cnt = 0;
  178.   gif_frame_start = gif_frame_cur = 0;
  179.   gif_imagex = gif_max_imagex = 0;
  180.   gif_imagey = gif_max_imagey = 0;
  181.   gif_imagec = gif_max_imagec = 0;
  182.   gif_imaged = gif_max_imaged = 0;
  183.   gif_screenx = 0;
  184.   gif_screeny = 0;
  185.  
  186.   gif_anim_type = 0;
  187.   gif_anim_time = XA_GET_TIME(100); /* 100ms is 10 fps */
  188.   gif_anim_mask = 0;
  189.  
  190.   GIF_Screen_Header(xin,anim_hdr);
  191.  
  192.   /*** read until  ,  separator */
  193.   do
  194.   {
  195.     i=xin->Read_U8(xin);
  196.     if ( (i<0) && xin->At_EOF(xin,-1))
  197.     {
  198.       xin->Close_File(xin);
  199.       fprintf(stderr,"GIF_Read_Header: Unexpected EOF\n");
  200.       return(0);
  201.     }
  202.     if (i == '!') GIF_Read_Extension(xin);  /* GIF extension */
  203.   } while(i != ',');
  204.  
  205.   exit_flag = 0;
  206.   while(!exit_flag)
  207.   {
  208.     xaUBYTE *pic_ptr;
  209.   
  210.     /* Read Image Header
  211.      */
  212.     GIF_Image_Header(xin,anim_hdr);
  213.  
  214.     /*** Setup ACTION for IMAGE or CLIP */
  215.     act = ACT_Get_Action(anim_hdr,ACT_MAPPED);
  216.  
  217.     pic_size = gif_imagex * gif_imagey;
  218.  
  219.     pic_ptr = (xaUBYTE *) malloc( XA_PIC_SIZE(pic_size) );
  220.     if (pic_ptr==0) TheEnd1("GIF_Read_File: could malloc of image\n");
  221.  
  222.     pic_i=0;
  223.     GIF_Decompress(xin,pic_ptr);
  224.  
  225.     if (gif_anim_type == 0x01)
  226.     {
  227.       ACT_Setup_Mapped(act, pic_ptr, gif_chdr_now,
  228.             gifimage.left,gifimage.top,gif_imagex,gif_imagey,
  229.             gif_screenx,gif_screeny,xaTRUE,gif_anim_mask,
  230.             xaTRUE,xaFALSE,xaFALSE);
  231.     }
  232.     else
  233.     {
  234.        ACT_Setup_Mapped(act, pic_ptr, gif_chdr_now,
  235.             gifimage.left,gifimage.top,gif_imagex,gif_imagey,
  236.             gif_screenx,gif_screeny,xaFALSE,0,xaTRUE,xaFALSE,xaFALSE);
  237.     }
  238.     ACT_Add_CHDR_To_Action(act,gif_chdr_now);
  239.     GIF_Add_Frame(gif_anim_time,act);
  240.  
  241.     /*** read until "," ";" or feof */ 
  242.     do
  243.     {
  244.       i=xin->Read_U8(xin);
  245.       if ( (i<0) || (i == ';')) exit_flag = 1;
  246.       else if (i == '!') GIF_Read_Extension(xin);  /* extension */
  247.     } while( (i != ',') && (!exit_flag) );
  248.  
  249.   } /*** end of while images */
  250.   xin->Close_File(xin);
  251.  
  252.   anim_hdr->imagex = gif_max_imagex;
  253.   anim_hdr->imagey = gif_max_imagey;
  254.   anim_hdr->imagec = gif_max_imagec;
  255.   anim_hdr->imaged = gif_max_imaged;
  256.   *frame_cnt = gif_frame_cnt;
  257.   return(gif_frame_start);
  258. }
  259.  
  260. xaULONG GIF_Decompress(xin,pic)
  261. XA_INPUT *xin;
  262. char *pic;
  263. {
  264.   register xaULONG code,old;
  265.  
  266.   gif_bits = 0;
  267.   num_bits=0;
  268.   gif_block_size=0;
  269.      /* starting code size of LZW */
  270.   root_code_size=(xin->Read_U8(xin) & 0xff); 
  271.   DEBUG_LEVEL3 fprintf(stderr,"  root code size = %d\n",root_code_size);
  272.   GIF_Clear_Table();  /* clear decoding symbol table */
  273.  
  274.   code=GIF_Get_Code(xin);
  275.  
  276.   if (code==CLEAR) 
  277.   {
  278.     GIF_Clear_Table(); 
  279.     code=GIF_Get_Code(xin);
  280.   }
  281.   /* write code(or what it currently stands for) to file */
  282.   if (GIF_Send_Data(code,pic) == xaFALSE) return(xaFALSE);
  283.   old=code;
  284.   code=GIF_Get_Code(xin);
  285.   do
  286.   {
  287.     if (table[code].valid == 1)    /* if known code */
  288.     {
  289.        /* send it's associated string to file */
  290.       if (GIF_Send_Data(code,pic)==xaFALSE) return(xaFALSE);
  291.     /* get next table entry (nextab) */
  292.       if (GIF_Get_Next_Entry(xin) == xaFALSE) return(xaFALSE);
  293.       GIF_Add_To_Table(old,code,nextab);  /* add old+code to table */
  294.       old=code;
  295.     }
  296.     else      /* code doesn't exist */
  297.     {
  298.       GIF_Add_To_Table(old,old,code);   /* add old+old to table */
  299.       if (GIF_Send_Data(code,pic) == xaFALSE) return(xaFALSE);
  300.       old=code;
  301.     }
  302.     code=GIF_Get_Code(xin);
  303.     if (code==CLEAR)
  304.     { 
  305.       GIF_Clear_Table();
  306.       code=GIF_Get_Code(xin);
  307.       if (GIF_Send_Data(code,pic) == xaFALSE) return(xaFALSE);
  308.       old=code;
  309.       code=GIF_Get_Code(xin);
  310.     }
  311.   } while(code!=EOI);
  312.   return(xaTRUE);
  313. }
  314.  
  315. xaULONG GIF_Get_Next_Entry(xin)
  316. XA_INPUT *xin;
  317. {
  318.     /* table walk to empty spot */
  319.   while( (table[nextab].valid==1) && (nextab<MAXVAL) ) nextab++;
  320.  
  321.   /* Ran out of space??  Something's roached */
  322.   if (nextab>=MAXVAL)    
  323.   { if ( xin->At_EOF(xin) ) 
  324.     { fprintf(stderr,"truncated file\n"); return(xaFALSE); }
  325.     else 
  326.     { /* GIF_Clear_Table(); */
  327.       nextab = MAXVAL - 1;
  328.     }
  329.   }
  330.   if (nextab == INCSIZE)   /* go to next table size (and LZW code size ) */
  331.   {
  332.     DEBUG_LEVEL4 fprintf(stderr,"GetNext INCSIZE was %d ",nextab);
  333.     code_size++; INCSIZE=(INCSIZE*2)+1;
  334.     if (code_size>=12) code_size=12;
  335.     DEBUG_LEVEL4 fprintf(stderr,"<%d>",INCSIZE);
  336.   }
  337.   return(xaTRUE);
  338. }
  339.  
  340.  
  341. /*  body is associated string
  342.  *  next is code to add to that string to form associated string for
  343.  *  index
  344.  */     
  345. void GIF_Add_To_Table(body,next,index)
  346. register xaULONG body,next,index;
  347. {
  348.   if (index>MAXVAL)
  349.   { 
  350.     fprintf(stderr,"Error index=%d\n",index);
  351.   }
  352.   else
  353.   {
  354.     table[index].valid=1;
  355.     table[index].data=table[next].first;
  356.     table[index].first=table[body].first;
  357.     table[index].last=body;
  358.   }
  359. }
  360.  
  361. xaULONG GIF_Send_Data(index,pic)
  362. register xaLONG index;
  363. char *pic;
  364. {
  365.   register xaLONG i,j;
  366.   i=0;
  367.   do         /* table walk to retrieve string associated with index */
  368.   { 
  369.     gif_buff[i] = table[index].data; 
  370.     i++;
  371.     index = table[index].last;
  372.     if (i>MAXVAL)
  373.     { fprintf(stderr,"Error: Sending i=%d index=%d\n",i,index);
  374.       return(xaFALSE);
  375.     }
  376.   } while(index >= 0);
  377.  
  378.   /* now invert that string since we retreived it backwards */
  379.   i--;
  380.   for(j=i;j>=0;j--) 
  381.   {
  382.     if (pic_i < pic_size) pic[pic_i++] = gif_buff[j];
  383.     else 
  384.     {
  385.        DEBUG_LEVEL1 
  386.     fprintf(stderr,"GIF_Send: data beyond image size - ignored\n");
  387.     }
  388.     if (gif_lace_flag)
  389.     {
  390.       if ((pic_i % gif_imagex) == 0 )
  391.       { 
  392.         switch(gif_lace_flag)
  393.         {
  394.           case 1: pic_i += gif_imagex * 7; break; /* fill every 8th row */
  395.           case 2: pic_i += gif_imagex * 7; break; /* fill every 8th row */
  396.           case 3: pic_i += gif_imagex * 3; break; /* fill every 4th row */
  397.           case 4: pic_i += gif_imagex    ; break; /* fill every other row */
  398.         }
  399.       }
  400.       if (pic_i >= pic_size)
  401.       {
  402.         gif_lace_flag++;
  403.         switch(gif_lace_flag)
  404.         {
  405.           case 2: pic_i = gif_imagex << 2; break;  /* start at 4th row */
  406.           case 3: pic_i = gif_imagex << 1; break;  /* start at 2nd row */
  407.           case 4: pic_i = gif_imagex;      break;  /* start at 1st row */
  408.           default: gif_lace_flag = 0; pic_i = 0; break;
  409.         }
  410.       }
  411.     } /*** end of if gif_lace_flag */
  412.   } /*** end of code expansion */
  413.   return(xaTRUE);
  414. }
  415.  
  416.  
  417. /* 
  418.  * initialize string table 
  419.  */
  420. void GIF_Init_Table()       
  421. {
  422.   register xaLONG maxi,i;
  423.  
  424.   DEBUG_LEVEL3 fprintf(stderr,"  Initing Table...");
  425.   maxi=gif_ptwo[root_code_size];
  426.   for(i=0; i<maxi; i++)
  427.   {
  428.     table[i].data=i;   
  429.     table[i].first=i;
  430.     table[i].valid=1;  
  431.     table[i].last = -1;
  432.   }
  433.   CLEAR=maxi; 
  434.   EOI=maxi+1; 
  435.   nextab=maxi+2;
  436.   INCSIZE = (2*maxi)-1;
  437.   code_size=root_code_size+1;
  438.   DEBUG_LEVEL3 fprintf(stderr,"done\n");
  439. }
  440.  
  441.  
  442. /* 
  443.  * clear table 
  444.  */
  445. void GIF_Clear_Table()   
  446. {
  447.  register xaLONG i;
  448. DEBUG_LEVEL3 fprintf(stderr,"  Clearing Table...\n");
  449.  for(i=0;i<MAXVAL;i++) table[i].valid=0;
  450.  GIF_Init_Table();
  451. }
  452.  
  453.  
  454. /*CODE*/
  455. xaULONG GIF_Get_Code(xin) /* get code depending of current LZW code size */
  456. XA_INPUT *xin;
  457. {
  458.   xaULONG code;
  459.   register xaLONG tmp;
  460.  
  461.   while(num_bits < code_size)
  462.   {
  463.     /**** if at end of a block, start new block */
  464.     if (gif_block_size==0)
  465.     {
  466.       tmp = xin->Read_U8(xin);
  467.       if (tmp >= 0 ) gif_block_size=(xaULONG)(tmp);
  468.       else {fprintf(stderr,"GIF: No EOF before EOI\n"); return(EOI); }
  469.       DEBUG_LEVEL3 fprintf(stderr,"New Block size=%d\n",gif_block_size);
  470.     }
  471.  
  472.     tmp = xin->Read_U8(xin);   gif_block_size--;
  473.     if (tmp >= 0)
  474.     {
  475.       gif_bits |= ( ((xaULONG)(tmp) & (xaULONG)(0xff)) << num_bits );
  476.       DEBUG_LEVEL3 
  477.        fprintf(stderr,"tmp=%x bits=%x num_bits=%d\n",tmp,gif_bits,num_bits);
  478.  
  479.       num_bits+=8;
  480.     }
  481.     else {fprintf(stderr,"GIF: No EOF before EOI\n"); return(EOI); }
  482.   }
  483.  
  484.   code = gif_bits & gif_mask[code_size];
  485.   gif_bits >>= code_size;  
  486.   num_bits -= code_size;
  487.   DEBUG_LEVEL3 fprintf(stderr,"code=%x \n",code);
  488.  
  489.   if (code>MAXVAL)
  490.   {
  491.     fprintf(stderr,"\nError! in stream=%x \n",code);
  492.     fprintf(stderr,"CLEAR=%x INCSIZE=%x EOI=%x code_size=%x \n",
  493.                                            CLEAR,INCSIZE,EOI,code_size);
  494.     code=EOI;
  495.   }
  496.  
  497.   if (code==INCSIZE)
  498.   {
  499.     DEBUG_LEVEL3 fprintf(stderr,"  code=INCSIZE(%d)\n",INCSIZE);
  500.     if (code_size<12)
  501.     {
  502.       code_size++; INCSIZE=(INCSIZE*2)+1;
  503.     }
  504.     else DEBUG_LEVEL3 fprintf(stderr,"  <13?>\n");
  505.     DEBUG_LEVEL3 fprintf(stderr,"  new size = %d\n",code_size);
  506.   }
  507.   return(code);
  508. }
  509.  
  510.  
  511. /* 
  512.  * read GIF header 
  513.  */
  514. void GIF_Screen_Header(xin,anim_hdr)
  515. XA_INPUT *xin;
  516. XA_ANIM_HDR *anim_hdr;
  517. {
  518.  xaLONG temp,i;
  519.  
  520.  for(i=0;i<6;i++) xin->Read_U8(xin);    /* read and toss GIF87a or GIF89? */
  521.  
  522.  gif_screenx = gif_imagex = gifscrn.width  = xin->Read_LSB_U16(xin);
  523.  gif_screeny = gif_imagey = gifscrn.height = xin->Read_LSB_U16(xin);
  524.  
  525.  temp=xin->Read_U8(xin);
  526.  gifscrn.m       =  temp & 0x80;
  527.  gifscrn.cres    = (temp & 0x70) >> 4;
  528.  gifscrn.pixbits =  temp & 0x07;
  529.  gifscrn.bc  = xin->Read_U8(xin);
  530.  temp=xin->Read_U8(xin);
  531.  gif_imaged = gifscrn.pixbits + 1;
  532.  gif_imagec = gif_ptwo[gif_imaged];
  533.  
  534.  if (gif_imagex > gif_max_imagex) gif_max_imagex = gif_imagex;
  535.  if (gif_imagey > gif_max_imagey) gif_max_imagey = gif_imagey;
  536.  if (gif_imagec > gif_max_imagec) gif_max_imagec = gif_imagec;
  537.  if (gif_imaged > gif_max_imaged) gif_max_imaged = gif_imaged;
  538.  
  539.  if (xa_verbose == xaTRUE)
  540.   fprintf(stderr,"  Screen: %dx%dx%d m=%d cres=%d bkgnd=%d pix=%d\n",
  541.     gifscrn.width,gifscrn.height,gif_imagec,gifscrn.m,gifscrn.cres,
  542.     gifscrn.bc,gifscrn.pixbits);
  543.  
  544.  if (   (gif_imagec > x11_cmap_size) && (x11_cmap_flag == xaTRUE)
  545.      && (x11_display_type & XA_X11_CMAP) )
  546.  {
  547.   fprintf(stderr,"ERROR: Image has %d colors, display can handle %d\n",
  548.                     gif_imagec,x11_cmap_size);
  549.   TheEnd();
  550.  }
  551.  
  552.   if (gifscrn.m)
  553.   {
  554.      for(i=0; i < gif_imagec; i++)
  555.      {
  556.        gif_cmap[i].red   = xin->Read_U8(xin);
  557.        gif_cmap[i].green = xin->Read_U8(xin);
  558.        gif_cmap[i].blue  = xin->Read_U8(xin);
  559.      }
  560.  
  561.      gif_chdr_now = ACT_Get_CMAP(gif_cmap,gif_imagec,0,gif_imagec,0,8,8,8);
  562.   }
  563. } /* end of function */
  564.  
  565. /*
  566.  *
  567.  */
  568. void GIF_Image_Header(xin,anim_hdr)
  569. XA_INPUT *xin;
  570. XA_ANIM_HDR *anim_hdr;
  571. {
  572.  xaLONG temp,i;
  573.  
  574.  gifimage.left   = xin->Read_LSB_U16(xin);
  575.  gifimage.top    = xin->Read_LSB_U16(xin);
  576.  gifimage.width  = xin->Read_LSB_U16(xin);
  577.  gifimage.height = xin->Read_LSB_U16(xin);
  578.  temp=xin->Read_U8(xin);
  579.  gifimage.m        = temp & 0x80;
  580.  gifimage.i        = temp & 0x40;
  581.  if (gifimage.i) gif_lace_flag = 1;
  582.  else gif_lace_flag = 0;
  583.  gifimage.pixbits  = temp & 0x07;
  584.  gif_imaged = gifimage.pixbits + 1;
  585.  gif_imagex = gifimage.width;
  586.  gif_imagey = gifimage.height;
  587.  gif_imagec = gif_ptwo[gif_imaged];
  588.  
  589.  if (gif_imagex > gif_max_imagex) gif_max_imagex = gif_imagex;
  590.  if (gif_imagey > gif_max_imagey) gif_max_imagey = gif_imagey;
  591.  if (gif_imagec > gif_max_imagec) gif_max_imagec = gif_imagec;
  592.  if (gif_imaged > gif_max_imaged) gif_max_imaged = gif_imaged;
  593.  
  594.  DEBUG_LEVEL1
  595.  {
  596.   fprintf(stderr,"  Image: %dx%dx%d m=%d i=%d pix=%d resvd=%x",
  597.     gif_imagex,gif_imagey,gif_imagec,gifimage.m,gifimage.i,gifimage.pixbits,
  598.     gifimage.reserved );
  599.   fprintf(stderr,"Pos: %dx%d \n",gifimage.left,gifimage.top);
  600.  }
  601.  
  602.    /* Read in Image CMAP if Image has one */
  603.   if (gifimage.m)
  604.   {
  605.     for(i=0; i < gif_imagec; i++)
  606.     {
  607.       gif_cmap[i].red   = xin->Read_U8(xin);
  608.       gif_cmap[i].green = xin->Read_U8(xin);
  609.       gif_cmap[i].blue  = xin->Read_U8(xin);
  610.     }
  611.     gif_chdr_now = ACT_Get_CMAP(gif_cmap,gif_imagec,0,gif_imagec,0,8,8,8);
  612.   }
  613. }
  614.  
  615.  
  616. void
  617. GIF_Read_Extension(xin)
  618. XA_INPUT *xin;
  619. {
  620.   xaLONG block_size,code,tmp,i;
  621.  
  622.   code = xin->Read_U8(xin);
  623.   DEBUG_LEVEL2 fprintf(stderr,"  GIF Extension: Code = %x\n",code);
  624.   if ( (code == 0xfe) && (xa_verbose==xaTRUE) )
  625.     fprintf(stderr,"  GIF COMMENT EXTENSION BLOCK\n");
  626.   block_size = xin->Read_U8(xin);
  627.  
  628.   if ( (code == 0xf9) && (block_size == 4))
  629.   {
  630.     gif_anim_type = xin->Read_U8(xin);
  631.     i = xin->Read_LSB_U16(xin); if (i < 0) i = 1;
  632.     gif_anim_time = XA_GET_TIME(i * 10);
  633.     gif_anim_mask = xin->Read_U8(xin);
  634.     block_size = xin->Read_U8(xin);
  635.   }
  636.  
  637.   while(block_size > 0)
  638.   {
  639.     for(i=0; i<block_size; i++) 
  640.     {
  641.       tmp=xin->Read_U8(xin);
  642.       if ( (code == 0xfe) && (xa_verbose==xaTRUE) ) fprintf(stderr,"%c",(char)tmp);
  643.       if (code == 0xf9) DEBUG_LEVEL1 fprintf(stderr,"%x ",tmp);
  644.     }
  645.     block_size = xin->Read_U8(xin);
  646.     if (code == 0xf9) DEBUG_LEVEL1 fprintf(stderr,"\n");
  647.   }
  648. }
  649.  
  650.