PDA

View Full Version : code for make black color of BITMAP (bmp) transparent...



MofuX
08-23-2001, 03:29 AM
Hi, if anybody has got a code 2 make the black colors of a bitmap transparent (alpha value of 1) please post here!
I know that tga is much better becouse of its alpha channel, but i need bmp for my models...
______________________
PS:
it would be very nice if the code could have a little example too how to texture it on an cube (or another object)

THX 2 YOU ;-)

niko
08-23-2001, 06:26 AM
Load your bmp for example to a char array and then check for each pixel if R, G and B are zero then your alphavalue for that pixel is also zero. For example...

//one pixel texture http://www.opengl.org/discussion_boards/ubb/smile.gif
char rgb[3];
char rgba[4];

//copy rgb values to new array
rgba[0] = rgb[0];
rgba[1] = rgb[1];
rgba[2] = rgb[2];

if (rgb[0] == 0 && rgb[1] == 0 && rgb[2] == 0)
rgba[3] = 0;
else
rgba[3] = 255;

...and then create your texture using rgba array as the source.

- Niko

MofuX
08-23-2001, 07:05 AM
this i know, but how to realize that?
I need code!
PLZ give me some code mates!

wXm
08-23-2001, 07:28 AM
yes i would like to have it to.

Inquisitor
08-23-2001, 02:00 PM
#include <stdio.h>
#include <GL\gl.h>

bool LoadBmpBlackTrans(const char *fname,GLubyte **bits,GLsizei &amp;width,GLsizei &amp;height)
{
bool retval=false;
// load file and check if it looks reasonable
FILE *fp=fopen(fname,"rb");
if(fp) {
fseek(fp,0L,2);
long size=ftell(fp);
if(size>(long)sizeof(BITMAPFILEHEADER)) {
unsigned char *data=new unsigned char[size];
if(data) {
fseek(fp,0L,0);
if(fread(data,size,1,fp)==1) {
BITMAPFILEHEADER *file_header=(BITMAPFILEHEADER*)data;
if(file_header->bfType==MAKEWORD('B','M')) {
if(file_header->bfSize==(DWORD)size) {
BITMAPINFO *info=(BITMAPINFO*)(data+sizeof(BITMAPFILEHEADER)) ;
// we only handle uncompressed bitmaps
if(info->bmiHeader.biCompression==BI_RGB) {
width=info->bmiHeader.biWidth;
if(width>0) {
height=info->bmiHeader.biHeight;
if(height) {
if(height<0) height=(-height);
// we want RGBA. let's alloc enough space
*bits=new GLubyte[width*height*4L];
if(*bits) {
retval=true;
GLubyte *current_bits=*bits;
GLubyte *pixel=data+file_header->bfOffBits;
GLsizei h=height,w=width;
long padding;
switch(info->bmiHeader.biBitCount) {
// 8-bit palette bitmaps
case 8:
padding=w % 2;
RGBQUAD rgba;
for(;h>0;h--) {
for(w=width;w>0;w--) {
rgba=info->bmiColors[*pixel];
pixel++;
*current_bits++=rgba.rgbRed;
*current_bits++=rgba.rgbGreen;
*current_bits++=rgba.rgbBlue;
*current_bits++=255;
}
pixel+=padding;
}
break;
// 24-bit bitmaps
case 24:
padding=(w*3) % 2;
for(;h>0;h--) {
for(w=width;w>0;w--) {
*current_bits++=pixel[2];
*current_bits++=pixel[1];
*current_bits++=pixel[0];
*current_bits++=255;
pixel+=3;
}
pixel+=padding;
}
break;
case 32:
// 32-bit bitmaps
// never seen it, but Win32 SDK claims the existance
// of that value. 4th byte is assumed to be alpha-channel.
for(;h>0;h--) {
for(w=width;w>0;w--) {
*current_bits++=pixel[2];
*current_bits++=pixel[1];
*current_bits++=pixel[0];
*current_bits++=pixel[3];
pixel+=4;
}
}
break;
// I don't like 1,4 and 16 bit.
default:
delete[] *bits;
retval=false;
break;
}
if(retval) {
// mirror image if neccessary (never tested)
if(info->bmiHeader.biHeight<0) {
long *data_q=(long*)*bits;
long wt=width*4L;
long *dest_q=(long*)(*bits+(height-1)*wt);
long tmp;
while(data_q<dest_q) {
for(w=width;w>0;w--) {
tmp=*data_q;
*data_q++=*dest_q;
*dest_q++=tmp;
}
dest_q-=(wt+wt);
}
}
// now make every black pixel transparent
size=width*height;
current_bits=*bits;
while(size>0L) {
if(current_bits[0]==0 &amp;&amp; current_bits[1]==0 &amp;&amp; current_bits[2]==0)
current_bits[3]=0;
else
current_bits[3]=255;
current_bits+=4;
size--;
}
}
}
}
}
}
}
}
}
delete[] data;
}
}
fclose(fp);
}
return retval;
}
//---------------------------------------------------------------------------


