• Advertisement
Sign in to follow this  

What would be the appropriate blend function?

This topic is 4348 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

What would be the appropriate blend function to blend out only the color magenta?

Share this post


Link to post
Share on other sites
Advertisement
Before you upload the texture, loop over the pixels and make the FF00FF pixels transparent (0 alpha).

Then use glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA )

Share this post


Link to post
Share on other sites
How would I set the alpha using this function to load bitmaps? :


void BmpImg::RESLoadImg(unsigned int idnumber, int num)
{
HBITMAP hBMP;
BITMAP BMP;

glGenTextures(1, &g_bmp[num]);

hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(idnumber), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
if (hBMP)
{
GetObject(hBMP,sizeof(BMP), &BMP);
// Buffer For Object Information
glPixelStorei(GL_UNPACK_ALIGNMENT,4); // Pixel Storage Mode (Word Alignment / 4 Bytes)
glBindTexture(GL_TEXTURE_2D, g_bmp[num]); // Bind Our Texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);

// Generate Mipmapped Texture (3 Bytes, Width, Height And Data From The BMP)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, BMP.bmWidth, BMP.bmHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
DeleteObject(hBMP); // Delete The Bitmap Object
}

}




Thank you,
~Axesor

Share this post


Link to post
Share on other sites
If bmBitsPixel is three, as it looks like it is, then you would have to allocate a new block of memory with space for the alpha value.

I suggest using TGA and just making the color transparent using your image editor of choice.

Link

Share this post


Link to post
Share on other sites
Likely another function is needed to convert the HBITMAP to a 32bit alpha bitmap. Since .BMP files cannot have alpha-channels you need to create a shadow bitmap that does. You may need to swap RGBA<->ARGB depending on what you want.

Here is some code and psuedo-code

unsigned char* Bmp24ToBmp32(BITMAP& BMP)
{

//1)Allocate an RGBA bitmap
unsigned char* alphabitmap = new char[BMP.bmWidth * BMP.bmHeight * 4];
if(NULL == alphabitmap)return NULL;

//2)Calculate pitch (bytes per line)
int alphapitch = BMP.bmWidth * 4;

//3)Loop though all pixels of the original bitmap
for (i = 0;i < BMP.bmHeight;i++)
for (j = 0;j < BMP.bmWidth;j++)
{
//4)Calculate proper byte offset into the bitmaps
int offRGBA = i *(alphapitch) + (j*4);
int offRGB = i * (BMP.bmWidthBytes) + (j*3);

//4a) Get color at (i,j) from source bitmap
unsigned int pix = BMP.bmBits[offRGB]&0xFF;//B
pix |= BMP.bmBits[offRGB+1]<<8;//G
pix |= BMP.bmBits[offRGB+2]<<16;//R

//4b) Get pointer to corresponding position in destination bitmap
unsigned int* curRGBA = static_cast<unsigned int *>(&alphabitmap[offRGBA]);

//4c) Copy source pixel to dest
*curRGBA = pix;

//5) Check if source color is magenta
if(pix == 0x00FF00FF)
curRGBA[3] = 0; //6) Set alpha to zero (this pixel will not be seen)
else
curRGBA[3] = 255; //7) Set alpha to 255 (this pixel will be seen fully)
}
return alphabitmap;
}

void BmpImg::RESLoadImg(unsigned int idnumber, int num)
{
HBITMAP hBMP;
BITMAP BMP;

glGenTextures(1, &g_bmp[num]);

hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(idnumber), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
if (hBMP)
{
GetObject(hBMP,sizeof(BMP), &BMP);
unsigned char* ptrAlpha = Bmp24ToBmp32(BMP);
if(NULL == ptrAlpha)return;
// Buffer For Object Information
glPixelStorei(GL_UNPACK_ALIGNMENT,4); // Pixel Storage Mode (Word Alignment / 4 Bytes)
glBindTexture(GL_TEXTURE_2D, g_bmp[num]); // Bind Our Texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);

// Generate Mipmapped Texture (4 Bytes, Width, Height And Data From The BMP)
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, BMP.bmWidth, BMP.bmHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
delete[] ptrAlpha;
DeleteObject(hBMP); // Delete The Bitmap Object
}

}





