Joe
Joe

Reputation: 404

CIImage creation with initWithTexture

I'm trying to read texture data using CIImage initWithTexture under iOS 9.0 but all I'm getting back is a black image. I've even tried to load the texture first and then read it back but still a black image.

Here's my code:

    CGImageRef brushImage;
    CGContextRef brushContext;
    GLubyte *brushData;
    size_t width, height;
    GLUint texId;
    CIImage *cimage;

    //
    // Here I'm just loading an image and preparing it as a bitmap.
    //
    brushImage = [UIImage imageNamed:"brush"].CGImage;
    width = CGImageGetWidth(brushImage);
    height = CGImageGetHeight(brushImage);
    brushData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));
    brushContext = CGBitmapContextCreate(brushData, width, height, 8, width * 4, CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast);
    CGContextDrawImage(brushContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), brushImage);


    //
    // Here I create the texture I want to use.
    // 
    glGenTextures(1, &texId);
    glBindTexture(GL_TEXTURE_2D, texId);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    //
    // Load in my bitmap to the texture.
    //
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)width, (int)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData);

    //
    // Now, try to read the texture back out.
    //
    cimage = [[CIImage alloc] initWithTexture:texId size:CGSizeMake(width, height) flipped:YES colorSpace:CGImageGetColorSpace(brushImage)];

    return [[UIImage alloc] initWithCIImage: cimage];

The UIImage return seems to have the correct size -- but the image appears to be blank (all black) although the source image (a PNG) definitely has some contents in it. Not sure what I am doing wrong. Any help please? Thanks!!

Upvotes: 0

Views: 699

Answers (1)

l-l
l-l

Reputation: 3854

I was able to make this work by using GLKTextureLoader from GLKit, I created the following method to create texture backed CIImage from an image:

- (CIImage *)createImageFromPath:(NSString *)filePath{
     NSError *error;
     GLKTextureInfo *texture = [GLKTextureLoader textureWithContentsOfFile:filePath options:@{GLKTextureLoaderApplyPremultiplication : @YES} error:&error];
     glBindTexture(texture.target, texture.name);

     return [CIImage imageWithTexture:texture.name size:CGSizeMake(texture.width, texture.height) flipped:YES colorSpace:nil];
}

In order for this to work you need to make sure you need to set the EAGLContext before calling this function. You also need to create a CIContext based on the same EAGLContext to render the CIImage

EAGLContext *eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
CIContext *ciContext = [CIContext contextWithEAGLContext:eaglContext options:@{kCIContextWorkingColorSpace : [NSNull null]}];
[EAGLContext setCurrentContext:eaglContext];

CIImage *image = [self createImageFromPath:[[NSBundle mainBundle] pathForResource:@"brush" ofType:@"png"]];

You can then apply your filters to this CIImage and render the image using the ciContext.

Upvotes: 2

Related Questions