Domanda

I am using [uiImage drawAtPoint] to draw a new image. But it turns out that the color gets changed. My original image uiImage is red while the generated image newImage is blue. Here is my code:

UIImage* uiImage = [UIHelper loadImage:fileName];
NSString *text = [ApplicationSettings instance].user.name;
UIGraphicsBeginImageContext(uiImage.size);
[uiImage drawAtPoint: CGPointZero];
[text drawAtPoint: CGPointMake(10, 10) withFont: [UIFont systemFontOfSize: 12]];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return [Texture createTexture: newImage];

And in [Texture createTexture]:

+ (Texture*) createTextureWithImage:(UIImage*)image {
    Texture* tex = [[[Texture alloc] init] autorelease];
    if ([tex loadImage:image])
        return tex;
    else {
        NSLog(@"Failed to load image %@", image);
        return nil;
    }
}

- (BOOL)loadImage:(UIImage *)image {
    BOOL ret = NO;

    if (image) {
        // Get the inner CGImage from the UIImage wrapper
        CGImageRef cgImage = image.CGImage;

        // Get the image size
        width = CGImageGetWidth(cgImage);
        height = CGImageGetHeight(cgImage);

        // Record the number of channels
        channels = CGImageGetBitsPerPixel(cgImage)/CGImageGetBitsPerComponent(cgImage);

        // Generate a CFData object from the CGImage object (a CFData object represents an area of memory)
        CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));

        // Copy the image data for use by Open GL
        ret = [self copyImageDataForOpenGL: imageData];
        CFRelease(imageData);
    }

    return ret;
}

And in [texture copyImageDataForOpenGL]

- (BOOL)copyImageDataForOpenGL:(CFDataRef)imageData {
    if (pngData) {
        free(pngData);
    }

    pngData = (unsigned char*)malloc(width * height * channels);
    const int rowSize = width * channels;
    const unsigned char* pixels = (unsigned char*)CFDataGetBytePtr(imageData);

    // Copy the row data from bottom to top
    for (int i = 0; i < height; ++i) {
        memcpy(pngData + rowSize * i, pixels + rowSize * (height - 1 - i), width * channels);
    }

    return YES;
}

I guess that the generated image uses RGB order while the original one uses the reversed order . This is because the white and black color remains the same.

EDIT

I am using OpenGL ES to render this texture.

return [Texture createTexture: uiImage]; instead of return [Texture createTexture: newImage] works perfectly but I want to draw the text on uiImage.

I have tested UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil); and the saved image is correct.

I printed CGImageGetBitmapInfo(uiImage.CGImage)) and CGImageGetBitmapInfo(newImage.CGImage), and they are NOT the same!

È stato utile?

Soluzione

This my current and correct version of copyImageDataForOpenGL

- (BOOL)copyImageDataForOpenGL:(CGImageRef)image {
    if (pngData) {
        free(pngData);
    }

    pngData = (GLubyte*)malloc(width * height * channels);
    const int rowSize = width * channels;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    NSUInteger bytesPerPixel = channels;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(pngData, width, height,
                                                 bitsPerComponent, bytesPerRow, colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextClearRect(context, CGRectMake(0, 0, width, height));
    CGContextTranslateCTM(context, 0,0);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);

    [ARRenderer flipRGBData: pngData bytesPerRow:bytesPerRow height:height];
    return YES;
}

where [ARRenderer flipRGBData] is defined as

+ (void)flipRGBData:(GLubyte*)data bytesPerRow:(int)bytesPerRow height:(int)height {
    GLubyte* swp = (GLubyte*)malloc(bytesPerRow);
    for (int h = 0; h < height / 2; h++) {
        memcpy(swp, data + (height - 1 - h) * bytesPerRow, bytesPerRow);
        memcpy(data + (height - 1 - h) * bytesPerRow, data + h * bytesPerRow, bytesPerRow);
        memcpy(data + h * bytesPerRow, swp, bytesPerRow);
    }
    free(swp);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top