🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: cn.bbs.comp.program
1 messages
1 total messages Started by �������� Fri, 20 Mar 1998 00:00
�� WATCOM C ��ʾ GIF ͼ��
#2000
Author: ��������
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]
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads