PDA

View Full Version : Will this work for transparency?



07-08-2002, 06:46 AM
I have a bmp image file that I am writing to the screen. I am making it in paint so I don't have a lot of complex features. I was thinking, I can set an Index to a color I will not use, then set the indexMask to that color. First will this give me a transparent image? and second, How do I set the color index up?

rhmazza
07-08-2002, 07:37 AM
Something you can do, is when loading the bmp to a texture, resample the bits. So say you wanted black to be transparent. If you're loading a 24 bit bmp, you have to take the array of bytes it's stored in (assuming that's how it's stored) and move that into an array that has room for 32 bits per pixel, so every 24 bits of the move, you'd save an extra 8 bits for an alpha channel. Then either afterwards (or while) you'd look at each set of 24 bits to see if it has the components that make up black, and if so, make the alpha value 255. Else leave it at zero. Then make sure you make it an RGBA when you create the texture, and then enable alpha testing with something like:
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, .95f);

That should do. Hope it's what you were looking for.

Ray

07-08-2002, 01:02 PM
So I need to create a 4-byte 2D array, copy the data from the original array to the first 24 bits of the new array then change the contents of the last 8-bits to add in the alpha parameter. Then use a test to not display those bits.

Is that right?

dorbie
07-08-2002, 05:02 PM
Yes that's typically how it is done. YOU must create an alpha channel for the image. There are several supported internal formats so it doesn't have to be 4 whole bytes but basically you do need to create an in memory image with alpha information.

P.S. The best way is to write an image with alpha, don't use keying, that produces bad results (halos in the blend region for example) so paint the transparency mask, something like photoshop will support this if you save the image with a transparency channel to a format which supports alpha, for example PNG files.

[This message has been edited by dorbie (edited 07-08-2002).]

07-09-2002, 04:23 AM
I tried the following code:




unsigned long int **tmp;
*tmp = (unsigned long*)malloc( 4*img->sizeY );
for( int x=0;x<img->sizeY; x++ )
{
tmp[x] = (unsigned long*)malloc( 4*img->sizeX );
}
for( int y=0;y<img->sizeY; y++ )
{
for( int x=0;x<img->sizeX; x++ )
{
tmp[x][y] = img->data[x][y] * 256;
if( tmp[x][y] > 0xF0F0F000 )
tmp[x][y] |= 0x000000FF;
}
}

glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, .95f);


But I can't seem to get the dynamic allocation to work properly.

Deiussum
07-09-2002, 04:50 AM
First of all, I notice you are using an unsigned long. In doing so you should be aware of the way that will be stored in memory. On Little-endian machines like x86 processors, if you are using 0xRRGGBBAA you'll find that in memory that is stored as 0xAABBGGRR.

Also, you would probably be better off allocating the memory all in one chunk. (e.g. unsigned long int *tmp = (unsigned long*)malloc(4*img->sizeY*img->sizeX))

You can get the index into that by using the formula:

index = y * sizeX + x;

The reason you don't want to allocate it the way you are is that when you pass tmp into something like glTexImage2D or glDrawPixels, the data it's going to be reading is going to be pointer addresses, not the actual data of the image. This is a bad thing. Especially since you only allocate the double pointer to be the size of the height * 4. The gl methods will try and read byte data equal to height * width * 4, so you will run into overflow conditions, and will likely crash.

Rob Fletcher
07-09-2002, 05:10 AM
Hi ... here's snippet of code ...

Use whatever you wish ...


=======
size= TextureImage->sizeX * TextureImage->sizeY * 4; /* rgba size */
temp_rgba = (char *) malloc(size);

if( tfunc == FIXED ) {
src = TextureImage->data;
dst = temp_rgba;
for( i = 0; i < TextureImage->sizeX ; i++ )
for( j = 0; j < TextureImage->sizeY ; j++ ) {
for( k = 0; k < 3 ; k++ ) {
*dst++ = *src++; /* Copy rgb over */
}
*dst++ = a; /* Set the alpha value */
}
}

