CGImageCreateWithMask 使用图像作为蒙版

发布于 2024-09-03 21:58:08 字数 2672 浏览 1 评论 0原文

我正在尝试使用图像(270 度的圆,类似于 pacman 徽标,绘制为 Core Graphics)来创建蒙版。我正在做的就是这个

1。创建核心图形路径

    CGContextSaveGState(context);
    CGContextBeginPath(context);
    CGContextMoveToPoint(context,circleCenter.x,circleCenter.y);
    //CGContextSetAllowsAntialiasing(myBitmapContext, YES);
    CGContextAddArc(context,circleCenter.x, circleCenter.y,circleRadius,startingAngle, endingAngle, 0); // 0 is counterclockwise
    CGContextClosePath(context);
    CGContextSetRGBStrokeColor(context,1.0,0.0,0.0,1.0);
    CGContextSetRGBFillColor(context,1.0,0.0,0.0,0.2);
    CGContextDrawPath(context, kCGPathFillStroke);

2.然后我创建一个路径图像,其中包含刚刚绘制的路径

    CGImageRef pacmanImage              = CGBitmapContextCreateImage (context); 

3。恢复上下文

CGContextRestoreGState(context);
CGContextSaveGState(context);

4。创建 1 位掩码(将提供黑白掩码)

bitsPerComponent                    = 1;
bitsPerPixel                        = bitsPerComponent * 1 ;
bytesPerRow                         = (CGImageGetWidth(imgToMaskRef) * bitsPerPixel);
mask                                = CGImageCreate(CGImageGetWidth(imgToMaskRef), 
                                                CGImageGetHeight(imgToMaskRef), 
                                                bitsPerComponent,
                                                bitsPerPixel, 
                                                bytesPerRow, 
                                                greyColorSpace,
                                                kCGImageAlphaNone, 
                                                CGImageGetDataProvider(pacmanImage), 
                                                NULL, //decode
                                                YES, //shouldInterpolate
                                                kCGRenderingIntentDefault);

5。使用刚刚创建的蒙版屏蔽 imgToMaskRef (这是一个 CGImageRef imgToMaskRef =imgToMask.CGImage;)

    imageMaskedWithImage                = CGImageCreateWithMask(imgToMaskRef, mask);
CGContextDrawImage(context,imgRectBox, imageMaskedWithImage);
CGImageRef maskedImageFinal         = CGBitmapContextCreateImage (context);

6.将 maskedImageFinal 返回给此方法的调用者(作为wheelChoiceMadeState,它是一个 CGImageRef),然后调用者用图像更新 CALayer 内容属性

 theLayer.contents                  = (id) wheelChoiceMadeState;

我看到的问题是遮罩无法正常工作并且看起来确实很奇怪。我在核心显卡绘制的路径上看到了奇怪的图案。我的预感是 CGImageGetDataProvider() 有问题,但我不确定。

任何帮助将不胜感激,

谢谢

I am trying to use an image (270 degrees of a circle, similar to a pacman logo, painted as Core Graphics) to create a mask. What I am doing is this

1. creating a Core Graphics path

    CGContextSaveGState(context);
    CGContextBeginPath(context);
    CGContextMoveToPoint(context,circleCenter.x,circleCenter.y);
    //CGContextSetAllowsAntialiasing(myBitmapContext, YES);
    CGContextAddArc(context,circleCenter.x, circleCenter.y,circleRadius,startingAngle, endingAngle, 0); // 0 is counterclockwise
    CGContextClosePath(context);
    CGContextSetRGBStrokeColor(context,1.0,0.0,0.0,1.0);
    CGContextSetRGBFillColor(context,1.0,0.0,0.0,0.2);
    CGContextDrawPath(context, kCGPathFillStroke);

2. then I'm creating an image of the path that has the path just painted

    CGImageRef pacmanImage              = CGBitmapContextCreateImage (context); 

3. restoring the context

CGContextRestoreGState(context);
CGContextSaveGState(context);

4. creating a 1 bit mask (which will provide the black-white mask)

