http://GameProgrammer.Com

Programming

GP Mailing List
     Thread Index
     Date Index

ATXGPSIG List
     Thread Index
     Date Index

Google
>

Home

Wise2Food



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: The Windows BMP File Format



Hey, guess what! I forgot to attach BMP.H! Sorry, I'm just an idiot.
-Ender Wiggin
unsigned char *VGA=(unsigned char *)0xA0000000L;        /* this points to video memory. */
struct Picture {
	unsigned short x,y;
     unsigned char *picture;
	unsigned char *palette;
} Pict;
struct BMP1 {
/******FILE HEADER****************/
	unsigned short bfType;		// Must be set to 'BM'
     unsigned long  bfSize;		// The size of the file in bytes
     unsigned short bfReserved1;	// Reserved for future expansion
     unsigned short bfReserved2;	// Reserved for future expansion
	unsigned long  bfOffBits;	// The number of bytes before bitmap
};
struct BMP1 BMPFILEHEADER;
struct BMP2 {
/******BITMAP HEADER**************/
     unsigned long  biSize;		// The size of this header: 40
	unsigned long  biWidth; 		// The width in pixels
     unsigned long  biHeight;		// The height in pixels
     unsigned short biPlanes;		// The number of planes (1)
     unsigned short biBitCount;	// The number of bits per pixel
     unsigned long  biCompression; // The type of compression
     unsigned long  biSizeImage;	// Size of image in bytes when compressed
     unsigned long biXPelsPerMeter;// The horizontal number of pix/meter
     unsigned long biYPelsPerMeter;// The vertical number of pix/meter
     unsigned long  biClrUsed;	// The number of colors that are used
     unsigned long  biClrImportant;// The number of important colors
} BMPINFOHEADER;

struct BMP3 {
/******OS/2 BITMAP HEADER*********/
	unsigned long	bcSize;		// The size of this header: 12
     unsigned short bcWidth;		// The width in pixels
     unsigned short bcHeight;		// The height in pixels
     unsigned short bcPlanes;		// The number of planes (1)
     unsigned short bcBitCount;	// The number of bits per pixel
} BMPCOREINFO;

#define fskip(fp,n) { \
	int i;		  \
     for(i=0;i<n;i++) \
     	fgetc(fp);  \
}
void WaitRetrace() {
	asm mov dx,3DAh
l1:
	asm {
		in al,dx
		and al,08h
		jnz l1
	}
l2:
	asm {
		in al,dx
		and al,08h
		jz l2
	}
}

void inline DrawPixelXY(short x,unsigned char y,unsigned char color) {
	VGA[(y<<8)+(y<<6)+x]=color;
}

unsigned char inline GetPixelXY(short x, unsigned char y) {
	return VGA[(y<<8)+(y<<6)+x];
}

void inline DrawPixelRaw(unsigned short a, unsigned char color) {
	VGA[a]=color;
}