/* Specific colour to set to transparent */
else {
size= TextureImage->sizeX * TextureImage->sizeY * 4; /* rgba size */
temp_rgba = (char *) malloc(size);
src = TextureImage->data;
dst = temp_rgba;
for( i = 0; i < TextureImage->sizeX ; i++ )
for( j = 0; j < TextureImage->sizeY ; j++ ) {
flag = 0;
for( k = 0; k < 3 ; k++ ) {
switch (tfunc) {
case EQUAL:
if( *src == col[k] ) flag++;
break;
case LESSTHAN:
if( *src < col[k] ) flag++;
break;
case GREATERTHAN:
if( *src > col[k] ) flag++;
break;
default:
if( *src == col[k] ) flag++;
break;
}
*dst++ = *src++; /* Copy rgb over */
}
if( flag == 3 ){ /* if rgb is correct ... */
*dst++ = a; /* Copy in the alpha value */
}
else
*dst++ = 255; /* else not transp */
}
}

if( MIPMAP ) {
glBindTexture(GL_TEXTURE_2D, textures[last_texture]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, 4,
TextureImage->sizeX, TextureImage->sizeY,
GL_RGBA, GL_UNSIGNED_BYTE, temp_rgba);
}
else .... blah

=====
Basically it copies over the rgb data, and then either sets the alpha to a fixed value, or checks the rgb triplets for lt,=,gt, to a supplied value ... so e.g. you could set an alpha of 0.6 for all pixels where the rgb values are gt 180,180,180.

Was used in a project of mine... you can of course dream up lots of ways to decide whether to assign an alpha or not, and of course, even assign different alpha values as well ... endless possibilities ...

Enjoy

Rob.

07-09-2002, 08:17 AM
Thank you for the source code, that really helps although I am having a problem understanding what some parts do. I am unsure about the usage of tfunc and exactly how the pointer statements are incrementing.

I made some modifications to my code following the advice and got rid of the errors, but no nothing will display:

I remembered to include the important variable defs this time.



bool drawBMP( float x, float y, const char* fname )
{
AUX_RGBImageRec* img = LoadBMP( fname );
if (img)
{
/* THIS SHOULD DO TRANSPARENCY */

unsigned long int *tmp;
tmp = (unsigned long*)malloc( 4*img->sizeY*img->sizeX );

for( int y=0;y<img->sizeY*img->sizeX; y++ )
{
tmp[y] = img->data[y];
if( tmp[y] > 0x00F0F0F0 )
tmp[y] |= 0xFF000000;
}
/* START OF MASK */

glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, .95f);

/* END OF TRANSPARENCY CODING */

glRasterPos2f( x, y );
glDrawPixels( img->sizeX , img->sizeY, GL_RGB, GL_UNSIGNED_BYTE, img->data );
free(img->data);
free(img);
return( true );
}
return( false );
}

Bob
07-09-2002, 09:42 AM
if( tmp[y] > 0x00F0F0F0 ) tmp[y] |= 0xFF000000;

What is this line suppozed to do? I have a feeling it doesn't do what you think it does.

Also, when you draw your image, you set a raster position. A raster position is treated as a vertex, and is transformed by the modelview and projection matrix, clipped bu the view colume, and finally marked as visible or invisible. If it's invisible, it will be invalid, and any drawing using that raster position will do nothing.

Even if the raster position is located slightly outside the view volume, in such way that the picture should be partly visible, it is still invalid and glDrawPixels will not draw anything.

Deiussum
07-09-2002, 10:37 AM
I'm curious about what this part is...

tmp[y] = img->data[y];

Isn't data an unsigned char array? And does the BMP contain RGB data or indexed data? If indexed data, you are just getting in index into a color table and you should be looking for the RGB values there. If it's RGB data, you need more than 1 byte.