convert $file -alpha extract $mask.png
Apple's documentation contains pretty nice articles on image masks, and tells you about the 'CGImageCreateWithMask' that seems to do exactly what you want. But there are two catches. First of all, the masked image should already have alpha channel (well, at least the various sources on the interwebs suggest so). The more important problem is that '[GLKTextureLoader textureWithCGImage: ....]' always dropped the alpha channel.
The solution I used is to create an offscreen Quartz bitmap context, clip it with an image mask, draw the opaque image, create image from the offscreen context and load that one. The other catch I discovered is that GLKTextureLoader ignores endianess information and you have to create the offscreen context with explicit 'kCGBitmapByteOrder32Little' .
Here comes the code. Please note that I am not really an experienced ObjC developer, so do not consider it 'best practices'.
NSString* maskFile=; NSString* dataFile= ; //load data CGDataProviderRef dataProvider=CGDataProviderCreateWithFilename([dataFile cStringUsingEncoding:NSASCIIStringEncoding]); CGImageRef dataImage=CGImageCreateWithJPEGDataProvider(dataProvider, NULL, true, kCGRenderingIntentDefault); int width=CGImageGetWidth(dataImage); int height=CGImageGetHeight(dataImage); //load mask CGDataProviderRef maskProvider=CGDataProviderCreateWithFilename([maskFile cStringUsingEncoding:NSASCIIStringEncoding]); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGImageRef maskImage=CGImageCreateWithPNGDataProvider(maskProvider, NULL, false, kCGRenderingIntentDefault); //create the masked image CGContextRef offscreenContext = CGBitmapContextCreate(NULL, width, height,8,width*4, colorSpace, kCGImageAlphaPremultipliedFirst|kCGBitmapByteOrder32Little); CGContextClipToMask(offscreenContext, CGRectMake(0,0,width,height), maskImage); CGContextDrawImage(offscreenContext, CGRectMake(0, 0, width, height), dataImage); CGImageRef resultImage = CGBitmapContextCreateImage(offscreenContext); CGContextRelease(offscreenContext); //CGImageRef resultImage=dataImageWithAlpha; NSError* error; NSDictionary* opts=[NSDictionary new]; GLKTextureInfo* info=[GLKTextureLoader textureWithCGImage:resultImage options:opts error:&error]; if(info==nil){ NSLog(@"Error during loading image %@. Exception %@ occured.",resultImage,error); } [opts release]; //if you are going to load larger images, it might be worth releasing the intermediate images //as soon as they are not needed CGDataProviderRelease(maskProvider); CGDataProviderRelease(dataProvider); CGImageRelease(dataImage); CGImageRelease(maskImage); CGImageRelease(resultImage); CGColorSpaceRelease(colorSpace); return info;
Žádné komentáře:
Okomentovat