UIImage字节顺序已更改

时间:2013-03-08 10:34:17

标签: iphone ios opengl-es uiimage cgimage

我正在使用[uiImage drawAtPoint]来绘制新图片。但事实证明颜色变了。我的原始图片uiImage为红色,而生成的图片newImage为蓝色。这是我的代码:

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];

[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;
}

并在[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;
}

我猜测生成的图像使用RGB顺序,而原始图像使用反转顺序。这是因为白色和黑色保持不变。

修改

我正在使用OpenGL ES来渲染这个纹理。

return [Texture createTexture: uiImage];代替return [Texture createTexture: newImage]完美无缺,但我想在uiImage上绘制文字。

我测试了UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil);,保存的图片是正确的。

我打印了CGImageGetBitmapInfo(uiImage.CGImage))CGImageGetBitmapInfo(newImage.CGImage),它们不一样!

1 个答案:

答案 0 :(得分:1)

这是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;
}

其中[ARRenderer flipRGBData]定义为

+ (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);
}