Bitmapy w C
LOSMARCELOS
Tutaj jest krótki kod źrodłowy jak wczytać i wyświetlić bitmape w Borland C...
- UWAGA! PAMIETAJ ABY USTAWIC "LARGE memory model" ! *
- W Borland C: bcc -ml bitmap.c
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <mem.h>
#define VIDEO_INT 0x10 /* przerwanie VIDO dla BIOS */
#define SET_MODE 0x00 /* BIOS funkcja BIOS ustawiająca video */
#define VGA_256_COLOR_MODE 0x13 /* tryb 320 X 200 */
#define TEXT_MODE 0x03 /* 80x25 tryb tekstowy. */
#define SCREEN_WIDTH 320 /* szerokosc w pixelach dla trybu 0x13 */
#define SCREEN_HEIGHT 200 /* wysokosc w pixelach dla trybu 0x13 */
#define NUM_COLORS 256 /* liczba kolorow dla trybu 0x13 */
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
byte *VGA=(byte *)0xA0000000L; /* wskazanie dla adresu pamieci video */
word *my_clock=(word *)0x0000046C; /* ustawienie zegaru systemowego 18.2hz */
typedef struct tagBITMAP /* struktura bitmapy */
{
word width;
word height;
byte *data;
} BITMAP;
/**************************************************************************
* fskip *
* Przeskoki bajtow w pliku *
**************************************************************************/
void fskip(FILE *fp, int num_bytes)
{
int i;
for (i=0; i<num_bytes; i++)
fgetc(fp);
}
/**************************************************************************
* set_mode *
* Ustaw tryb video *
**************************************************************************/
void set_mode(byte mode)
{
union REGS regs;
regs.h.ah = SET_MODE;
regs.h.al = mode;
int86(VIDEO_INT, ®s, ®s);
}
/**************************************************************************
* load_bmp *
* Wczytaj bitmape z pliku do pamięci *
**************************************************************************/
void load_bmp(char *file,BITMAP *b)
{
FILE *fp;
long index;
word num_colors;
int x;
/* otworz plik */
if ((fp = fopen(file,"rb")) == NULL)
{
printf("Blad w otwieraniu pliku %s.\n",file);
exit(1);
}
/* zobacz czy to jest poprawny plik bitmapy (kazda bitmapa zaczyna sie od 'BM' wewnatrz pliku */
if (fgetc(fp)!='B' || fgetc(fp)!='M')
{
fclose(fp);
printf("%s To nie jest plik bitmapy ! \n",file);
exit(1);
}
/* przeczytaj szerokosc i wysokosc bitmapy, i liczbe kolorow uzywanych w niej;
ignoruj reszte ! */
fskip(fp,16);
fread(&b->width, sizeof(word), 1, fp);
fskip(fp,2);
fread(&b->height,sizeof(word), 1, fp);
fskip(fp,22);
fread(&num_colors,sizeof(word), 1, fp);
fskip(fp,6);
/* zakładamy,że pracujemy na pliku 8 - bitowym */
if (num_colors==0) num_colors=256;
/* alokacja pamięci */
if ((b->data = (byte *) malloc((word)(b->width*b->height))) == NULL)
{
fclose(fp);
printf("Bład przy alokacji pliku : %s.\n",file);
exit(1);
}
/* Ingoruj informacje na temat palety kolorów.
*/
fskip(fp,num_colors*4);
/* czytaj bitmape */
for(index=(b->height-1)*b->width;index>=0;index-=b->width)
for(x=0;x<b->width;x++)
b->data[(word)index+x]=(byte)fgetc(fp);
fclose(fp);
}
/**************************************************************************
* draw_bitmap *
* Draws a bitmap. *
**************************************************************************/
void draw_bitmap(BITMAP *bmp,int x,int y)
{
int j;
word screen_offset = (y<<8)+(y<<6)+x;
word bitmap_offset = 0;
for(j=0;j<bmp->height;j++)
{
memcpy(&VGA[screen_offset],&bmp->data[bitmap_offset],bmp->width);
bitmap_offset+=bmp->width;
screen_offset+=SCREEN_WIDTH;
}
}
/**************************************************************************
* draw_transparent_bitmap *
* Rysuje przezroczystą bitmape *
**************************************************************************/
void draw_transparent_bitmap(BITMAP *bmp,int x,int y)
{
int i,j;
word screen_offset = (y<<8)+(y<<6);
word bitmap_offset = 0;
byte data;
for(j=0;j<bmp->height;j++)
{
for(i=0;i<bmp->width;i++,bitmap_offset++)
{
data = bmp->data[bitmap_offset];
if (data) VGA[screen_offset+x+i] = data;
}
screen_offset+=SCREEN_WIDTH;
}
}
/**************************************************************************
* wait *
* Oczekuj okreslona liczbe tykniec zegara (18hz). *
**************************************************************************/
void wait(int ticks)
{
word start;
start=*my_clock;
while (*my_clock-start<ticks)
{
*my_clock=*my_clock;
}
}
/**************************************************************************
* Main *
* Rysuj nieprzezroczyste i przezroczyste bitmapy *
**************************************************************************/
void main()
{
int i,x,y;
BITMAP bmp;
load_bmp("BITMAPA1.bmp",&bmp); /* otwórz plik */
set_mode(VGA_256_COLOR_MODE); /* ustaw tryb video*/
/* rysuj tło */
for(i=0;i<200;i++)
memset(&VGA[320*i],i,SCREEN_WIDTH);
wait(25);
/* rysuj plytke bitmap po lewej stronie*/
for(y=0;y<=SCREEN_HEIGHT-bmp.height;y+=bmp.height)
for(x=0;x<=(SCREEN_WIDTH)/2-bmp.width;x+=bmp.width)
draw_bitmap(&bmp,x,y);
wait(25);
/* rysuj plytke bitmap przezroczysta po prawej stronie */
for(y=0;y<=SCREEN_HEIGHT-bmp.height;y+=bmp.height)
for(x=SCREEN_WIDTH-bmp.width;x>=SCREEN_WIDTH/2;x-=bmp.width)
draw_transparent_bitmap(&bmp,x,y);
wait(100);
free(bmp.data); /* zwolnij uzywana pamiec */
set_mode(TEXT_MODE); /* przywroc z powrotem tryb tekstowy 80X25 */
return;
}
Trochę dziwne rozwiązanie funkcji pomijania znaków - fskip. Po co po kolei pomijać jeden znak zamiast podaną ilość hurtem za pomocą funkcji ftell/fseek? ;]
Jest błąd w Coyote i zjada wszelkie znaki < - możesz temu zapobiec póki błąd nie zostanie poprawiony zamieniając wszelkie < na <