home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / GIFPASSE.ZIP / DGIF.PAS next >
Encoding:
Pascal/Delphi Source File  |  1989-02-27  |  13.6 KB  |  478 lines

  1. unit dgif;
  2.  
  3.        { Steve Enns Feb.26 1989
  4.          Copyright 1989 Steve Enns   All rights reserved.
  5.          Synergrafix - Graphical and Numerical Software
  6.          2425 Haultain Ave. Saskatoon, Sask. Canada  S7J 1R2
  7.  
  8.          GIF DEcoding for BGI graphics
  9.          Based on GIFSLOW.PAS by Jim Griebel
  10.          Must be in graphics mode before call
  11.          Uses EGA palette.
  12.  
  13.          This software is provided for unlimited use and
  14.          distribution EXCEPT for the following conditions:
  15.            - No fee is to be charged for the use or distribution
  16.              of this software, including any works which include
  17.              the source code or compiled form of this software.
  18.            - Any derived software or software which uses the source
  19.              code or compiled versions of this software must include
  20.              the source code of the derived software, and this notice.
  21.            - This software is to be distributed in the original
  22.              archived form, with the SAME name, GIFPASSE,
  23.              i.e. GIFPASSE.ZIP, GIFPASSE.ARC.
  24.  
  25.          This software is provided without warranty of any kind,
  26.          express or implied. YOU, the user assume complete
  27.          responsibility for any and all incidental or consequential
  28.          damages arising out of the use of this program. Use
  29.          at your own risk.
  30.  
  31.          This license is intended to encourage the distribution of
  32.          programs which include source code!
  33.  
  34.          'GIF' and 'Graphics Interchange Format' are trademarks
  35.           of Compuserve, Inc., an H&R Block Company. }
  36.  
  37. interface
  38.  
  39. Function degif(filename :string; { Name of GIF file to decode }
  40.                x,y      :integer { Location for upper left corner of image }
  41.               ):boolean;         { Returns FALSE on failure }
  42.  
  43. implementation
  44.  
  45. {$R-,S-}                     { Speed }
  46.  
  47. uses graph, { PUTPIXEL }
  48.      crt;   { KEYPRESSED, READKEY }
  49.  
  50. Function degif(filename:string;x,y:integer):boolean;
  51.  
  52. const maxcodes   :array[0..9] of word=(4,8,16,$20,$40,$80,$100,$200,$400,$800);
  53.       codemask   :array[1..8] of byte=(1,3,7,15,31,63,127,255);
  54.       powersof2  :array[0..8] of word=(1,2,4,8,16,32,64,128,256);
  55.       masks      :array[0..9] of Integer=(7,15,$1f,$3f,$7f,$ff,$1ff,$3ff,$7ff,$fff);
  56.       rastersize :word=64000;
  57.  
  58. type rasterarray=array[0..63999] of byte;
  59.      rasterp=^rasterarray;
  60.  
  61. var giffile  :file of rasterarray;{The input file}
  62.     gifstuff :rasterp;  {The heap array to hold it, raw}
  63.     raster   :rasterp;  {The raster data stream, unblocked}
  64.     raster2  :rasterp;  {more raster data stream if needed}
  65.     byteoffset,         {computed byte position in rasTEr array}
  66.     bitoffset :longint; {bit offset of next code in rasTEr array}
  67.  
  68.     width,      {read from gif header, image width}
  69.     height,     { ditto, image height}
  70.     leftofs,    { ditto, image offset from left}
  71.     topofs,     { ditto, image offset from top}
  72.     rwidth,     { ditto, raster width}
  73.     rheight,    { ditto, raster height}
  74.     clearcode,  {gif clear code}
  75.     eofcode,    {gif end-of-information code}
  76.     outcount,   {decompressor output 'stack count'}
  77.     maxcode,    {decompressor limiting value for current code size}
  78.     code,       {Value returned by readcode}
  79.     curcode,    {decompressor variable}
  80.     oldcode,    {decompressor variable}
  81.     incode,     {decompressor variable}
  82.     firstfree,  {first free code, generated per gif spec}
  83.     freecode,   {decompressor, next free slot in hash table}
  84.     gifptr,     {array pointers used during file read}
  85.     rasterptr,
  86.     xc,yc,      {screen X and Y coords of current pixel}
  87.     pindex,     {Index into screen save array}
  88.     readmask,   {code and mask for current code size}
  89.     i       :word;
  90.  
  91.     interlace,  {True if interlaced image}
  92.     nextraster, {True if file > 64000 bytes}
  93.     colormap :boolean; {True if colormap present}
  94.  
  95.     ch      :char;
  96.     a,              {Utility}
  97.     resolution,     {resolution, read from gif header}
  98.     bitsperpixel,   {bits per pixel, read from gif header}
  99.     background,     {background color, read from gif header}
  100.     colormapsize,   {Length of color map, from gif header}
  101.     codesize,       {code size, read from gif header}
  102.     initcodesize,   {starting code size, used during clear}
  103.     finchar,        {decompressor variable}
  104.     pass,           {Used by video output if interlaced pic}
  105.     bitmask,        {and mask for data size}
  106.     r,g,b      :byte;
  107.     filestring :string[80];
  108.     ioerror    :boolean;
  109.  
  110.     {The hash table used by the decompressor}
  111.     prefix  :array[0..4095] of word;
  112.     suffix  :array[0..4095] of byte;
  113.  
  114.     {an output array used by the decompressor}
  115.     outcode :array[0..1024] of byte;
  116.  
  117.     {The color map, read from the gif header}
  118.     red,green,blue  :array[0..255] of byte;
  119.  
  120.     {The ega palette, derived from the color map}
  121.     palette         :array[0..255] of byte;
  122.  
  123. Procedure detcolor(var pvalue:byte;mapvalue:byte);
  124. var local :byte;
  125. begin
  126.    pvalue:=mapvalue div 64;
  127.    if pvalue=1 then pvalue:=2 else
  128.    if pvalue=2 then pvalue:=1
  129. end;
  130.  
  131. Function allocmem(var p:rasterp):boolean;
  132. var asize :longint;
  133. begin
  134.    asize:=maxavail;
  135.    if asize<rastersize then
  136.       allocmem:=false
  137.    else
  138.    begin
  139.       getmem(p,rastersize);
  140.       allocmem:=true
  141.    end
  142. end;
  143.  
  144. Function getbyte:byte;
  145. begin
  146.    if gifptr=rastersize then exit;
  147.    getbyte:=gifstuff^[gifptr];
  148.    inc(gifptr)
  149. end;
  150.  
  151. Function getword:word;
  152. var a :byte;
  153. begin
  154.    a:=getbyte;
  155.    getword:=a+getbyte shl 8
  156. end;
  157.  
  158. Function readraster:boolean;
  159. var blocklength :byte;
  160.     i,ior       :integer;
  161. begin
  162.    readraster:=true;
  163.    rasterptr:=0;
  164.    repeat
  165.       blocklength:=getbyte;
  166.       for i:=0 to blocklength-1 do
  167.       begin
  168.          if gifptr=rastersize then
  169.          begin
  170.             {$I-}
  171.             read(giffile,gifstuff^);
  172.             {$I+}
  173.             ior:=ioresult;
  174.             gifptr:=0
  175.          end;
  176.          if not nextraster then
  177.             raster^[rasterptr]:=getbyte
  178.          else
  179.             raster2^[rasterptr]:=getbyte;
  180.          inc(rasterptr);
  181.          if rasterptr=rastersize then
  182.          begin
  183.             nextraster:=True;
  184.             rasterptr:=0;
  185.             if not allocmem(raster2) then
  186.                readraster:=false
  187.          end
  188.       end
  189.    until blocklength=0
  190. end;
  191.  
  192. Procedure readcode;
  193. var rawcode :longint;
  194.     a       :word;
  195. begin
  196.    byteoffset:=bitoffset shr 3 {div 8};
  197.  
  198.    {pick up our 24-bit chunk}
  199.  
  200.    a:=raster^[byteoffset]+(raster^[byteoffset+1] shl 8);
  201.  
  202.    if codesize>=8 then
  203.       rawcode:=a+(raster^[byteoffset+2]*65536)
  204.    else
  205.       rawcode:=a;
  206.  
  207.    {  doing the above calculation as a single statement, i.e.
  208.  
  209.    rawcode:=raster^[byteoffset]+(256*raster^[byteoffset+1])+
  210.            (65536*raster[byteoffset+2])
  211.    sometimes returns incorrect results. This may or may not be a bug.}
  212.  
  213.  
  214.    rawcode:=rawcode shr(bitoffset mod 8);
  215.    code:=rawcode and readmask;
  216.  
  217.    {cope with overflow of the first raster array}
  218.  
  219.    if (nextraster) and (byteoffset>=63000) then
  220.    begin
  221.       move(raster^[byteoffset],raster^[0],rastersize-byteoffset);
  222.       move(raster2^[0],raster^[rastersize-byteoffset],63000);
  223.       bitoffset:=bitoffset mod 8;
  224.       freemem(raster2,rastersize)
  225.    end;
  226.  
  227.    bitoffset:=bitoffset+codesize
  228.  
  229. end;
  230.  
  231. Procedure doclear;
  232. begin
  233.    codesize:=Initcodesize;
  234.    maxcode:=maxcodes[codesize-2];
  235.    freecode:=firstfree;
  236.    readmask:=masks[codesize-3]
  237. end;
  238.  
  239. Procedure addtopixel(index:byte);
  240. begin
  241.  
  242. {   putpixel(xc,yc,not index);
  243. }
  244.    putpixel(xc,yc,index);
  245.  
  246.    inc(xc);
  247.    if xc=width+x then
  248.    begin
  249.       xc:=x;
  250.       if not interlace then
  251.          inc(yc)
  252.       else
  253.       case pass of
  254.          0: begin
  255.                inc(yc,8);
  256.                if yc>=height+y then
  257.                begin
  258.                   inc(pass);
  259.                   yc:=4+y
  260.                end
  261.             end;
  262.          1: begin
  263.                inc(yc,8);
  264.                if yc>=height+y then
  265.                begin
  266.                   inc(pass);
  267.                   yc:=2+y
  268.                end
  269.             end;
  270.          2: begin
  271.                inc(yc,4);
  272.                if yc>=height+y then
  273.                begin
  274.                   inc(pass);
  275.                   yc:=1+y
  276.                end
  277.             end;
  278.          3: inc(yc,2)
  279.       end
  280.    end
  281. end;
  282.  
  283. begin
  284.    degif:=true;
  285.  
  286.    xc:=x;          {X and Y screen coords back to home}
  287.    yc:=y;
  288.    pass:=0;        {interlace pass counter back to 0}
  289.    bitoffset:=0;   {point to the start of the raster data stream}
  290.    gifptr:=0;      {mock file read pointer back to 0}
  291.  
  292.    nextraster:=false;    {over 64000 flag off}
  293.  
  294.    if (not allocmem(raster)) or (not allocmem(gifstuff)) then
  295.       degif:=false
  296.    else
  297.    begin
  298.  
  299.       {$I-}
  300.       assign(giffile,filename);
  301.       reset(giffile);
  302.       {$I+}
  303.  
  304.       degif:=(ioresult=0);
  305.  
  306.       {$I-}
  307.       read(giffile,gifstuff^);
  308.       {$I+}
  309.  
  310.       ioerror:=(ioresult<>0);
  311.  
  312.       if ioresult=0 then
  313.       begin
  314.  
  315.          filestring:='';
  316.          for i:=1 to 6 do
  317.             filestring:=filestring+chr(getbyte);
  318.  
  319.          if filestring<>'GIF87a' then
  320.             degif:=false
  321.          else
  322.          begin
  323.  
  324.             { get variables from the gif screen descriptor}
  325.  
  326.             rwidth:=getword;         {The raster width and height}
  327.             rheight:=getword;
  328.  
  329.             {get the packed byte immediately following and decode it}
  330.  
  331.             b:=getbyte;
  332.             if b and $80=$80 then
  333.                colormap:=true
  334.             else
  335.                colormap:=false;
  336.             resolution:=b and $70 shr 5 +1;
  337.             bitsperpixel:=b and 7+1;
  338.             if bitsperpixel=1 then
  339.                i:=2
  340.             else
  341.                i:=1 shl bitsperpixel;
  342.  
  343.             bitmask:=codemask[bitsperpixel];
  344.             background:=getbyte;
  345.             b:=getbyte;         {skip byte of 0's}
  346.  
  347.             colormapsize:=(1 shl bitsperpixel)-1;
  348.  
  349.             if colormap then
  350.             begin
  351.                for i:=0 to colormapsize{-1} do
  352.                begin
  353.                   red[i]:=getbyte;
  354.                   green[i]:=getbyte;
  355.                   blue[i]:=getbyte;
  356.                   detcolor(r,red[i]);
  357.                   detcolor(g,green[i]);
  358.                   detcolor(b,blue[i]);
  359.                   palette[I]:=b and 1+(2*(g and 1))+(4*(r and 1))+(8*(b div 2))+(16*(G div 2))+(32*(r div 2))
  360.                end;
  361.                palette[16]:=background
  362.             end;
  363.  
  364.             {now read in values from the image descriptor}
  365.  
  366.             b:=getbyte;  {skip image seperator}
  367.             leftofs:=getword;
  368.             topofs:=getword;
  369.             width:=getword;
  370.             height:=getword;
  371.             a:=getbyte;
  372.             if a and $40=$40 then
  373.                interlace:=true
  374.             else
  375.                interlace:=false;
  376.  
  377.             codesize:=getbyte;
  378.  
  379.             {compute decompressor constant values, based on the code size}
  380.  
  381.             clearcode:=powersof2[codesize];
  382.             eofcode:=clearcode+1;
  383.             firstfree:=clearcode+2;
  384.             freecode:=firstfree;
  385.  
  386.             inc(codesize);
  387.             initcodesize:=codesize;
  388.             maxcode:=maxcodes[codesize-2];
  389.             readmask:=masks[codesize-3];
  390.  
  391.             if not readraster then
  392.             begin
  393.                degif:=false;
  394.                exit
  395.             end;
  396.  
  397.             freemem(gifstuff,rastersize);
  398.             outcount:=0;
  399.  
  400.             repeat
  401.  
  402.                {get the next code from the raster array}
  403.  
  404.                readcode;
  405.  
  406.                if code<>eofcode then
  407.                begin
  408.                   if code=clearcode then
  409.                   begin
  410.                      doclear;
  411.                      readcode;
  412.                      curcode:=code;
  413.                      oldcode:=code;
  414.                      finchar:=code and bitmask;
  415.                      addtopixel(finchar);
  416.                   end else
  417.                   begin
  418.                      curcode:=code;
  419.                      Incode:=code;
  420.                      if code>=freecode then
  421.                      begin
  422.                         curcode:=oldcode;
  423.                         outcode[outcount]:=finchar;
  424.                         inc(outcount)
  425.                      end;
  426.  
  427.                      if curcode>bitmask then
  428.                      repeat
  429.                         outcode[outcount]:=suffix[curcode];
  430.                         inc(outcount);
  431.                         curcode:=prefix[curcode];
  432.                      until curcode<=bitmask;
  433.  
  434.                      finchar:=curcode and bitmask;
  435.                      outcode[outcount]:=finchar;
  436.                      inc(outcount);
  437.  
  438.                      for i:=outcount-1 downto 0 do
  439.                         addtopixel(outcode[i]);
  440.  
  441.                      outcount:=0;
  442.  
  443.                      prefix[freecode]:=oldcode;
  444.                      suffix[freecode]:=finchar;
  445.                      oldcode:=incode;
  446.  
  447.                      inc(freecode);
  448.                      if freecode>=maxcode then
  449.                      begin
  450.                         if codesize<12 then
  451.                         begin
  452.                            inc(codesize);
  453.                            inc(maxcode,maxcode);
  454.                            readmask:=masks[codesize-3]
  455.                         end
  456.                      end
  457.                   end;
  458.  
  459.                   if keypressed then
  460.                      if readkey=#27 then
  461.                         exit
  462.  
  463.                end
  464.             until code=eofcode
  465.  
  466.          end
  467.       end else
  468.          degif:=false;
  469.  
  470.       close(giffile);
  471.       freemem(raster,rastersize)
  472.  
  473.    end
  474.  
  475. end;
  476.  
  477. begin
  478. end.