🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: cn.bbs.comp.program
Article #2000

�� WATCOM C ��ʾ GIF ͼ��

#2000
From: ��������
Date: Fri, 20 Mar 1998 00:00
286 lines
7515 bytes
// Graphics Interchange Format File Processing Program
// This Program is to Unpack amd View GIF Image
// Copyright(c) Nov. 1997, Zhang Wei, USTC

#if !defined(__WATCOMC__) || !defined(__386__)
#error "This Program needs Watcom C/C++ 10.0 Compiler"
#endif

#include <io.h>
#include <i86.h>
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#define  FALSE  0
#define  TRUE   1
#define  ESCAPE 27

typedef  unsigned char  byte;
typedef  unsigned short word;
int   CLEARCODE = 256;
int   ENDIOCODE = 257;
byte  FIRSTCHAR = 0;
byte  stack[4096];
byte  first[4096];
byte  last[4096];
int   link[4096];
int   start[4] = {0,4,2,1};
int   incre[4] = {8,8,4,2};

int   index=1, count=0;
int   code=0, oldcode=0, nextcode=0;
unsigned rembits=0,remcnts=0,reqbits=0,bitslim=0;

int   orig_mode;
int   MAXX=320, MAXY=200;
char  *pv=(char *)(0x0A0000L);  //Video Pointer for FLAT Memory Mode
byte  rgb[768];
byte  outrow[4096];
byte  buffer[256];
int   fhandle;

void SetAllPalette(byte rgb[768])
{
   union REGS regs;
   struct SREGS segregs;
   segread(&segregs);
   regs.w.ax = 0x1012;
   regs.w.bx = 0x0000;
   regs.w.cx = 0x0100;
   regs.x.edx = FP_OFF( rgb );
   segregs.es = FP_SEG( rgb );
   int386x(0x10, &regs, &regs, &segregs);
}

//put a line at (x,y), n points, use color[i] at (x+i,y)
void PutLine(int x, int y, int n, byte color[])
{
   int offset=MAXX*y+x;
   for(int i=0; i<n; i++)
     *(pv+offset+i)=color[i];
}
void ClearDevice(byte color=0)
{
   _fmemset(pv,color,64*1024);
}

void InitGraph( int mode )
{
   union REGS regs;

   //Test if it is VGA Adapter.
   regs.w.ax = 0x1A00;
   int386(0x10, &regs, &regs);
   if(regs.h.al != 0x1A)
   {
     puts("This Program needs VGA Adapter\n");
     exit(1);
   }

   //get original video mode
   regs.w.ax = 0x0F00;
   int386(0x10, &regs, &regs);
   orig_mode = regs.h.al;

   //set new mode
   regs.h.ah = 0;
   regs.h.al = mode;
   int386(0x10, &regs, &regs);
}

void CloseGraph()
{
   union REGS regs;
   regs.h.ah = 0x00;
   regs.h.al = orig_mode;
   int386(0x10, &regs, &regs);
}

void InitCode()
{
   nextcode = CLEARCODE+2;
   reqbits  = FIRSTCHAR+1;
   bitslim  = 1<<reqbits;
   for(int i=0; i<CLEARCODE; i++)
   {
      first[i]= i;
      last[i] = i;
      link[i] =-1;
   }
   for(i=CLEARCODE; i<4096; i++)
      link[i] =-2;
}

int GetCode()
{
   unsigned value=0;
   if( remcnts < reqbits )
   {
     for(int i=0; i<2; i++)
     {
       if( index > count )
       {
         read(fhandle, buffer, 256);
         count = buffer[0];
         if( count != 255 )
             lseek(fhandle, count-255, SEEK_CUR);
         index = 1;
       }
       value = (buffer[index++]<<8*i)|value;
     }
     code = rembits|((value<<(32-reqbits+remcnts))>>(32-reqbits));
     rembits = (value)>>(reqbits-remcnts);
     remcnts = 16-(reqbits-remcnts);
   }
   else
   {
     code = ((rembits<<(32-reqbits)))>>(32-reqbits);
     rembits = rembits>>reqbits;
     remcnts = remcnts-reqbits;
   }
   return code;
}

void AddCode(int code)
{
   link[nextcode]  = oldcode;
   first[nextcode] = first[oldcode];
   if(link[code] == -2)
      last[nextcode] = first[oldcode];
   else
      last[nextcode] = first[code];
   if(++nextcode==bitslim && reqbits<12)
   {
      bitslim<<=1;
      reqbits++;
   }
}

