使用Core Graphics合成图像并保留Alpha通道

时间:2014-06-11 12:59:04

标签: ios opengl-es core-graphics fragment-shader

我有一个PNG(完整的alpha通道),我希望使用CGContextDrawImage合成到CGContextRef上。我想要合成RBG频道,但我也希望将源图像alpha频道复制过来。

最终我将最终的CGContextRef(以CGImageRef的形式)传递给GLKit,我希望使用片段着色器操作alpha通道以进行颜色着色。

不幸的是,在使用Core Graphics创建纹理图集时,我遇到了问题。似乎最终的CGImageRef无法从我的源图像复制alpha通道,并且是不透明的。我已附上我当前的合成代码,以及下面的测试图片副本:

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UInt8 * m_PixelBuf = malloc(sizeof(UInt8) * atlasSize.height * atlasSize.width * 4);

NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * atlasSize.width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(m_PixelBuf,
                                            atlasSize.width,
                                            atlasSize.height,
                                            bitsPerComponent,
                                            bytesPerRow,
                                            colorSpace
                                            kCGImageAlphaPremultipliedFirst);

CGContextDrawImage(context, CGRectMake(x, y, image.size.width, image.size.height), image.CGImage);

CGImageRef imgRef = CGBitmapContextCreateImage(context);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);

enter image description here

1 个答案:

答案 0 :(得分:2)

您在哪里找到使用CGBitmapContextCreate的此过程,因为这是最常见的问题之一:kCGImageAlphaPremultipliedFirst会将alpha设置为1,将PREMULTIPLY RGB设置为alpha值。

如果您正在使用Xcode请求命令,请单击kCGImageAlphaPremultipliedFirst并找到适当的替代项,例如kCGImageAlphaLast

添加使用alpha作为最后一个频道的示例:

+ (UIImage *)generateRadialGradient {
    int size = 256;
    uint8_t *buffer = malloc(size*size*4);
    memset(buffer, 255, size*size*4);
    for(int i=0; i<size; i++) {
        for(int j=0; j<size; j++) {
            float x = ((float)i/(float)size)*2.0f - 1.0f;
            float y = ((float)j/(float)size)*2.0f - 1.0f;
            float relativeRadius = x*x + y*y;
            if(relativeRadius >= 0.0 && relativeRadius < 1.0) { buffer[(i*size + j)*4 + 3] = (uint8_t)((1.0-sqrt(relativeRadius))*255.0); }
            else buffer[(i*size + j)*4 + 3] = 0;
        }
    }

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
                                                              buffer,
                                                              size*size*4,
                                                              NULL);

    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4*size;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big|kCGImageAlphaLast;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    CGImageRef imageRef = CGImageCreate(size,
                                        size,
                                        bitsPerComponent,
                                        bitsPerPixel,
                                        bytesPerRow,
                                        colorSpaceRef,
                                        bitmapInfo,
                                        provider,
                                        NULL,
                                        NO,
                                        renderingIntent);
    /*I get the current dimensions displayed here */
    return [UIImage imageWithCGImage:imageRef];
}

因此,此代码从代码创建径向渐变。内部部分是完全不透明的,当它从中心进一步变得透明时。

我们也可以使用kCGImageAlphaFirst,这会导致黄色渐变。 Alpha始终为1,只有第一个(红色)通道正在减少。结果是中间是白色,随着红色通道减少,黄色开始显示。