【问题标题】:UIImage byte order was changed [closed]UIImage 字节顺序已更改 [关闭]
【发布时间】:2013-03-08 10:34:16
【问题描述】:

我正在使用[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),它们不一样!

【问题讨论】:

  • 我建议使用 UIGraphicsBeginImageContextWithOptions(uiImage.size, NO, 0.0);而不是 UIGraphicsBeginImageContext(uiImage.size);为了支持视网膜屏幕渲染。但是,这不应该是您的图像渲染翻转颜色的原因。我很想稍后再深入研究一下——尽快给你回信(只要它还没有解决;))。
  • @Markus 在使用UIGraphicsBeginImageContextWithOptions时不起作用。
  • 您根本没有看到任何图像?请尝试使用不透明的 YES 而不是 NO(第二个参数),如果您不介意,请分享结果。
  • @Markus 我的意思是它保持不变。

标签: iphone ios opengl-es uiimage cgimage


【解决方案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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    相关资源
    最近更新 更多