-
1
- #1
AbidingDude
Programmer
thread206-1695190
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:
[tt]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;
};[/tt]
Then to know how much memory is needed, I made a quick macro:
[tt]#define BMimagesize(w,h) imagesize(0,0,(int)(w),(int)(h))[/tt]
Then to use the bitmap data I needed to read it from file:
[tt]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);
}[/tt]
Then finally the function that actually does the converting:
[tt]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);
}[/tt]
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:
[tt]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;
};[/tt]
Then to know how much memory is needed, I made a quick macro:
[tt]#define BMimagesize(w,h) imagesize(0,0,(int)(w),(int)(h))[/tt]
Then to use the bitmap data I needed to read it from file:
[tt]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);
}[/tt]
Then finally the function that actually does the converting:
[tt]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);
}[/tt]
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.