Thread View: cn.bbs.comp.program
1 messages
1 total messages
Started by ��������
Fri, 20 Mar 1998 00:00
�� WATCOM C ��ʾ GIF ͼ��
Author: ��������
Date: Fri, 20 Mar 1998 00:00
Date: Fri, 20 Mar 1998 00:00
286 lines
7515 bytes
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, ®s, ®s, &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, ®s, ®s);
if(regs.h.al != 0x1A)
{
puts("This Program needs VGA Adapter\n");
exit(1);
}
//get original video mode
regs.w.ax = 0x0F00;
int386(0x10, ®s, ®s);
orig_mode = regs.h.al;
//set new mode
regs.h.ah = 0;
regs.h.al = mode;
int386(0x10, ®s, ®s);
}
void CloseGraph()
{
union REGS regs;
regs.h.ah = 0x00;
regs.h.al = orig_mode;
int386(0x10, ®s, ®s);
}
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