【问题标题】:Remove UIBezirePath Lines drawn On UIImage删除在 UIImage 上绘制的 UIBezirePath 线
【发布时间】:2023-08-30 10:36:01
【问题描述】:

我正在尝试擦除在UIImage 上绘制的线条。我已成功擦除在空白画布上绘制的线条。

擦除UIImage 上的线条有什么技巧。以下是我尝试过但无法获得正确橡皮擦效果的一些方法。

  1. 使用触摸点并在该点获取图像的 RGB 并使用该颜色描边。
  2. colorwithpatternimage 太慢了。

请提出更好的解决方案

【问题讨论】:

  • UIImage 对其图像内容一无所知,就图像上的视觉内容而言。您无法删除未知的内容。
  • 我想擦除 UIImage 上方的笔画。
  • 如果它们不是 UIImage 对象的一部分,那么提及 UIImage 是无关紧要的。这些行在某些 CGContextRef 上下文中。您可以使用 CGContextClearRect 函数。

标签: ios objective-c drawing uibezierpath erase


【解决方案1】:

我通常将图像绘制到屏幕外缓冲区(例如CGBitmapContext),在其上绘制贝塞尔曲线,然后将结果复制到屏幕上。

要删除其中一个贝塞尔曲线,我将图像绘制到屏幕外缓冲区,绘制所有贝塞尔曲线,除了我不想要的那条(或多条)曲线,然后将结果复制到屏幕上。

这还有一个好处,那就是它可以避免因擦除已经在屏幕上的元素而导致的闪烁。如果曲线重叠,它可以正常工作,而将图像作为图案绘制可能会消除任何重叠点。


编辑:这里有一些伪代码(从未编译 - 只是从内存中编译)来说明我的意思:

-(UIImage*)drawImageToOffscreenBuffer:(UIImage*)inputImage
{
    CGBitmapContextRef offscreen = CGBitmapContextCreate(...[inputImage width], [inputImage height]...);
    CGImageRef cgImage = [inputImage CGImage];
    CGRect bounds = CGRectMake (0, 0, [inputImage width], [inputImage height]);
    CGContextDrawImage (offscreen, bounds, cgImage);
    // Now iterate through the Beziers you want to draw
    for (i = 0; i < numBeziers; i++)
    {
        if (drawBezier(i))
        {
            CGContextMoveToPoint(offscreen, ...);
            CGContextAddCurveToPoint(offscreen, ...); // fill in your bezier info here
        }
    }

    // Put result into a CGImage
    size_t rowBytes = CGBitmapContextGetBytesPerRow(offscreen);
    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, CGBitmapContextGetData(offscreen), rowBytes * [inputImage height], NULL);
    CGColorSpaceRef colorSpace = CGBitmapContextGetColorSpace(offscreen);
    CGImageRef cgResult = CGImageCreate([inputImage width], [inputImage height], ..., dataProvider, NULL, false, kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);
    CGColorSpaceRelease(rgbColorSpace);

    // Make a UIImage out of that CGImage
    UIImage* result = [UIImage imageWithCGImage:cgResult];
    // Can't remember if you need to release the cgResult here? I think so
    CGImageRelease(cgResult);
    return result;
}

【讨论】:

  • 谢谢,你能分享任何例子吗?
  • 你可以试试上面的。你需要填写一些细节,这主要是凭记忆,所以可能会有一些错误,但它应该能让你继续前进。