This following source code is about to display GIF87a Files in
DOS-enviroment, but something crazy happenned! It doesn't display the
image correctly.?
Could you pleased check and point out the mistake?
Here is the source code.
/*************************************************************************
READING GIF87a
DISPLAY IN 320x200x256 VGA MODE
**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <mem.h>
#include <string.h>
#include <conio.h>
#define VIDEO_INT 0x10 /* ngat video cua Bios. */
#define SET_MODE 0x00 /* Ham cua BIOS de dat che do man hinh. */
#define VGA_256_COLOR_MODE 0x13 /* ngat dung de dat che do 256 mau. */
#define TEXT_MODE 0x03 /* su dung de dat che do ky tu 80x25 */
#define PALETTE_INDEX 0x03c8
#define PALETTE_DATA 0x03c9
#define INPUT_STATUS 0x03da
#define VRETRACE 0x08
#define SCREEN_WIDTH 320 /* do rong man hinh trong che do 0x13 */
#define SCREEN_HEIGHT 200 /* chieu cao man hinh trong che do 0x13 */
#define NUM_COLORS 256 /* so mau trong che do 0x13 */
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
byte *VGA=(byte *)0xA0000000L; /* con tro tro thang vao bo nho man hinh */
typedef struct _IMAGE /* cau truc du lieu hinh anh */
{
word width;
word height;
byte palette[256*3];
byte *data;
} IMAGE;
ReadPcxLine(char *p,FILE *fp);
/*****************************************
THONG TIN HEADER FILE GIF
******************************************/
typedef struct _gifInfoType // thong tin cua Header file Gif
{
char version[7]; // thong tin phien ban GIF89a hay GIF87a ?
byte gcTable; // Co ton tai bang mau hay khong? Gia tri 0 hoac 1
byte bitsPerPixel; // so bit tren mot pixel
byte background; // thuong la 0;
unsigned int xStart, yStart; // thuong la 0,0
int width, height; // chieu cao cua anh
byte lcTable; // bang mau ton tai
byte interlaced; // tep interlaced
} gifInfoType;
/****************************************
Cac bien toan cuc cho file gif.c
*****************************************/
FILE *dataFile; // file GIF duoc khai baotoan cuc
unsigned long pwr2[17]; // luu tru cac luy thua cua 2
int nBitsIn; // So bit duoc lay tu mot ky tu
int num;
int aChar; // mot ky tu doc duoc tu tep
int blockLength;
long paletteOffset, dataOffset; //vi tri cua bang mau va du lieu
/**************************************************************************
* fskip *
* Bo qua mot so byte trong 1 tep *
**************************************************************************/
void fskip(FILE *fp, int num_bytes)
{
int i;
for (i=0; i<num_bytes; i++)
fgetc(fp);
}
/**************************************************************************
* set_mode *
* Dat che do do hoa. *
**************************************************************************/
void set_mode(byte mode)
{
union REGS regs;
regs.h.ah = SET_MODE;
regs.h.al = mode;
int86(VIDEO_INT, ®s, ®s);
}
void put_pixel (int x, int y, byte color)
{
if (y>=0 && y<200) // kiem tra xem toa do co hop le hay khong
if (x>=0 && x<320)
VGA[y*320+x] = color; // truy cap thang vao bo nho man hinh
}
/**************************************************************************
* set_palette *
* Sets all 256 colors of the palette. *
**************************************************************************/
void set_palette(byte *palette)
{
int i;
outp(PALETTE_INDEX,0); /* tell the VGA that palette
data is coming. */
for(i=0;i<256*3;i++)
outp(PALETTE_DATA,palette[i]); /* write the data */
}
/******************************************
* khoitao
* Khoi tao cac gia tri cho ham show_gif
*******************************************/
void khoitao(void)
{
int i;
nBitsIn = 8; // dat so bit doc ra la 8
num = 0;
pwr2[0]=1; // khoi tao bang luy thua cua 2
for (i=1;i<17;i++) pwr2[i]=pwr2[i-1]*2;
}
/******************************************
* get_bit
* Doc 1 bit tu tep
* Tra ve gia tri doc duoc, 0 hoac 1
******************************************/
int get_bit(void)
{
nBitsIn++; // tang bo dem so bit duoc doc vao
if (nBitsIn == 9) // kiem tra xem doc xong 1 ky tu hay chua?
{
aChar = fgetc(dataFile); //doc 1 ky tu
nBitsIn = 1; //dat so bit doc vao thanh 1 (9-8 =1)
num++;
if (num == blockLength)
{
blockLength = aChar + 1;
aChar = fgetc(dataFile);
num = 1;
}
}
if ((aChar & pwr2[nBitsIn-1])==0) return 0;
else return 1;
}
/******************************************
* read_code
* doc mot ma tu tep
* Se goi ham get_bit de khoi tao ra ma duoc yeu cau
*******************************************/
int read_code (int codesize)
{
int i, code = 0; //Khoi tao gia tri
for (i=0;i<codesize;i++)
code +=get_bit()*pwr2[i]; //chuyen doi tu nhi phan sang thap phan
return code;
}
/***************************************************
* read_gif_info
* Doc thong tin tu header cua file GIF
* tra lai gia tri 1 neu gap loi
***************************************************/
int read_gif_info (FILE *dataFile, gifInfoType *gifInfo)
{
int i;
char abyte; //bien tam thoi
khoitao(); //khoi tao cac gia tri can thiet
for (i=0; i<6; i++) gifInfo->version[i]=fgetc(dataFile);
gifInfo->version[6]='\0'; //Doc 6 byte phien ban
for (i=0;i<4;i++) (void) fgetc(dataFile); //bo qua thong tin chieu cao va rong
abyte = fgetc(dataFile); //doc byte tiep theo va luu
gifInfo->gcTable = ((abyte&128)==128); //Bang mau co ton tai hay khong?
gifInfo->bitsPerPixel = (abyte & 7)+1; //So bit tren 1 pixel
gifInfo->background = fgetc(dataFile); //doc mau nen
abyte = fgetc(dataFile); //byte tiep theo luon la 0
if (abyte!=0) return 1; //khac 0 => khong phai tep GIF
fgetpos(dataFile,&paletteOffset); //bo qua bang mau
//doc thong tin cua hinh anh
fseek (dataFile, pwr2[gifInfo->bitsPerPixel]*3,SEEK_CUR);
abyte= fgetc(dataFile); //bo qua byte tiep theo
fread(&gifInfo->xStart,2,1,dataFile);
fread(&gifInfo->yStart,2,1,dataFile);
fread(&gifInfo->width,2,1,dataFile);
fread(&gifInfo->height,2,1,dataFile);
abyte=fgetc(dataFile);
gifInfo->lcTable=(((abyte&128)==128) ? 1 : 0); //local color table?
gifInfo->interlaced = (((abyte & 64) == 64) ? 1:0); //interlaced image?
fgetpos(dataFile,&dataOffset);
return 0; //successful
}
/************************************************
* show_gif
* Giai nen file gif ra mot mang du lieu de hien thi trong chuong trinh chinh
* Tra lai gia tri neu hinh anh khong hien thi duoc
*************************************************/
int load_gif(char *file,IMAGE *img)
{
gifInfoType gifInfo;
byte abyte;
byte r,g,b;
int i;
int size;
int codeSize, code, inCode, curCode, oldCode, prefix[4096],
suffix[4096]; //de giai nen LZW
int clearCode, eofCode, freeCode, firstFree, maxCode, initCodesize,
bitMask, finChar, outCount, outCode[1025]; //giai thuat LZW bien the
int x, y; //vi tri cua pixel
dataFile = fopen(file,"rb");
if (dataFile == NULL) return 6; //khong mo tep duoc
if (read_gif_info(dataFile,&gifInfo)!=0)
{ fclose(dataFile); return 5;} //tep khong hop le
if (strcmpi(gifInfo.version, "GIF89a")==0)
{ fclose(dataFile); return 1;} //dinh dang khong ho tro
else if (strcmpi(gifInfo.version, "GIF87a") !=0)
{ fclose(dataFile); return 4;} //header khong hop le
if (gifInfo.gcTable == 0) //khong the thao tac thieu bang mau
{ fclose(dataFile);return 2;}
if (gifInfo.lcTable !=0) //khong xu ly bang mau dia phuong duoc
{ fclose(dataFile); return 3;}
if (gifInfo.interlaced !=0) //khong xu ly tep ket noi duoc
{ fclose(dataFile); return 4;}
//Doc bang mau
fseek(dataFile, paletteOffset, SEEK_SET); //Nhay toi vi tri bang mau
for (i=0;i<pwr2[gifInfo.bitsPerPixel];i++) //doc bang mau
{
img->palette[(int)(i*3+2)] = fgetc(dataFile) >> 2;
img->palette[(int)(i*3+1)] = fgetc(dataFile) >> 2;
img->palette[(int)(i*3+0)] = fgetc(dataFile) >> 2;
}
set_palette(img->palette);
//Xin cap phat o nho
img->width=gifInfo.width;
img->height=gifInfo.height;
size=gifInfo.width*gifInfo.height;
if((img->data=(byte
*)malloc((word)(gifInfo.width*gifInfo.height)))==NULL) //Khong cap
phat bo nho duoc
return 7;
//Doc du lieu
fseek(dataFile, dataOffset, SEEK_SET); //nhay toi vi tri bat dau
du lieu hinh anh
codeSize = fgetc(dataFile); //doc kich co ma
clearCode = pwr2[codeSize]; //ma clear = 2^codeSize
eofCode = clearCode +1; // ma ket thuc File
freeCode = firstFree = clearCode +2; // ma tu do
codeSize++; // kich co that cua so ma
initCodesize = codeSize; // khoi tao gia tri
maxCode = pwr2[codeSize];
bitMask = pwr2[gifInfo.bitsPerPixel]-1; // giai nen cac bit
blockLength = fgetc(dataFile) + 1;
outCount = 0; // so cai pixel nen
x = gifInfo.xStart; //toa do x va y cho mot pixel
y = gifInfo.yStart;
//Bat dau giai nen du lieu
do
{
code = read_code(codeSize); // doc ma co kich thuoc CodeSize
if (code == eofCode) break; // ket thuc tep?
if (code == clearCode) // ma Clear?
{
codeSize = initCodesize; // bat dau khoi tao kich co CodeSize
maxCode = pwr2[codeSize];
freeCode = firstFree;
code = read_code(codeSize); // Doc ma tiep theo
oldCode = curCode = code; // danh dau hien tai va bit cu
finChar = code & bitMask; // giai nen cac bit
img->data[y*gifInfo.width+(x++)] = finChar; // Ghi du lieu vao bo dem
put_pixel (x, y, outCode[i]);
if (x>= gifInfo.width) { x=0; y++;} //Hang tiep theo
}
else
{
inCode = curCode = code; // chua hieu
if (code >= freeCode) // khong trong bang?
{
curCode = oldCode;
outCode [outCount++]=finChar;
}
if (curCode > bitMask)
do {
outCode[outCount++] = suffix[curCode];
curCode = prefix[curCode];
} while (curCode > bitMask);
finChar = curCode & bitMask; //giai nen cac bit
outCode [outCount++] = finChar; // luu lai
for (i=outCount - 1;i>=0;i--) // in ra cac pixel da duoc luu
{
img->data[y*gifInfo.width+(x++)]=outCode[i];
put_pixel (x, y, outCode[i]);
if (x>= gifInfo.width) {x=0; y++;}
}
outCount = 0;
prefix[freeCode] = oldCode;
suffix[freeCode++] = finChar;
oldCode = inCode;
if(freeCode >=maxCode && codeSize <12)
{ codeSize++; maxCode *=12; }
}
} while (code != eofCode); // EOF? Thoat
fclose(dataFile);
return 0;
}
/**************************************************************************
* draw_image *
* Draws an image. *
**************************************************************************/
void draw_image(IMAGE img)
{
int j,k;
j=k=0;
for(j=0;j<img.height;j++)
for(k=0;k<img.width;k++)
put_pixel(k,j,img.data[j*img.width+k]);
}
/**************************************************************************
* Main *
* Draws a bitmap and then rotates the palette. *
**************************************************************************/
void main()
{
IMAGE img;
set_mode(VGA_256_COLOR_MODE); /* set the video mode. */
/* set the palette */
load_gif("a.gif",&img); /* open the file */
draw_image(img);
free(&img.data); /* free up memory used */
getch();
set_mode(TEXT_MODE); /* set the video mode back to text mode. */
return;
} |