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

iPhone上的CoreGraphics。加载带有预乘alpha的PNG文件的正确方法是什么?,iphone,core-graphics,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, kCGImageAlphaPremult

对于我的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-kcGimagealpha预乘Last-我是否无意中告诉CoreGraphics将r g b通道乘以alpha,或者-我假设的-我只是指示传入图像的格式已经预乘了alpha

谢谢, 道格

通过指定预乘alpha-kcGimagealpha预乘Last-我是否无意中告诉CoreGraphics将r g b通道乘以alpha,或者-我假设的-我只是指示传入图像的格式已经预乘了alpha

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

这意味着缓冲区中的像素将被预乘,而不是两次,但它们将在上下文缓冲区中被预乘,无论源颜色是否被预乘(如果是,则无需再次乘法;如果不是,则将第一次乘法)

我对OpenGL的了解还不够,不知道这是否是一个问题,如果是的话,这段代码可能没有解决方案:至少在Mac上


您可以改为尝试。

对于以后遇到此问题的任何人,请参考以下关于如何取消预乘的示例:

    /////// .... 
    /////// 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.);
        }
    }
//。。。。
///////将图像加载到此处的imageRef中
///////例如,使用CGImageSourceCreateWithURL();和CGImageSourceCreateImageAtIndex();在OSX上
///////或者,通过访问UIImage的CGImage属性
///////  
///////然后提取bitsPerComponent、bytesPerRow和颜色空间
/////// .... 
//将CG图像绘制到字节数组
CGContextRef bitmapContext=CGBitmapContextCreate(img->data,
img->w,img->h,
比特组件,
拜特斯佩罗,
空间
KCGIMAGEAlphaPremultipledLast);
CGContextDrawImage(位图上下文,CGRectMake(0.0,0.0,(浮点)img->w,(浮点)img->h),imageRef);
CGContextRelease(bitmapContext);
//让我们撤销预乘
对于(int i=0;ih;i+=4)
{
对于(int j=0;jdata[i+j]=img->data[i+j]/(img->data[i+3]/255.);
}
}

谢谢彼得。实际上我更喜欢预装,因为我是一个搬运工/达夫(预装方法的发明者)爱好者。不幸的是,OpenGL不是premult,所以我需要自己处理。干杯。如果alpha为0,这将不起作用。事实上,对于alpha接近0的任何像素,恢复原始rgb越来越困难。你无法精确地取消alpha的预乘。但是,你可以用第二个版本的图像替换rgb没有alpha通道的图像。这可能有效。例如:
img->data[i+j]=img2->data[i+j]