iPhone上的CoreGraphics。使用预乘的alpha加载PNG文件的正确方法是什么?

时间:2010-03-29 13:21:57

标签: iphone core-graphics

对于我的iPhone 3D应用程序,我目前正在使用CoreGraphics来加载预先乘以alpha的png文件。以下是要点:

// load a 4-channel rgba png file with pre-multiplied alpha. 
CGContextRef context =  
CGBitmapContextCreate(data, width, height, 8, num_channels * width, colorSpace, 
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 

// Draw the image into the context
CGRect rect =  CGRectMake(0, 0, width, height); 
CGContextDrawImage(context, rect, image); 
CGContextRelease(context); 

然后我继续使用数据作为OpenGL中的纹理。

我的问题:通过指定预乘的alpha - kCGImageAlphaPremultipliedLast - 我 - 无意中 - 告诉CoreGraphics将rgb通道乘以alpha或 - 我所假设的 - 我只是指出输入图像的格式已经预先乘以alpha?

谢谢, 道格

2 个答案:

答案 0 :(得分:4)

  

通过指定预乘的alpha - kCGImageAlphaPremultipliedLast - 我 - 无意中 - 告诉CoreGraphics将rgb通道乘以alpha或 - 我所假设的 - 我只是表明输入图像的格式已预先乘以alpha?

都不是。您指定了目标(上下文)的格式,而不是源。源 - 图像对象 - 知道它的像素的颜色是否被预乘,并且当它将源图像绘制到上下文中时,Quartz将使用该知识做正确的事情。

这意味着缓冲区中的像素将被预乘 - 而不是两次,但是它们将在上下文缓冲区中预乘,无论源颜色是否被预乘(如果它们是,则不需要)再次繁殖;如果不是,那么它将第一次成倍增加。)

我不知道OpenGL知道这是否有问题,如果是,可能没有解决此代码的方法:在Mac上,至少Quartz does not support unpremultiplied colors in bitmap contexts

您可以尝试this storage format

答案 1 :(得分:2)

为了将来参考绊到这个问题的人,这里有一个关于如何去预乘的例子:

    /////// .... 
    /////// load the image into imageRef up here
    /////// e.g. with CGImageSourceCreateWithURL(); and CGImageSourceCreateImageAtIndex(); on OS X
    /////// or, by accessing CGImage property of UIImage 
    ///////  
    /////// then extract bitsPerComponent, bytesPerRow and color space 
    /////// .... 


    // draw CG image to a byte array
    CGContextRef bitmapContext = CGBitmapContextCreate(img->data,
                                                       img->w, img->h,
                                                       bitsPerComponent, 
                                                       bytesPerRow,
                                                       space,
                                                       kCGImageAlphaPremultipliedLast);

    CGContextDrawImage(bitmapContext,CGRectMake(0.0, 0.0, (float)img->w, (float)img->h),imageRef);
    CGContextRelease(bitmapContext);

    // let's undo premultiplication
    for(int i=0; i < bytesPerRow * img->h; i+=4)
    {
        for(int j=0; j<3; j++)
        {
            img->data[i+j] = img->data[i+j] / (img->data[i+3]/255.);
        }
    }