Hope this helps. But be warned: I did test it with one single bmp.
It handles 8-bit paletted and 24/32 bit truecolor bitmaps only. It returns RGBA data.
Usage:



GLubyte *data;
GLsizei width,height;
if(LoadBmpBlackTrans("test.bmp",&amp;data,width,height)) {
glTexImage2D(GL_TEXTURE_2D,0,4,width,height,0,GL_R GBA,GL_UNSIGNED_BYTE,(const GLvoid*)data);
}

Inquisitor
08-23-2001, 02:04 PM
Ah, I forgot: if the function returns true you must not forget to free the memory it allocated for you. So if you don't need the RGBA-data anymore, use delete[] to kill it.

MofuX
08-23-2001, 10:23 PM
ah thanks, i will try if it helps...
a lot of code to do http://www.opengl.org/discussion_boards/ubb/wink.gif
but if somebody read this and say: "hey, my code isn't as long as this!!!" so post http://www.opengl.org/discussion_boards/ubb/wink.gif

MofuX
08-23-2001, 10:55 PM
Dont get includet your cool code...
hmmm, could you post a simple example texturing a quad or something like that?

would be very cool!
or send it to my mail addy
m.zilz@web.de

http://www.opengl.org/discussion_boards/ubb/wink.gif

Inquisitor
08-24-2001, 01:16 PM
//---------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h> // needed for LoadBmpBlackTrans (file-I/O)
#include <GL\glu.h>
//---------------------------------------------------------------------------
/*
Do all your normal initialization stuff first.
Don't forget to turn on blending or alpha-testing.
*/
//---------------------------------------------------------------------------
// insert the function here instead of this prototype
bool LoadBmpBlackTrans(const char *fname,GLubyte **bits,GLsizei &amp;width,GLsizei &amp;height);
//---------------------------------------------------------------------------
/* following function should
- load a bmp,
- make black parts transparent
- create a mipmapped, filtered texture
- and finally return a texture name which you can use with glBindTexture

use it like that:
...
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
...
GLuint my_texture=CreateTexture("test.bmp");
glBindTexture(my_texture);
glBegin(GL_QUADS);
....
*/
//---------------------------------------------------------------------------
GLuint CreateTexture(const char *s)
{
GLuint id=0;
GLubyte *data;
GLsizei width,height;
if(LoadBmpBlackTrans(s,&amp;data,width,height)) {
glGenTextures(1,&amp;id);
glBindTexture(GL_TEXTURE_2D,id);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R,GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,GL_LINEAR_MIPMAP_LINEAR;
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL _REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL _REPEAT);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MO DULATE);
gluBuild2DMipmaps(GL_TEXTURE_2D,4,width,height,GL_ RGBA,GL_UNSIGNED_BYTE,(void*)data);
delete[] data;
}
return id;
}
//---------------------------------------------------------------------------


Should work. Don't forget to place prototypes of the functions on top of your code.

MofuX
08-24-2001, 11:34 PM
ok, thanks for your wonderfull work!
i will try if it helps me with my problem...
but if i get it i will use this code for a tutorial on my page (if you want too) www.mofux.de.vu (http://www.mofux.de.vu)
http://www.opengl.org/discussion_boards/ubb/wink.gif

MofuX
08-25-2001, 06:32 AM
argh!

Inquisitor
08-26-2001, 06:15 AM
Please mail me the part of your code that doesn't work. And of course, use it for whatever you want.