[Edited by - Jack Sotac on March 28, 2006 7:34:14 PM]

Share this post


Link to post
Share on other sites
Seems correct and mainly the way I am loading my bitmaps from a file.

Can you put that in code form? I don't seem how you transfer the resource bitmap.

Share this post


Link to post
Share on other sites

GLuint BitmapToTexture(char* filename, COLORREF key/*= RGB(255, 0, 255)*/, unsigned char alpha/*=255*/, unsigned char key_alpha/*=0*/)
{
GLuint texture = 0; //the return value
long width = 0;
long height = 0;
unsigned long* data = BitmapToRGBA(filename, &width, &height, key, alpha, key_alpha);

//finally generate a texture
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
delete data;
return texture;
}

unsigned long int* BitmapToRGBA(char* filename, long int* width, long int* height, COLORREF key/*= RGB(255, 0, 255)*/, unsigned char alpha/*=255*/, unsigned char key_alpha/*=0*/)
{
BITMAP bmp; //used only to get bmp dimensions
HDC hDC = CreateCompatibleDC(NULL); //choose DC like the desktop
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, //load the bitmap
filename,
IMAGE_BITMAP,
0, 0,
LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);

if(hBitmap == NULL) //bitmap failed to load
{
return 0;
}
//get bitmap dimensions
GetObject(hBitmap, sizeof(BITMAP), &bmp);

//allocate memory for the bitmap
COLORREF *data = new COLORREF[bmp.bmWidth * bmp.bmHeight];

//put it into our device context for GetPixel calls
SelectObject(hDC, hBitmap);
for(int y = 0; y < bmp.bmHeight; y++)
{
for(int x = 0; x < bmp.bmWidth; x++)
{
data[x + (y*bmp.bmHeight)] = GetPixel(hDC, x, y);
if(key != data[x + (y*bmp.bmHeight)])
{
data[x + (y*bmp.bmHeight)] |= (alpha << 24);
}
else
{
data[x + (y*bmp.bmHeight)] |= (key_alpha << 24);
}


}
}
//if they care about the dimesions, give them back
if(width != NULL)
{
*width = bmp.bmWidth;
}
if(height != NULL)
{
*height = bmp.bmHeight;
}
return data;
}

Share this post


Link to post
Share on other sites

GLubyte *data = NULL;
if( BMP.bmBitsPixel == 3 ){
data = AlphaPixelize( BMP.bmBits, BMP.bmWidth, BMP.bmHeight );
} else return;

gluBuild2DMipmaps(GL_TEXTURE_2D, 4, BMP.bmWidth, BMP.bmHeight, GL_ABGR_EXT, GL_UNSIGNED_BYTE, data);
free( data );
DeleteObject(hBMP);




I just realized that bmWidthBytes is 4, so you can probably loop over the bits without creating a new BITMAP or GLubyte[]

Share this post


Link to post
Share on other sites
Here's my BMP loading module:


/*
Texture class
Relsoft (Richard Eric M. Lope BSN RN)
Uses SDL to load the image
Transparency is supported
*/

#ifndef TEXTURE_CPP
#define TEXTURE_CPP

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sdl\sdl.h>
#include <gl\gl.h>
#include <gl\glu.h>

#include "ctexture.h"

CTexture::CTexture()
{
}

CTexture::CTexture(char *file_name)
{
if ( load(file_name) == 0)
{
fprintf( stderr, "Can't load texture!!!%s\n",
SDL_GetError( ) );
SDL_Quit( );
exit (3);
}

}

CTexture::~CTexture()
{
}

GLuint CTexture::texID()
{
return texname;
}

int CTexture::load(char *file_name)
{

glGenTextures(1,&texname);
glBindTexture(GL_TEXTURE_2D,texname);
SDL_Surface *image = SDL_LoadBMP(file_name);
if (image == NULL)
{
SDL_FreeSurface(image);
return 0;
}

invert_sdl_image(image);

unsigned char *tex_RGBA;
tex_RGBA = convert_to_rgba(image);

glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);


glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_RGBA);
gluBuild2DMipmaps (GL_TEXTURE_2D, GL_RGBA,
image->w, image->h, GL_RGBA,
GL_UNSIGNED_BYTE, tex_RGBA);