bitsPerComponent                    = 1;
bitsPerPixel                        = bitsPerComponent * 1 ;
bytesPerRow                         = (CGImageGetWidth(imgToMaskRef) * bitsPerPixel);
mask                                = CGImageCreate(CGImageGetWidth(imgToMaskRef), 
                                                CGImageGetHeight(imgToMaskRef), 
                                                bitsPerComponent,
                                                bitsPerPixel, 
                                                bytesPerRow, 
                                                greyColorSpace,
                                                kCGImageAlphaNone, 
                                                CGImageGetDataProvider(pacmanImage), 
                                                NULL, //decode
                                                YES, //shouldInterpolate
                                                kCGRenderingIntentDefault);

5. masking the imgToMaskRef (which is a CGImageRef imgToMaskRef =imgToMask.CGImage;) with the mask just created

    imageMaskedWithImage                = CGImageCreateWithMask(imgToMaskRef, mask);
CGContextDrawImage(context,imgRectBox, imageMaskedWithImage);
CGImageRef maskedImageFinal         = CGBitmapContextCreateImage (context);

6. returning the maskedImageFinal to the caller of this method (as wheelChoiceMadeState, which is a CGImageRef) who then updates the CALayer contents property with the image

 theLayer.contents                  = (id) wheelChoiceMadeState;

the problem I am seeing is that the mask does not work properly and looks very strange indeed. I get strange patterns across the path painted by the Core Graphics. My hunch is there is something with CGImageGetDataProvider() but I am not sure.

Any help would be appreciated

thank you

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

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

发布评论

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

评论(1

风吹雨成花 2024-09-10 21:58:09

CGImageGetDataProvider 根本不更改数据。如果 pacmanImage 的数据与传递给 CGImageCreate 的参数 (bitsPer,bytesPer,colorSpace,...) 不完全匹配,则结果未定义。如果它完全匹配,则创建掩码就没有意义了。

您需要创建一个灰度 CGBitmapContext 来绘制蒙版,以及一个使用与位图相同的像素和参数的 CGImage。然后,您可以使用 CGImage 来遮盖另一个图像。

仅当您想要继续修改 CGBitmapContext 的快照时才使用 CGBitmapContextCreateImage。对于一次性位图,将相同的缓冲区传递给位图和您创建的匹配 CGImage。

编辑:

finalRect 是最终图像应有的尺寸。它要么足够大以容纳原始图像,并且 pacman 位于其中,要么它足够大以容纳 pacman,并且原始图像被裁剪以适合。在此示例中,原始图像被裁剪。否则,pacman 路径必须相对于原始图像定位。

maskContext = CGBitmapContextCreate( ... , finalRect.size.width , finalRect.size.height , ... );
// add the pacman path and set the stroke and fill colors
CGContextDrawPath( maskContext , kCGPathFillStroke );
maskImage = CGBitmapContextCreateImage( maskContext );
imageToMask = CGImageCreateWithImageInRect( originalImage , finalRect );
finalImage = CGImageCreateWithMask( imageToMask , maskImage );

CGImageGetDataProvider does not change the data at all. If the data of pacmanImage does not exactly match the parameters passed to CGImageCreate (bitsPer,bytesPer,colorSpace,...) the result is undefined. If it does exactly match, there would be no point in creating mask.

You need to create a grayscale CGBitmapContext to draw the mask into, and a CGImage that uses the same pixels and parameters as the bitmap. You can then use the CGImage to mask another image.

Only use CGBitmapContextCreateImage if you want a snapshot of a CGBitmapContext that you will continue to modify. For a single use bitmap, pass the same buffer to the bitmap and the matching CGImage you create.

Edit:

finalRect is the size the final image should be. It is either large enough to hold the original image, and the pacman is positioned inside it, or it is large enough to hold the pacman, and the original image is cropped to fit. In this example, the original image is cropped. Otherwise the pacman path would have to be positioned relative to the original image.

maskContext = CGBitmapContextCreate( ... , finalRect.size.width , finalRect.size.height , ... );
// add the pacman path and set the stroke and fill colors
CGContextDrawPath( maskContext , kCGPathFillStroke );
maskImage = CGBitmapContextCreateImage( maskContext );
imageToMask = CGImageCreateWithImageInRect( originalImage , finalRect );
finalImage = CGImageCreateWithMask( imageToMask , maskImage );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文