void DrawPicture(unsigned short xoffset, unsigned short yoffset, Picture &P) {
	unsigned short pos=0;
	for(unsigned short y=0;y<P.y;y++)
     	for(unsigned short x=0;x<P.x;x++) {
              	DrawPixelXY(x+xoffset,y+yoffset,P.picture[pos]);
               pos++;
          }
}
void DrawPictureRGB(unsigned short xoffset, unsigned short yoffset, Picture &P, unsigned char which) {
	unsigned long pos=which;
     for(unsigned short y=0;y<P.y;y++)
     	for(unsigned short x=0;x<P.x;x++) {
          	DrawPixelXY(x+xoffset,y+yoffset,P.picture[pos]);
               pos+=3;
          }
}
int LoadBMP(char *file, Picture *P) {
	FILE *fp;
	long index;
     int x,type,cnt,c,d;  // type: 0=OS/2, 1=Windows
     double a,b;
	unsigned char reed;
     if((fp=fopen(file,"rb"))==NULL) {
          return 1; // Error opening file
     }
     fread(&BMPFILEHEADER,sizeof(BMPFILEHEADER),1,fp);
     fread(&BMPINFOHEADER.biSize,sizeof(BMPINFOHEADER.biSize),1,fp);
     if(BMPINFOHEADER.biSize==40) { // Windows
     	fread(&BMPINFOHEADER.biWidth,36,1,fp); // 36 = 40 - 4
          P->x=BMPINFOHEADER.biWidth;
          P->y=BMPINFOHEADER.biHeight;
          type=1;
     }
     if(BMPINFOHEADER.biSize==12) { // OS/2
          BMPCOREINFO.bcSize=BMPINFOHEADER.biSize; // 12
		fread(&BMPCOREINFO.bcWidth,8,1,fp); // 8 = 12 - 4
          P->x=BMPCOREINFO.bcWidth;
		P->y=BMPCOREINFO.bcHeight;
          type=0;
     }
     if((BMPINFOHEADER.biSize!=40)&&(BMPINFOHEADER.biSize!=12))
     	return 5; // Unknown BMP type or corrupted header
     if(((!type)&&(BMPCOREINFO.bcBitCount==8))||(type)&&(BMPINFOHEADER.biBitCount==8)) {	// Test for 8 bit
     	if((P->picture=new unsigned char[P->x*P->y])==NULL) {
     		fclose(fp);
     	     return 3; // Not enough memory for picture
	     }
     	if((P->palette=new unsigned char[256*3])==NULL) {
     		fclose(fp);
     	     return 4; // Not enough memory for palette
	     }
     	for(index=0;index<256;index++) {
	     	P->palette[(int)(index*3+2)]=fgetc(fp)>>2;
     	     P->palette[(int)(index*3+1)]=fgetc(fp)>>2;
          	P->palette[(int)(index*3+0)]=fgetc(fp)>>2;
	          if(type) x=fgetc(fp);
     	}
	     if(((type)&&(!BMPINFOHEADER.biCompression))||(!type)) {	// Test for compressed
		     for(index=(P->y-1)*P->x;index>=0;index-=P->x)
     			for(x=0;x<P->x;x++)
          			P->picture[(index+x)]=(unsigned char)fgetc(fp);
          }
		if((type)&&(BMPINFOHEADER.biCompression)) {
          	index=(P->y-1)*P->x;
               while(index>=0) {
               	x=0;
                    while(x<P->x) {
                    	reed=fgetc(fp);
                         if(!reed)	{ // Literal or special
                              c=fgetc(fp);
                              if(c==2) {
                              	x+=fgetc(fp);
                                   index-=(P->x*fgetc(fp));
                              }
                              if((c!=0)&&(c!=1)&&(c!=2)) {
	                         	for(cnt=0;cnt<c;cnt++) {
     	                    		P->picture[index+x]=(unsigned char)fgetc(fp);
	     	                         x++;
     	     	               }
                                   a=(float)c;
                    	          if(modf(a/2,&b)) {
                         	     	d=fgetc(fp);	// even byte padding
                                   }
                              }
                         } else {	// RLE
                              d=fgetc(fp); // what to store
                              for(cnt=0;cnt<reed;cnt++) {
                              	P->picture[index+x]=(unsigned char)d;
                                   x++;
                              }
                         }
                    }
                    index-=P->x;
               }
          }
     }
     if(((!type)&&(BMPCOREINFO.bcBitCount==24))||((type)&&(BMPINFOHEADER.biBitCount==24))) {	// Test for 24 bit
     	if((P->picture=new unsigned char[P->x*P->y*3])==NULL) {
          	fclose(fp);
               return 3;	// Not enough memory for picture
          }
          for(index=P->y;index>=0;index--)
          	for(x=0;x<P->x;x++) {
                    P->picture[(index*P->x+x)*3+2]=fgetc(fp);
                    P->picture[(index*P->x+x)*3+1]=fgetc(fp);
                    P->picture[(index*P->x+x)*3+0]=fgetc(fp);
               }
     }
	if	(((!type)&&(BMPCOREINFO.bcBitCount!=24)&&(BMPCOREINFO.bcBitCount!=8))||
		  ((type)&&(BMPINFOHEADER.biBitCount!=24)&&(BMPINFOHEADER.biBitCount!=8)))
            	return 2; // Unsupported number of bits per pixel
	fclose(fp);
     return 0; // No error, successful
}

void UnDrawPicture(unsigned short xoffset, unsigned short yoffset, Picture &P, unsigned char color) {
	unsigned short pos=0;
	for(unsigned short y=0;y<P.y;y++)
     	for(unsigned short x=0;x<P.x;x++) {
              	DrawPixelXY(x+xoffset,y+yoffset,color);
               pos++;
          }
}

void set_palette(unsigned char *palette) {
  int i;

  outp(0x3c8,0);              /* tell the VGA that palette data
                                         is coming. */
  for(i=0;i<256*3;i++)
    outp(0x3c9,palette[i]);    /* write the data */
}