PNG alpha problem OGLES

Nibbie
Posts: 2
Joined: 2009.07
Post: #1
Hello!

I have problems displaying PNGs images with an alpha channel if the dimensions are small. Here is what the problem looks like:

[Image: bugg.jpg]

As you can see the apple should have transparency around it but instead there are lots of garbage pixels. The apple has a dimension of 32x32. I have no problem displaying larger images.

My image is loaded with this function:
Code:
GLuint loadTexture(NSString *filename){
    GLuint location;
    CGImageRef textureImage = [UIImage imageNamed:filename].CGImage;
        
    if (textureImage == nil) {
        NSLog(@"Failed to load texture image");
        return false;
    }
        
    NSInteger texWidth = CGImageGetWidth(textureImage);
    NSInteger texHeight = CGImageGetHeight(textureImage);
        
    GLubyte *textureData = (GLubyte *)malloc(texWidth * texHeight * 4);
    memset(textureData,0,sizeof(textureData));
        
    CGContextRef textureContext = CGBitmapContextCreate(textureData,texWidth, texHeight,8, texWidth*4,CGImageGetColorSpace(textureImage),kCGImageAlphaPremultipliedLast);
        
    // Rotate the image
    CGContextTranslateCTM(textureContext, 0, texHeight);
    CGContextScaleCTM(textureContext, 1.0, -1.0);
        
    CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)texWidth, (float)texHeight), textureImage);
    CGContextRelease(textureContext);
    glGenTextures(1, &location);
    glBindTexture(GL_TEXTURE_2D, location);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
        
    free(textureData);
    
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    return location;
}

Any help appreciated.
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #2
Change the malloc to calloc.
Quote this message in a reply
Nibbie
Posts: 2
Joined: 2009.07
Post: #3
Thanks, it worked like a charm. Seems my memset was a bit of... thanks again Smile
Quote this message in a reply
Member
Posts: 35
Joined: 2009.01
Post: #4
I had the same problem with a 16x16 image.

Was gonna grudgingly enlarge it to 64x64 despite it having an onscreen diameter of 10 pixels, but this saved me the trouble.

Thanks!
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #5
MrOlofsson Wrote:Thanks, it worked like a charm. Seems my memset was a bit of... thanks again Smile

So you know the trouble was this:
Code:
memset(textureData,0,sizeof(textureData));

sizeof(textureData) isn't doing what you think it's doing. I'm not at a machine with a compiler right now, but I think that will return the size of the pointer, not the size of the array pointed to by said pointer.

You'd want:
Code:
memset(textureData,0,sizeof(texWidth * texHeight * 4));

Nonetheless calloc is simpler, might even be faster.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #6
TomorrowPlusX Wrote:You'd want:
Code:
memset(textureData,0,sizeof(texWidth * texHeight * 4));

Won't work either. I think you mean:

Code:
memset(textureData, 0, texWidth * texHeight * 4);
Quote this message in a reply
Member
Posts: 166
Joined: 2009.04
Post: #7
ThemsAllTook Wrote:Won't work either. I think you mean:

Code:
memset(textureData, 0, texWidth * texHeight * 4);

Or to be even more verbatim (and avoid polluting code with magic numbers):

Code:
memset(textureData, 0, texWidth * texHeight * sizeof(unsigned int));
Quote this message in a reply
Member
Posts: 245
Joined: 2005.11
Post: #8
warmi Wrote:Or to be even more verbatim (and avoid polluting code with magic numbers):

Code:
memset(textureData, 0, texWidth * texHeight * sizeof(unsigned int));

Nope - that would be
Code:
memset(textureData, 0, texWidth * texHeight * 4 * sizeof(UInt8));
But what's the point of using sizeof(UInt8) when the answer's in the name?
Quote this message in a reply
Member
Posts: 166
Joined: 2009.04
Post: #9
backslash Wrote:Nope - that would be
Code:
memset(textureData, 0, texWidth * texHeight * 4 * sizeof(UInt8));
But what's the point of using sizeof(UInt8) when the answer's in the name?

Depends how you look at it ... I tend to look at RGBA as an unsigned int as opposed to 4 unsigned chars.
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #10
Looks like fun, I wanna play too! How about:

Code:
#define BYTES_PER_PIXEL    4
memset(textureData, 0, texWidth * texHeight * BYTES_PER_PIXEL);

or maybe better yet:

Code:
#define FOUR_BYTES_PER_PIXEL    4
memset(textureData, 0, texWidth * texHeight * FOUR_BYTES_PER_PIXEL);
Quote this message in a reply
Member
Posts: 166
Joined: 2009.04
Post: #11
AnotherJake Wrote:Looks like fun, I wanna play too! How about:

Code:
#define BYTES_PER_PIXEL    4
memset(textureData, 0, texWidth * texHeight * BYTES_PER_PIXEL);

or maybe better yet:

Code:
#define FOUR_BYTES_PER_PIXEL    4
memset(textureData, 0, texWidth * texHeight * FOUR_BYTES_PER_PIXEL);

Hehe ... you know , whatever you put in there it is still better than just a random magic number.
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #12
I suppose if you want to discourage "magic" numbers then you really should use descriptive constants, rather than sizeof(unsigned int), since that doesn't really say anything either Rasp
Quote this message in a reply
Member
Posts: 166
Joined: 2009.04
Post: #13
AnotherJake Wrote:I suppose if you want to discourage "magic" numbers then you really should use descriptive constants, rather than sizeof(unsigned int), since that doesn't really say anything either Rasp

Well, in this particular context I think it is more than enough, it says that the basic unit you are dealing with is an unsigned int.
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #14
Maybe unsigned int means it represents a four byte pixel to you, but not necessarily to someone else. If you look at it like that, unsigned int is only as helpful as the number 4.

Either one would work for me, since I'd understand the context regardless.
Quote this message in a reply
Member
Posts: 245
Joined: 2005.11
Post: #15
Quote:Well, in this particular context I think it is more than enough, it says that the basic unit you are dealing with is an unsigned int.
No you're not - RGBA with unsigned bytes is 4 separate single bytes, which happens to be the same size as an unsigned int on many systems, but you are making the very mistake you are telling us all to avoid. I like Jake's solution.
Quote this message in a reply
Post Reply