int DisplayGIF(char *fname)
{
  index=1, count=0;
  rembits=0, remcnts=0;
  int  pass,interlaced;
  int  xx=0,yy=0,sx,sy,width,depth;

   static struct
   {
     char  Signature[3];    //must be "GIF"
     char  Version[3];      //must be "87a" or "89a"
     word  ScreenWidth;     //bit3==1 :color table sorted by frequency
     word  ScreenDepth;     //bit6--4 :colors=2^(bits+1)
     byte  GlobalFlag;      //bit7==1 :has global color
     byte  BackColor;       //bit2--0 :one pixel has bits+1
     byte  BitAspectRatio;  //must be 0 or (BitAspectRatio+15)/64
     byte  Palette[768];    //color table
     byte  Comma;           //if Comma==',' this is image data
     word  ImageStartx;     //image left
     word  ImageStarty;     //image top
     word  ImageWidth;      //image width
     word  ImageDepth;      //bit5==1 :color table sorted by frequency
     byte  LocalFlag;       //same as GlobalFlag,bit6==1 :line is interlaced
     byte  FirstChar;       //bit6==0 :sequential
   } gifhead;

    if((fhandle=open(fname,O_RDONLY|O_BINARY)) == -1) return FALSE;
    read(fhandle, &gifhead, 13);
    read(fhandle, gifhead.Palette, 3*(1<<(gifhead.GlobalFlag&0x7)+1));
    read(fhandle, &gifhead.Comma, 11);
    if(strncmp(gifhead.Signature,"GIF8",4)  //not a GIF file
       || !(gifhead.GlobalFlag & 0x80   )   //has no global color
       || ((gifhead.GlobalFlag&0x7) != 7)   //not a 256 colors file
       && ((gifhead.GlobalFlag&0x7) != 3)   //not a 16 colors file
       || (gifhead.Comma != ',')            //not image block
       || (gifhead.LocalFlag & 0x80))       //has local color table
    {
      close(fhandle);
      return FALSE;
    }
    width = gifhead.ImageWidth;
    depth = gifhead.ImageDepth;
    sx = MAXX/2-(width>>1); if(sx<0) sx=0;
    sy = MAXY/2-(depth>>1); if(sy<0) sy=0;
    interlaced = gifhead.LocalFlag & 0x40;

    for(int i=0; i<768; i++)
       gifhead.Palette[i] >>= 2;
    SetAllPalette( gifhead.Palette );
    FIRSTCHAR = gifhead.FirstChar;

    CLEARCODE = 1<<FIRSTCHAR;
    ENDIOCODE = CLEARCODE+1;
    reqbits = FIRSTCHAR+1;

    while( (code=GetCode()) != ENDIOCODE && yy <= depth )
    {
      if(code == CLEARCODE)
      {
         InitCode();
         code = GetCode();
      }
      else if( code < 4096 )
         AddCode( code );
      else
         return FALSE;

      oldcode = code;
      for(int i=0; code != -1 && i < 4096; i++)
      {
         stack[i] = last[code];
         code = link[code];
         if( code >= 4096 ) return FALSE;
      }
      for(i--; i>=0; i--)
      {
        if( xx < 1024 )
            outrow[xx] = stack[i];
        if( ++xx >= width )
        {
           if( yy < 200 )
              PutLine(sx, yy+sy, xx>MAXX? MAXX: xx, outrow);
           if( !interlaced ) //Image is Laid Line by Line
	      yy++;
	   else
	   {
              yy += incre[pass];
              if( yy >= depth ) yy = start[++pass];
	   }
	   xx = 0;
        }
      }
   }//End of While
   close(fhandle);
   return TRUE;
}

void main(int argc, char *argv[])
{
   int  key,done;
   char file[80];
   struct find_t find;

   if( argc != 2 )
      strcpy(file, "*.GIF");
   else
      strcpy(file, argv[1]);

   InitGraph( 0x13 );
   done = _dos_findfirst(file, _A_NORMAL, &find);
   while( !done )
   {
      ClearDevice();
      DisplayGIF( find.name );
      while( !kbhit() );
      key = getch();
      if( key == ESCAPE ) break;
      done = _dos_findnext( &find );
   }
   CloseGraph();
}

--
�� ��Դ: �й�ƴ�BBSվ [bbs.ustc.edu.cn]
Technical Details
Message-ID: <980320.yFqiY$PBBS@bbs.ustc.edu.cn>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII
X-Google-Thread: fc86e,9dbe58162d22fbea,start
X-Google-Attributes: gidfc86e,public
From: Smiling_Satan@bbs.ustc.edu.cn (��������)
Subject: �� WATCOM C ��ʾ GIF ͼ��
Date: 1998/03/20
Message-ID: <980320.yFqiY$PBBS@bbs.ustc.edu.cn>
X-Deja-AN: 335851835
Organization: �й�ƴ�BBSվ
Newsgroups: cn.bbs.comp.program