## Bitmap to BGI

## Bitmap to BGI

(OP)

thread206-1695190: Borland BGI getimage() Details

Ok, for the most part I've figured out how getimage() and putimage() arrange its data in memory. I had to study up on VGA memory layouts and bit planes, but I have a function that will take a 16-color bitmap and convert it to a memory layout such that it can be pasted with putimage(). First I needed a structure:

struct W3_BMP_header{

int type;

unsigned long int size;

unsigned long int reserved;

unsigned long int offset;

unsigned long int headerSize;

long int width;

long int height;

int planes;

int bpp;

unsigned long int comp;

unsigned long int sizeImg;

unsigned long int Xppm;

unsigned long int Yppm;

unsigned long int colorsUsed;

unsigned long int colorsImportant;

};

Then to know how much memory is needed, I made a quick macro:

#define BMimagesize(w,h) imagesize(0,0,(int)(w),(int)(h))

Then to use the bitmap data I needed to read it from file:

void readBMheader(struct W3_BMP_header *h,FILE *f)

{

fpos_t pos;

fgetpos(f,&pos);

rewind(f);

fread(h,sizeof(struct W3_BMP_header),1,f);

fsetpos(f,&pos);

}

Then finally the function that actually does the converting:

void BMtoBGI(char *imgmem,FILE *bmpsource)

{

int j,p2,xy[2];

unsigned int n;

long int x,y,slwb,X;

char buff[8];

unsigned char I,R,G,B;

int chunx,scan;

struct W3_BMP_header Q;

fpos_t pos;

/*Just in case...*/

if(imgmem==NULL)

return;

fgetpos(bmpsource,&pos);

rewind(bmpsource);

readBMheader(&Q,bmpsource);

scan=(int)Q.height;

X= Q.width%2==0 ? Q.width/2 : Q.width/2+1;

slwb=X+(4-X%4)%4;

chunx=(int)(Q.width/8+(Q.width%8>0));

xy[0]=(int)Q.width-1; xy[1]=(int)Q.height-1;

memcpy(imgmem,xy,2*sizeof(int));

n=4;

for(y=1;y<=scan;y++,n+=3*chunx){

fseek(bmpsource,-slwb*y,SEEK_END);

for(x=0;x<slwb;x+=4){

for(j=0;j<4;j++){

p2=fgetc(bmpsource);

/*Break the byte up into two pixel bytes.*/

buff[2*j]=p2>>4; /*0,2,4,6*/

buff[2*j+1]=p2&15;/*1,3,5,7*/

}

I=R=G=B=0;

for(j=0;j<8;j++){

I|=j>4?(buff[j]&8)>>(j-4):(buff[j]&8)<<(4-j);

R|=j>5?(buff[j]&4)>>(j-5):(buff[j]&4)<<(5-j);

G|=j>6?(buff[j]&2)>>(j-6):(buff[j]&2)<<(6-j);

B|=j>7?(buff[j]&1)>>(j-7):(buff[j]&1)<<(7-j);

}

imgmem[n]=I;

imgmem[n+chunx]=R;

imgmem[n+2*chunx]=G;

imgmem[n+3*chunx]=B;

n++;

}

}

fsetpos(bmpsource,&pos);

}

It does have its limitations. It can only work with 16-color bitmaps, and it only properly works when in EGA or VGA mode. I'm currently working on a CGA conversion.

Ok, for the most part I've figured out how getimage() and putimage() arrange its data in memory. I had to study up on VGA memory layouts and bit planes, but I have a function that will take a 16-color bitmap and convert it to a memory layout such that it can be pasted with putimage(). First I needed a structure:

struct W3_BMP_header{

int type;

unsigned long int size;

unsigned long int reserved;

unsigned long int offset;

unsigned long int headerSize;

long int width;

long int height;

int planes;

int bpp;

unsigned long int comp;

unsigned long int sizeImg;

unsigned long int Xppm;

unsigned long int Yppm;

unsigned long int colorsUsed;

unsigned long int colorsImportant;

};

Then to know how much memory is needed, I made a quick macro:

#define BMimagesize(w,h) imagesize(0,0,(int)(w),(int)(h))

Then to use the bitmap data I needed to read it from file:

void readBMheader(struct W3_BMP_header *h,FILE *f)

{

fpos_t pos;

fgetpos(f,&pos);

rewind(f);

fread(h,sizeof(struct W3_BMP_header),1,f);

fsetpos(f,&pos);

}

Then finally the function that actually does the converting:

void BMtoBGI(char *imgmem,FILE *bmpsource)

{

int j,p2,xy[2];

unsigned int n;

long int x,y,slwb,X;

char buff[8];

unsigned char I,R,G,B;

int chunx,scan;

struct W3_BMP_header Q;

fpos_t pos;

/*Just in case...*/

if(imgmem==NULL)

return;

fgetpos(bmpsource,&pos);

rewind(bmpsource);

readBMheader(&Q,bmpsource);

scan=(int)Q.height;

X= Q.width%2==0 ? Q.width/2 : Q.width/2+1;

slwb=X+(4-X%4)%4;

chunx=(int)(Q.width/8+(Q.width%8>0));

xy[0]=(int)Q.width-1; xy[1]=(int)Q.height-1;

memcpy(imgmem,xy,2*sizeof(int));

n=4;

for(y=1;y<=scan;y++,n+=3*chunx){

fseek(bmpsource,-slwb*y,SEEK_END);

for(x=0;x<slwb;x+=4){

for(j=0;j<4;j++){

p2=fgetc(bmpsource);

/*Break the byte up into two pixel bytes.*/

buff[2*j]=p2>>4; /*0,2,4,6*/

buff[2*j+1]=p2&15;/*1,3,5,7*/

}

I=R=G=B=0;

for(j=0;j<8;j++){

I|=j>4?(buff[j]&8)>>(j-4):(buff[j]&8)<<(4-j);

R|=j>5?(buff[j]&4)>>(j-5):(buff[j]&4)<<(5-j);

G|=j>6?(buff[j]&2)>>(j-6):(buff[j]&2)<<(6-j);

B|=j>7?(buff[j]&1)>>(j-7):(buff[j]&1)<<(7-j);

}

imgmem[n]=I;

imgmem[n+chunx]=R;

imgmem[n+2*chunx]=G;

imgmem[n+3*chunx]=B;

n++;

}

}

fsetpos(bmpsource,&pos);

}

It does have its limitations. It can only work with 16-color bitmaps, and it only properly works when in EGA or VGA mode. I'm currently working on a CGA conversion.