home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / space / software / unix / xanim / xanim_gf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-04  |  14.0 KB  |  607 lines

  1.  
  2. /*
  3.  * xanim_gif.c
  4.  *
  5.  * Copyright (C) 1990,1991,1992 by Mark Podlipec. 
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified and redistributed
  9.  * without fee provided that this copyright notice is preserved 
  10.  * 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. #include "xanim.h"
  19. #include "xanim_gif.h"
  20.  
  21. void GIF_Read_File();
  22. void GIF_Decompress();
  23. void GIF_Get_Next_Entry();
  24. void GIF_Add_To_Table();
  25. void GIF_Send_Data();
  26. void GIF_Init_Table();
  27. void GIF_Clear_Table();
  28. ULONG GIF_Get_Code();
  29. void GIF_Screen_Header();
  30. void GIF_Image_Header();
  31. LONG UTIL_Get_LSB_Short();
  32. LONG Is_GIF_File();
  33. void GIF_Read_Extension();
  34.  
  35. void ACT_Setup_CMAP();
  36. void ACT_Get_Next_Action();
  37. void ACT_Setup_PIXMAP();
  38. void ACT_Setup_IMAGE();
  39. void ACT_Setup_CLIP();
  40. void UTIL_Create_Clip();
  41.  
  42.  
  43. #define MAXVAL  4100            /* maxval of lzw coding size */
  44. #define MAXVALP 4200
  45.  
  46.  
  47. #define GIF_CMAP_SIZE 256
  48. static GIF_Screen_Hdr gifscrn;
  49. static GIF_Image_Hdr gifimage;
  50. static ColorReg gifcolor[GIF_CMAP_SIZE];
  51. static GIF_Table table[MAXVALP];
  52.  
  53. static ULONG root_code_size,code_size,CLEAR,EOI,INCSIZE;
  54. static ULONG nextab;
  55. static ULONG gif_mask[16] = {1,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,0,0};
  56. static ULONG gif_ptwo[16] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,0,0};
  57. static UBYTE gif_buff[MAXVALP];
  58. static ULONG gif_block_size;
  59. static LONG gif_bits,num_bits;
  60. static gif_lace_flag;
  61.  
  62. static LONG gif_max_imagec,gif_max_imagex,gif_max_imagey;
  63.  
  64. static LONG pic_i,pic_size;
  65.  
  66. /* GIF89a variables */
  67. static LONG gif_anim_type;  /* from GIF89 f9 extension */
  68. static LONG gif_anim_time;  /* from GIF89 f9 extension */
  69. static LONG gif_anim_mask;  /* from GIF89 f9 extension */
  70.  
  71.  
  72. /*
  73.  *
  74.  */
  75. void GIF_Read_File(fname)
  76. char *fname;
  77. {
  78.   FILE *fp;
  79.   LONG i,exit_flag;
  80.   ACTION *act;
  81.  
  82.   if ( (fp=fopen(fname,"r"))==0)
  83.   { 
  84.     fprintf(stderr,"Can't open %s for reading.\n",fname); 
  85.     TheEnd();
  86.   }
  87.  
  88.   gif_anim_type = 0;
  89.   gif_anim_time = (jiffy_flag) ? jiffy_flag : MS_PER_60HZ;
  90.   gif_anim_mask = 0;
  91.  
  92.   GIF_Screen_Header(fp);
  93.  
  94.   /*** read until  ,  separator */
  95.   do
  96.   {
  97.     i=fgetc(fp);
  98.     if ( (i<0) && feof(fp))
  99.     {
  100.       fclose(fp);
  101.       TheEnd1("GIF_Read_Header: Unexpected EOF\n");
  102.     }
  103.     if (i == '!') GIF_Read_Extension(fp);  /* GIF extension */
  104.   } while(i != ',');
  105.  
  106.   exit_flag = 0;
  107.   while(!exit_flag)
  108.   {
  109.     UBYTE *pic_ptr;
  110.   
  111.     /* Read Image Header
  112.      */
  113.     GIF_Image_Header(fp);
  114.  
  115.     /*** Setup ACTION for IMAGE or CLIP */
  116.     ACT_Get_Next_Action(&act);
  117.  
  118.     pic_size = imagex * imagey;
  119.  
  120.     if (anm_map_flag == FALSE) 
  121.       pic_ptr = (UBYTE *) malloc(pic_size);
  122.     else
  123.       pic_ptr = (UBYTE *) malloc(pic_size * x11_bytes_pixel);
  124.     if (pic_ptr==0) TheEnd1("GIF_Read_File: could malloc of image\n");
  125.  
  126.     pic_i=0;
  127.     GIF_Decompress(fp,pic_ptr);
  128.  
  129.     /* NOTE: work in TRUE_COLOR and MONOCHROME support for CLIPS */
  130.     if (gif_anim_type == 0x01)
  131.     {
  132.       UBYTE *clip_ptr;
  133.       ULONG t_x,pix_size;
  134.  
  135.       /* 8 pixels per byte for clip mask */
  136.       t_x = imagex/8;
  137.       /* make room for pad on non byte sizes */
  138.       if (imagex%8) t_x++;
  139.  
  140.       clip_ptr = (UBYTE *) malloc( imagey * t_x );
  141.       if (clip_ptr==0) TheEnd1("GIF_Read_File: could malloc of image\n");
  142.  
  143.       if (anm_map_flag == TRUE) pix_size = x11_bytes_pixel;
  144.       else pix_size = 1;
  145.  
  146.       UTIL_Create_Clip(clip_ptr,pic_ptr,gifcolor[gif_anim_mask].map,
  147.         imagex,imagey,pix_size);
  148.  
  149.       ACT_Setup_Mapped(act, gif_anim_time,
  150.             pic_ptr, gifcolor, gif_max_imagec,
  151.             gifimage.left,gifimage.top,imagex,imagey,
  152.             anm_map_flag,clip_ptr);
  153.     }
  154.     else
  155.     {
  156.        ACT_Setup_Mapped(act, gif_anim_time,
  157.             pic_ptr, gifcolor, gif_max_imagec,
  158.             gifimage.left,gifimage.top,imagex,imagey,
  159.             anm_map_flag,0);
  160.     }
  161.  
  162.     /*** read until "," ";" or feof */ 
  163.     do
  164.     {
  165.       i=fgetc(fp);
  166.       if ( (i<0) || (i == ';')) exit_flag = 1;
  167.       else if (i == '!') GIF_Read_Extension(fp);  /* extension */
  168.     } while( (i != ',') && (!exit_flag) );
  169.  
  170.   } /*** end of while images */
  171.  
  172.   imagex = gif_max_imagex;
  173.   imagey = gif_max_imagey;
  174.   imagec = gif_max_imagec;
  175.   fclose(fp);
  176. }
  177.  
  178. void GIF_Decompress(fp,pic)
  179. FILE *fp;
  180. char *pic;
  181. {
  182.  register ULONG code,old;
  183.  
  184.  gif_bits = 0;
  185.  num_bits=0;
  186.  gif_block_size=0;
  187.      /* starting code size of LZW */
  188.  root_code_size=(fgetc(fp) & 0xff); 
  189.  DEBUG_LEVEL2 fprintf(stderr,"  root code size = %ld\n",root_code_size);
  190.  GIF_Clear_Table();  /* clear decoding symbol table */
  191.  
  192.  code=GIF_Get_Code(fp);
  193.  
  194.  if (code==CLEAR) 
  195.  {
  196.   GIF_Clear_Table(); 
  197.   code=GIF_Get_Code(fp);
  198.  }
  199.  /* write code(or what it currently stands for) to file */
  200.  GIF_Send_Data(code,pic);   
  201.  old=code;
  202.  code=GIF_Get_Code(fp);
  203.  do
  204.  {
  205.   if (table[code].valid==1)    /* if known code */
  206.   {
  207.        /* send it's associated string to file */
  208.     GIF_Send_Data(code,pic);
  209.     GIF_Get_Next_Entry(fp);       /* get next table entry (nextab) */
  210.     GIF_Add_To_Table(old,code,nextab);  /* add old+code to table */
  211.     old=code;
  212.   }
  213.   else      /* code doesn't exist */
  214.   {
  215.     GIF_Add_To_Table(old,old,code);   /* add old+old to table */
  216.     GIF_Send_Data(code,pic);
  217.     old=code;
  218.   }
  219.   code=GIF_Get_Code(fp);
  220.   if (code==CLEAR)
  221.   { 
  222.    GIF_Clear_Table();
  223.    code=GIF_Get_Code(fp);
  224.    GIF_Send_Data(code,pic);
  225.    old=code;
  226.    code=GIF_Get_Code(fp);
  227.   }
  228.  } while(code!=EOI);
  229. }
  230.  
  231. void GIF_Get_Next_Entry(fp)
  232. FILE *fp;
  233. {
  234.    /* table walk to empty spot */
  235.  while(  (table[nextab].valid==1)
  236.        &&(nextab<MAXVAL)
  237.       ) nextab++;
  238.  /* 
  239.   * Ran out of space??!?  Something's roached 
  240.   */
  241.  if (nextab>=MAXVAL)    
  242.  { 
  243.   fprintf(stderr,"Error: GetNext nextab=%ld\n",nextab);
  244.   fclose(fp);
  245.   TheEnd();
  246.  }
  247.  if (nextab==INCSIZE)   /* go to next table size (and LZW code size ) */
  248.  {
  249.    /* fprintf(stderr,"GetNext INCSIZE was %ld ",nextab); */
  250.    code_size++; INCSIZE=(INCSIZE*2)+1;
  251.    if (code_size>=12) code_size=12;
  252. /*   fprintf(stderr,"<%ld>",INCSIZE); */
  253.  }
  254.  
  255. }
  256. /*  body is associated string
  257.     next is code to add to that string to form associated string for
  258.     index
  259. */     
  260.  
  261. void GIF_Add_To_Table(body,next,index)
  262. register ULONG body,next,index;
  263. {
  264.  if (index>MAXVAL)
  265.  { 
  266.   fprintf(stderr,"Error index=%ld\n",index);
  267.  }
  268.  else
  269.  {
  270.   table[index].valid=1;
  271.   table[index].data=table[next].first;
  272.   table[index].first=table[body].first;
  273.   table[index].last=body;
  274.  }
  275. }
  276.  
  277. void GIF_Send_Data(index,pic)
  278. register LONG index;
  279. char *pic;
  280. {
  281.  register LONG i,j;
  282.  i=0;
  283.  do         /* table walk to retrieve string associated with index */
  284.  { 
  285.   gif_buff[i]=table[index].data; 
  286.   i++;
  287.   index=table[index].last;
  288.   if (i>MAXVAL)
  289.   { 
  290.    fprintf(stderr,"Error: Sending i=%ld index=%ld\n",i,index);
  291.    TheEnd();
  292.   }
  293.  } while(index>=0);
  294.  
  295.  /* now invert that string since we retreived it backwards */
  296.  i--;
  297.  for(j=i;j>=0;j--) 
  298.  {
  299.    if (anm_map_flag == FALSE) pic[pic_i++] = gif_buff[j];
  300.    else
  301.    {
  302.      if (x11_bytes_pixel == 4)
  303.         ((ULONG *)(pic))[pic_i++] = (ULONG)(gifcolor[ (gif_buff[j]) ].map);
  304.      else if (x11_bytes_pixel == 2)
  305.         ((USHORT *)(pic))[pic_i++] = (USHORT)(gifcolor[ (gif_buff[j]) ].map);
  306.      else
  307.         ((UBYTE *)(pic))[pic_i++] = (UBYTE)(gifcolor[ (gif_buff[j]) ].map);
  308.    }
  309.  
  310.    if (gif_lace_flag)
  311.    {
  312.      if ((pic_i % imagex) == 0 )
  313.      { 
  314.        switch(gif_lace_flag)
  315.        {
  316.          case 1: pic_i += imagex * 7; break; /* fill every 8th row */
  317.          case 2: pic_i += imagex * 7; break; /* fill every 8th row */
  318.          case 3: pic_i += imagex * 3; break; /* fill every 4th row */
  319.          case 4: pic_i += imagex    ; break; /* fill every other row */
  320.        }
  321.      }
  322.      if (pic_i >= pic_size)
  323.      {
  324.        gif_lace_flag++;
  325.        switch(gif_lace_flag)
  326.        {
  327.          case 2: pic_i = imagex << 2; break;  /* start at 4th row */
  328.          case 3: pic_i = imagex << 1; break;  /* start at 2nd row */
  329.          case 4: pic_i = imagex;      break;  /* start at 1st row */
  330.          default: gif_lace_flag = 0; pic_i = 0; break;
  331.        }
  332.      }
  333.    } /*** end of if gif_lace_flag */
  334.  } /*** end of code expansion */
  335. }
  336.  
  337.  
  338. /* 
  339.  * initialize string table 
  340.  */
  341. void GIF_Init_Table()       
  342. {
  343.  register LONG maxi,i;
  344.  
  345. DEBUG_LEVEL2 fprintf(stderr,"  Initing Table...");
  346.  maxi=gif_ptwo[root_code_size];
  347.  for(i=0; i<maxi; i++)
  348.  {
  349.   table[i].data=i;   
  350.   table[i].first=i;
  351.   table[i].valid=1;  
  352.   table[i].last = -1;
  353.  }
  354.  CLEAR=maxi; 
  355.  EOI=maxi+1; 
  356.  nextab=maxi+2;
  357.  INCSIZE = (2*maxi)-1;
  358.  code_size=root_code_size+1;
  359. DEBUG_LEVEL2 fprintf(stderr,"done\n");
  360. }
  361.  
  362.  
  363. /* 
  364.  * clear table 
  365.  */
  366. void GIF_Clear_Table()   
  367. {
  368.  register LONG i;
  369. DEBUG_LEVEL2 fprintf(stderr,"  Clearing Table...\n");
  370.  for(i=0;i<MAXVAL;i++) table[i].valid=0;
  371.  GIF_Init_Table();
  372. }
  373.  
  374.  
  375. /*CODE*/
  376. ULONG GIF_Get_Code(fp) /* get code depending of current LZW code size */
  377. FILE *fp;
  378. {
  379.  ULONG code;
  380.  register LONG tmp;
  381.  
  382.  while(num_bits < code_size)
  383.  {
  384.   /**** if at end of a block, start new block */
  385.   if (gif_block_size==0)
  386.   {
  387.    tmp = fgetc(fp);
  388.    if (tmp >= 0 ) gif_block_size=(ULONG)(tmp);
  389.    else TheEnd1("EOF in data stream\n");
  390.    DEBUG_LEVEL2 fprintf(stderr,"New Block size=%ld\n",gif_block_size);
  391.   }
  392.  
  393.   tmp = fgetc(fp);   gif_block_size--;
  394.   if (tmp >= 0)
  395.   {
  396. /*POD added ULONG on 0xff */
  397.    gif_bits |= ( ((ULONG)(tmp) & (ULONG)(0xff)) << num_bits );
  398.    DEBUG_LEVEL2 
  399.     fprintf(stderr,"tmp=%lx bits=%lx num_bits=%ld\n",tmp,gif_bits,num_bits);
  400.  
  401.    num_bits+=8;
  402.   }
  403.   else TheEnd1("EOF in data stream\n");
  404.  }
  405.  
  406.  code = gif_bits & gif_mask[code_size];
  407.  gif_bits >>= code_size;  
  408.  num_bits -= code_size;
  409.  DEBUG_LEVEL2 fprintf(stderr,"code=%lx \n",code);
  410.  
  411.  
  412.  if (code>MAXVAL)
  413.  {
  414.   fprintf(stderr,"\nError! in stream=%lx \n",code);
  415.   fprintf(stderr,"CLEAR=%lx INCSIZE=%lx EOI=%lx code_size=%lx \n",
  416.                                            CLEAR,INCSIZE,EOI,code_size);
  417.   code=EOI;
  418.  }
  419.  
  420.  if (code==INCSIZE)
  421.  {
  422.   DEBUG_LEVEL2 fprintf(stderr,"  code=INCSIZE(%ld)\n",INCSIZE);
  423.   if (code_size<12)
  424.   {
  425.    code_size++; INCSIZE=(INCSIZE*2)+1;
  426.   }
  427.   else DEBUG_LEVEL2 fprintf(stderr,"  <13?>\n");
  428.   DEBUG_LEVEL2 fprintf(stderr,"  new size = %ld\n",code_size);
  429.  }
  430.  
  431.  return(code);
  432. }
  433.  
  434.  
  435. /* 
  436.  * read GIF header 
  437.  */
  438. void GIF_Screen_Header(fp)
  439. FILE *fp;
  440. {
  441.  LONG temp,i;
  442.  
  443.  for(i=0;i<6;i++) fgetc(fp);    /* read and toss GIF87a or GIF89? */
  444.  
  445.  gifscrn.width  = UTIL_Get_LSB_Short(fp);
  446.  gifscrn.height = UTIL_Get_LSB_Short(fp);
  447.  imagex = gifscrn.width;
  448.  imagey = gifscrn.height;
  449.  gif_max_imagex = gifscrn.width;
  450.  gif_max_imagey = gifscrn.height;
  451.  
  452.  temp=fgetc(fp);
  453.  gifscrn.m       =  temp & 0x80;
  454.  gifscrn.cres    = (temp & 0x70) >> 4;
  455.  gifscrn.pixbits =  temp & 0x07;
  456.  gifscrn.bc  = fgetc(fp);
  457.  temp=fgetc(fp);
  458.  imagec=gif_ptwo[(1+gifscrn.pixbits)];
  459.  gif_max_imagec = imagec;
  460.  
  461.  if (verbose == TRUE)
  462.   fprintf(stderr,"  Screen: %ldx%ldx%ld m=%ld cres=%ld bkgnd=%ld pix=%ld\n",
  463.     gifscrn.width,gifscrn.height,imagec,gifscrn.m,gifscrn.cres,
  464.     gifscrn.bc,gifscrn.pixbits);
  465.  
  466.  if (   (imagec > x11_cmap_size) && (x11_cmap_flag == TRUE)
  467.      && (x11_display_type == PSEUDO_COLOR) )
  468.  {
  469.   fprintf(stderr,"ERROR: Image has %ld colors, display can handle %ld\n",
  470.                     imagec,x11_cmap_size);
  471.   TheEnd();
  472.  }
  473.  
  474.   if (gifscrn.m)
  475.   {
  476.     ACTION *act;
  477.     ULONG off;
  478.  
  479.      for(i=0; i < imagec; i++)
  480.      {
  481.        gifcolor[i].red   = fgetc(fp);
  482.        gifcolor[i].green = fgetc(fp);
  483.        gifcolor[i].blue  = fgetc(fp);
  484.      } /* end of for i */
  485.  
  486.      /* Setup ACTION for CMAP */
  487.      ACT_Get_Next_Action(&act);
  488.      ACT_Setup_CMAP(gifcolor,imagec,&off,CMAP_ALLOW_REMAP);
  489.  
  490.   } /* end of image color map */
  491.  
  492. } /* end of function */
  493.  
  494. void GIF_Image_Header(fp)
  495. FILE *fp;
  496. {
  497.  LONG temp,tnum,i;
  498.  
  499.  gifimage.left   = UTIL_Get_LSB_Short(fp);
  500.  gifimage.top    = UTIL_Get_LSB_Short(fp);
  501.  gifimage.width  = UTIL_Get_LSB_Short(fp);
  502.  gifimage.height = UTIL_Get_LSB_Short(fp);
  503.  temp=fgetc(fp);
  504.  gifimage.m        = temp & 0x80;
  505.  gifimage.i        = temp & 0x40;
  506.  if (gifimage.i) gif_lace_flag = 1;
  507.  else gif_lace_flag = 0;
  508.  gifimage.pixbits  = temp & 0x07;
  509.  imagex=gifimage.width;
  510.  imagey=gifimage.height;
  511.  if (imagex > gif_max_imagex) gif_max_imagex = imagex;
  512.  if (imagey > gif_max_imagey) gif_max_imagey = imagey;
  513.  tnum=gif_ptwo[(1+gifimage.pixbits)];
  514.  if (tnum > gif_max_imagec) gif_max_imagec = tnum;
  515.  imagec = tnum;
  516.  if (debug >= 1)
  517.  {
  518.   fprintf(stderr,"  Image: %ldx%ldx%ld m=%ld i=%ld pix=%ld ",
  519.     imagex,imagey,tnum,gifimage.m,gifimage.i,gifimage.pixbits,
  520.     gifimage.reserved );
  521.   fprintf(stderr,"Pos: %ldx%ld \n",gifimage.left,gifimage.top);
  522.  }
  523.  
  524.  
  525.   if (gifimage.m)
  526.   {
  527.     ACTION *act;
  528.     LONG off;
  529.  
  530.       /* Read in Image CMAP if Image has one
  531.        */
  532.       for(i=0; i < imagec; i++)
  533.       {
  534.         gifcolor[i].red   = fgetc(fp);
  535.         gifcolor[i].green = fgetc(fp);
  536.         gifcolor[i].blue  = fgetc(fp);
  537.       }
  538.  
  539.       /* Setup ACTION for CMAP 
  540.        */
  541.       ACT_Get_Next_Action(&act);
  542.       ACT_Setup_CMAP(gifcolor,imagec,&off,CMAP_ALLOW_REMAP);
  543.  
  544.   } /* end of Image has cmap */
  545. }
  546.  
  547. /*
  548.  *
  549.  */
  550. LONG Is_GIF_File(filename)
  551. char *filename;
  552. {
  553.  FILE *fp;
  554.  ULONG firstword;
  555.  
  556.  if ( (fp=fopen(filename,"r")) == 0)
  557.  { 
  558.   fprintf(stderr,"can't open %s\n",filename); 
  559.   TheEnd();
  560.  }
  561.  /* by reading bytes we can ignore big/little endian problems */
  562.  firstword  = (ULONG)(fgetc(fp) & 0xff) << 24;
  563.  firstword |= (ULONG)(fgetc(fp) & 0xff) << 16;
  564.  firstword |= (ULONG)(fgetc(fp) & 0xff) <<  8;
  565.  firstword |= (ULONG)(fgetc(fp) & 0xff);
  566.  
  567.  fclose(fp);
  568.  
  569.  if (firstword == 0x47494638) return((LONG)TRUE);
  570.  return((LONG)FALSE);
  571. }
  572.  
  573. void
  574. GIF_Read_Extension(fp)
  575. FILE *fp;
  576. {
  577.  int block_size,code,tmp,i;
  578.  
  579.  code = fgetc(fp);
  580.  if (debug >= 1) fprintf(stderr,"  GIF Extension: Code = %lx\n",code);
  581.  if ( (code == 0xfe) && (verbose==TRUE) )
  582.     fprintf(stderr,"  GIF COMMENT EXTENSION BLOCK\n");
  583.  block_size = fgetc(fp);
  584.  
  585.  if ( (code == 0xf9) && (block_size == 4))
  586.  {
  587.   gif_anim_type = fgetc(fp);
  588.   i = UTIL_Get_LSB_Short(fp);
  589.   if (jiffy_flag == 0) gif_anim_time = i * 10;
  590.   gif_anim_mask = fgetc(fp);
  591.   block_size = fgetc(fp);
  592.  }
  593.  
  594.  while(block_size > 0)
  595.  {
  596.   for(i=0; i<block_size; i++) 
  597.   {
  598.    tmp=fgetc(fp);
  599.    if ( (code == 0xfe) && (verbose==TRUE) ) fprintf(stderr,"%c",tmp);
  600.    if ( (code == 0xf9) && (debug >= 1) ) fprintf(stderr,"%lx ",tmp);
  601.   }
  602.   block_size = fgetc(fp);
  603.   if ( (code == 0xf9) && (debug >= 1) ) fprintf(stderr,"\n",tmp);
  604.  }
  605. }
  606.  
  607.