ios - 使用 Core Graphics 合成图像并保留 alpha channel

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

我有一个 PNG(带有 alpha channel ),我希望使用 CGContextDrawImage 将其合成到 CGContextRef 上。我希望合成 RBG channel ,但我也希望将源图像的 alpha channel 也复制过来。

最终,我会将最终的 CGContextRef(以 CGImageRef 的形式)传递给 GLKit,我希望在其中使用片段着色器来操纵 alpha channel 以进行颜色着色。

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

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

最佳答案

你们在哪里可以找到使用 CGBitmapContextCreate 的过程,因为这是最常见的问题之一:kCGImageAlphaPremultipliedFirst 会将 alpha 设置为 1,并使用 alpha PREMULTIPLY RGB值(value)。

如果您使用的是 Xcode,请使用命令单击 kCGImageAlphaPremultipliedFirst 并找到合适的替换项,例如 kCGImageAlphaLast

添加一个使用 alpha 作为最后一个 channel 的例子:

+ (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,只有第一个(红色) channel 正在减少。结果是中间是白色,随着红色 channel 的减少,黄色开始显示。

关于ios - 使用 Core Graphics 合成图像并保留 alpha channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24163596/

相关文章:

android - 从 Activity 返回时没有当前的 openGL 上下文?

c++ - 在 OpenGL 中屏蔽掉地形表面的一个区域

ios - 如何更快地将 View 渲染成图像?

ios - 无法为没有参数的类型调用初始值设定项 - Swift

ios - 使用 Xamarin UITest 在 iOS 选择器中选择一个项目?

ios - VNImageBasedRequest regionOfInterest 不在规范化范围内

ios - 如何发现 OpenGL ES 帧速率是否卡顿 - 没有仪器?

iphone - 有什么技巧可以绘制动画路径吗?

iphone-sdk-3.0 - 描边和填充的区别?

iphone - Facebook 连接 Batch 请求和 FQL 错误问题