CoreGraphics 上下文中的透明度/alpha(iphone、objc)

发布于 2024-09-16 11:52:15 字数 1433 浏览 6 评论 0 原文

我目前正在为 iPhone 制作一个基本的图像编辑器。

我从 UIImage 获取 CGImageRef 并使用以下代码为其创建上下文

origImage = result.CGImage;

Iheight = CGImageGetHeight(origImage);
Iwidth = CGImageGetWidth(origImage);
IcolorSpace = CGColorSpaceCreateDeviceRGB();
IrawData = malloc(Iheight * Iwidth * 4);
IbytesPerPixel = 4;
IbytesPerRow = IbytesPerPixel * Iwidth;
IbitsPerComponent = 8;
Icontext = CGBitmapContextCreate(IrawData, Iwidth, Iheight, IbitsPerComponent,
                                 IbytesPerRow, IcolorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big
                                 );
//[bytesPerRow release];
CGContextSetBlendMode(Icontext, kCGBlendModeCopy);
CGContextDrawImage(Icontext, CGRectMake(0,0,Iwidth,Iheight),  origImage);

,然后循环遍历像素

for (int x=0; x<Iwidth; x++) {
    for (int y=0; y<Iheight; y++) {
            //and  set the alpha component to 0
            int byteIndex = (y*IbytesPerRow) + x*IbytesPerPixel;

            IrawData[byteIndex+3] = 0;

            }
}

,然后从上下文创建 CGImageRef

    CGImageRef imagea = CGBitmapContextCreateImage(Icontext);

并添加 CGImage到 UIImage 并分配给 UIImageView

问题是 alpha 的变化不会影响结果图像

而改变像素的颜色

IrawData[byteIndex+(0/1/2)]

如果我随着颜色的变化 ,但是我仍然可以不要改变像素的 alpha

谢谢你,

nonono

I am currently making a basic image editor for iphone.

I take the CGImageRef from a UIImage and create a context for it using the following code

origImage = result.CGImage;

Iheight = CGImageGetHeight(origImage);
Iwidth = CGImageGetWidth(origImage);
IcolorSpace = CGColorSpaceCreateDeviceRGB();
IrawData = malloc(Iheight * Iwidth * 4);
IbytesPerPixel = 4;
IbytesPerRow = IbytesPerPixel * Iwidth;
IbitsPerComponent = 8;
Icontext = CGBitmapContextCreate(IrawData, Iwidth, Iheight, IbitsPerComponent,
                                 IbytesPerRow, IcolorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big
                                 );
//[bytesPerRow release];
CGContextSetBlendMode(Icontext, kCGBlendModeCopy);
CGContextDrawImage(Icontext, CGRectMake(0,0,Iwidth,Iheight),  origImage);

I then loop through the pixels

for (int x=0; x<Iwidth; x++) {
    for (int y=0; y<Iheight; y++) {
            //and  set the alpha component to 0
            int byteIndex = (y*IbytesPerRow) + x*IbytesPerPixel;

            IrawData[byteIndex+3] = 0;

            }
}

and then create a CGImageRef from the context with

    CGImageRef imagea = CGBitmapContextCreateImage(Icontext);

and add the CGImage to a UIImage and assign to a UIImageView

The problem is that the change of alpha isn't effecting the resultant image

if I change the colour of the pixels with

IrawData[byteIndex+(0/1/2)]

the colour changes, but I still can't change the alpha of the pixel

Thank you,

nonono

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

表情可笑 2024-09-23 11:52:15

不要忘记在更改 Alpha 之前取消预乘颜色,然后重新预乘它们。

预乘颜色(通常称为“预乘 alpha”,这是一种误导)意味着存储的颜色分量已经乘以 alpha,以便于合成。通常的合成(源覆盖)操作如下所示:

result = (source.rgb * source.a) + (destination.rgb * (1.0 - destination.a));

预乘意味着第一个乘法已经完成,因此可以跳过:

result =  source.rgb             + (destination.rgb * (1.0 - destination.a));

当您更改 alpha 而不更改预乘颜色分量时,结果不会改变 — 当您绘制图像,它看起来没有什么不同,因为颜色仍然预先乘以旧的 Alpha。

因此,在更改 alpha 之前,您需要取消颜色的预乘,即将每种颜色除以 alpha(之前是相乘的,所以现在必须执行相反的操作)。然后,更改 Alpha 后,将颜色预乘以新的 Alpha。

当然,这意味着当将 alpha 更改为零时,所有颜色都会变黑(r=g=b=0)。因此,如果用户可能想将其更改回来,请确保保留原始图像。

以用户想要的任何 alpha 值绘制原始图像(不对其进行任何 alpha 更改)可能会更有效,而且肯定会更容易。您可以通过 在绘制图像之前更改显示上下文的全局 alpha

Don't forget to unpremultiply the colors before changing the alpha, and re-premultiply them afterward.

Premultiplied color (often called “premultiplied alpha”, which is misleading) means that the color components are stored already multiplied by the alpha, to ease compositing. The usual compositing (source-over) operation looks like this:

result = (source.rgb * source.a) + (destination.rgb * (1.0 - destination.a));

Premultiplication means that the first multiplication is already done, so it can be skipped:

result =  source.rgb             + (destination.rgb * (1.0 - destination.a));

When you change the alpha without changing the premultiplied color components, the result doesn't change—when you draw the image, it will look no different, because the colors are still premultiplied by the old alpha.

So, you need to unpremultiply the colors—that is, divide each one by the alpha (as previously it was multiplied, so you must now do the inverse)—before you change the alpha. Then, after changing the alpha, premultiply the colors by the new alpha.

Of course, this means that when changing the alpha to zero, all the colors will go black (r=g=b=0). So, make sure you keep the original image if the user might want to change it back.

It would probably be more effective, and would certainly be easier, to just draw the original image (without any alpha changes made to it) at whatever alpha the user wants. You can do this by changing your display context's global alpha before you draw the image.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文