//Free the surface since we don't have use for it anymore
SDL_FreeSurface (image);
delete [] tex_RGBA;
tex_RGBA = NULL;

}

int CTexture::set_trans_color(char sr=0, char sg=0, char sb=0)
{
r = sr;
g = sg;
b = sb;
}

int CTexture::destroy()
{

}
void CTexture::invert_sdl_image(SDL_Surface *image)
{
unsigned char *imgptr;
unsigned char *imgptr_below;
int texture_size;
int image_format;
image_format = image->format->BytesPerPixel;
texture_size = (image->w * image->h * image_format);
imgptr = (unsigned char*)image->pixels;
imgptr_below = (imgptr + texture_size);
imgptr_below = imgptr_below - ((image_format * image->w));


int i,j,x,y;


//Flip the image
for (y = 0; y < (image->h / 2); y++)
{
for (x = 0; x < image->w; x++)
{
for (j = 0; j < image_format; j++)
{
unsigned char c = *(imgptr + j);
*(imgptr + j) = *(imgptr_below + j);
*(imgptr_below + j) = c;
}
imgptr_below = imgptr_below + image_format;
imgptr = imgptr + image_format;
}
imgptr_below = imgptr_below - ((image_format*image->w) * 2);
}

//invert channels

imgptr = (unsigned char*)image->pixels;
for (y = 0; y < image->h; y++)
{
for (x = 0; x < image->w; x++)
{
unsigned char c = *(imgptr);
*(imgptr)=*(imgptr+2);
*(imgptr+2) = c;
imgptr = imgptr + image_format;
}
}

}
unsigned char* CTexture::convert_to_rgba(SDL_Surface *image)
{


unsigned char *imgptr;
int texture_size;
int image_format;
image_format = image->format->BytesPerPixel;
texture_size = (image->w * image->h * image_format);

unsigned char *texture_RGBA = new unsigned char[image->w * image->h * 4];

int i, j, x, y;
unsigned char ir, ig, ib;

imgptr = (unsigned char*)image->pixels;
i = 0;
for (y = 0; y < image->h; y++)
{
for (x = 0; x < image->w; x++)
{
ir = *(imgptr);
ig = *(imgptr + 1);
ib = *(imgptr + 2);
texture_RGBA[i + 0] = ir;
texture_RGBA[i + 1] = ig;
texture_RGBA[i + 2] = ib;
if ( (ir == 0) && (ig == 0) && (ib == 0) )
texture_RGBA[i + 3] = 0; //Transparent
else
texture_RGBA[i + 3] = 255; //Opaque

i = i + 4;
imgptr = imgptr + image_format;
}
}

return texture_RGBA;
}


#endif





Here's the header:




/*
Texture class
Relsoft (Richard Eric M. Lope BSN RN)
Uses SDL to load the image
Transparency is supported
*/

#ifndef TEXTURE_H
#define TEXTURE_H

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sdl\sdl.h>



class CTexture
{
public:
CTexture::CTexture();
CTexture::CTexture(char *file_name);
CTexture::~CTexture();
int load(char *file_name);
int set_trans_color(char sr, char sg, char sb);
int destroy();
GLuint texID();
private:
char r,g,b; //mask color
GLuint texname; //id
void invert_sdl_image(SDL_Surface *image);
unsigned char *convert_to_rgba(SDL_Surface *image);
};


#endif





Hope this helps. It uses SDL.

Share this post


Link to post
Share on other sites
Axesor, instead of blindly copying and pasting, perhaps you should try to actually DEBUG the code.

Share this post


Link to post
Share on other sites
You think I'd try that already?

PS: I am doing it in OpenGL, not SDL.

Share this post


Link to post
Share on other sites
Quote:
Original post by Axesor
You think I'd try that already?

Uh... yes, I think you should consider it at this point. (?)

Share this post


Link to post
Share on other sites
I have been on this forever and what I meant was that I have tried denugging it before I camplained <_<

Share this post


Link to post
Share on other sites
I liked Anist's method but when I put down 64L for long int* width, it said it could compare a const long with a long*

What does that mean??

Share this post


Link to post
Share on other sites
I was able to debug Anist's code but it shows nothing but a white square...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement