04-19-2010, 04:42 AM
#1 (permalink )
Divine avenger
Join Date: Nov 2009
Location: Vic, Catalunya (Spain)
Posts: 320
OpenGL shows .PNG halos?
Hi there!
I'm working in an OpenGL application and when using .PNG images I've seen that OpenGL seems to draw a non-existing halo rounding the transparent part of the image... Why is this happening? Is there any way to avoid this halo? Here's the method I'm using to load an image:
Code:
- (id) initWithImage:(UIImage *)uiImage
{
NSUInteger width,
height,
i;
CGContextRef context = nil;
void* data = nil;;
CGColorSpaceRef colorSpace;
void* tempData;
unsigned int* inPixel32;
unsigned short* outPixel16;
BOOL hasAlpha;
CGImageAlphaInfo info;
CGAffineTransform transform;
CGSize imageSize;
Texture2DPixelFormat pixelFormat;
CGImageRef image;
UIImageOrientation orientation;
BOOL sizeToFit = NO;
image = [uiImage CGImage];
orientation = [uiImage imageOrientation];
if(image == NULL) {
[self release];
NSLog(@"Image is Null");
return nil;
}
info = CGImageGetAlphaInfo(image);
hasAlpha = ((info == kCGImageAlphaPremultipliedLast) || (info == kCGImageAlphaPremultipliedFirst) || (info == kCGImageAlphaLast) || (info == kCGImageAlphaFirst) ? YES : NO);
pixelFormat = kTexture2DPixelFormat_RGBA8888;
imageSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
transform = CGAffineTransformIdentity;
width = imageSize.width;
if((width != 1) && (width & (width - 1))) {
i = 1;
while((sizeToFit ? 2 * i : i) < width)
i *= 2;
width = i;
}
height = imageSize.height;
if((height != 1) && (height & (height - 1))) {
i = 1;
while((sizeToFit ? 2 * i : i) < height)
i *= 2;
height = i;
}
while((width > kMaxTextureSize) || (height > kMaxTextureSize)) {
width /= 2;
height /= 2;
transform = CGAffineTransformScale(transform, 0.5, 0.5);
imageSize.width *= 0.5;
imageSize.height *= 0.5;
}
switch(pixelFormat) {
case kTexture2DPixelFormat_RGBA8888:
colorSpace = CGColorSpaceCreateDeviceRGB();
data = malloc(height * width * 4);
context = CGBitmapContextCreate(data, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
break;
case kTexture2DPixelFormat_RGB565:
colorSpace = CGColorSpaceCreateDeviceRGB();
data = malloc(height * width * 4);
context = CGBitmapContextCreate(data, width, height, 8, 4 * width, colorSpace, kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
break;
case kTexture2DPixelFormat_A8:
data = malloc(height * width);
context = CGBitmapContextCreate(data, width, height, 8, width, NULL, kCGImageAlphaOnly);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid pixel format"];
}
CGContextClearRect(context, CGRectMake(0, 0, width, height));
CGContextTranslateCTM(context, 0, height - imageSize.height);
if(!CGAffineTransformIsIdentity(transform))
CGContextConcatCTM(context, transform);
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
//Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
if(pixelFormat == kTexture2DPixelFormat_RGB565) {
tempData = malloc(height * width * 2);
inPixel32 = (unsigned int*)data;
outPixel16 = (unsigned short*)tempData;
for(i = 0; i < width * height; ++i, ++inPixel32)
*outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0);
free(data);
data = tempData;
}
self = [self initWithData:data pixelFormat:pixelFormat pixelsWide:width pixelsHigh:height contentSize:imageSize];
CGContextRelease(context);
free(data);
return self;
}
- (id) initWithData:(const void*)data pixelFormat:(Texture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size
{
GLint saveName;
if((self = [super init])) {
glGenTextures(1, &_name);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &saveName);
glBindTexture(GL_TEXTURE_2D, _name);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
switch(pixelFormat) {
case kTexture2DPixelFormat_RGBA8888:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
break;
case kTexture2DPixelFormat_RGB565:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
break;
case kTexture2DPixelFormat_A8:
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@""];
}
glBindTexture(GL_TEXTURE_2D, saveName);
_size = size;
_width = width;
_height = height;
_format = pixelFormat;
_maxS = size.width / (float)width;
_maxT = size.height / (float)height;
}
return self;
}
Anyone know anything about this?
Thanks in advance!
04-19-2010, 10:01 AM
#2 (permalink )
Pro. Game Developer
iPhone Dev SDK Supporter
Join Date: Feb 2009
Location: ¿La Islas Hermosas?
Posts: 2,178
What you're seeing is probably the known PNG premultiplied alpha issue. Search the forum or Google for more information. My solution was to write and use my own PNG loader using libpng (free open source).
04-20-2010, 04:09 AM
#3 (permalink )
Divine avenger
Join Date: Nov 2009
Location: Vic, Catalunya (Spain)
Posts: 320
Hi Kalimba!
Thanks for your reply, it's solved!
I've searched over the net and I've found how to prevent OpenGL to do this. In the OpenGL initialization, you may have this:
Code:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Well, it's that simple that you must change this line for this one:
Code:
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
And voilà, no halo is shown then!
Hope it helps someone with the same problem!
Thread Tools
Display Modes
Linear Mode
Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
» Advertisements
» Online Users: 345
20 members and 325 guests
ADY , Alsahir , Dani77 , e2applets , JasonR , keeshux , linkmx , mer10 , Monstertaco , piesia , prchn4christ , Promo Dispenser , Robiwan , sebasx , sly24 , Touchmint , twerner , zulfishah
Most users ever online was 1,187, 10-11-2011 at 08:09 AM.
» Stats
Members: 158,880
Threads: 89,228
Posts: 380,760
Top Poster: BrianSlick (7,129)
Welcome to our newest member, @sandris