【问题标题】:iOS using UIGraphicsGetImageFromCurrentImageContext to detect certain pixels on screeniOS 使用 UIGraphicsGetImageFromCurrentImageContext 检测屏幕上的某些像素
【发布时间】:2015-05-08 12:14:00
【问题描述】:

我有一个 UIView,用户可以在其中绘制各种 UIBezierPaths。

我需要分析绘制的 BezierPaths 来处理某些模式。我还没有找到任何将 UIBezierPaths 转换为坐标/点列表的解决方案,这似乎是可撤销的?这很奇怪,因为必须存储这些数据并以某种方式绘制实际路径。

所以为了绕过这个问题,我决定绘制宽度为 1px 的 BezierPath:

[path setLineWidth:1];

并将我的 UIView 转换为 UIImage:

UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();

然后我可以通过获取图像上某个像素位置的颜色来识别像素:

- (UIColor *)colorAtPixel:(CGPoint)point {
    CGImageRef imageRef = [self CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    int bytesPerPixel = 4;
    long bytesPerRow = bytesPerPixel * width;
    int bitsPerComponent = 8;

    unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));

    CGContextRef context = CGBitmapContextCreate(rawData,
                                                 width,
                                                 height,
                                                 bitsPerComponent,
                                                 bytesPerRow,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGColorSpaceRelease(colorSpace);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);

    // Now your rawData contains the image data in the RGBA8888 pixel format.
    long byteIndex = (bytesPerRow * point.y) + point.x * bytesPerPixel;
    CGFloat red   = (rawData[byteIndex] * 1.0) / 255.0;
    CGFloat green = (rawData[byteIndex + 1] * 1.0) / 255.0 ;
    CGFloat blue  = (rawData[byteIndex + 2] * 1.0) / 255.0 ;
    CGFloat alpha = (rawData[byteIndex + 3] * 1.0) / 255.0;

    byteIndex += 4;
    UIColor *color = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
    free(rawData);

    return color;
}

现在我的问题是生成的图像是模糊的,如果绘制一条直线 1px BezierPath 线并将其转换为 UIImage,由于它变得模糊,该线的宽度为 3x。

我该如何解决这个问题?实际上没有办法将 BezierPaths 转换为坐标列表吗?

【问题讨论】:

标签: ios objective-c uibezierpath bezier


【解决方案1】:

这是由于抗锯齿渲染造成的。

See this question on SO for information on how to turn this of.

我相信你自己渲染贝塞尔曲线会更好。内存占用非常小,速度会更快。

【讨论】:

  • 谢谢,我不确定如何使用 [data writeToFile:[self screenShotFilename] atomically:YES];。这是指什么文件?
  • 该行将屏幕截图写入磁盘。我所指的部分是防止反别名呈现您的问题,CGContextSetShouldAntialias(context, NO); -- 请参阅下面 Rufel 的答案,作为查找渲染点的更好选择。
【解决方案2】:

你可以看看this answer from Moritz关于使用CGPathApplyCGPathApplierFunction

对于指定路径中的每个元素,Quartz 调用 applier 函数,该函数可以检查(但不能修改)元素。

这可以让您访问存储在 UIBezierPath 中的点。

【讨论】:

  • 使用该方法我只得到了 21 个点的列表,我的曲线至少应该得到大约 500 个点。
猜你喜欢
  • 1970-01-01
  • 2021-02-07
  • 2012-04-13
  • 2020-12-16
  • 2018-05-08
  • 1970-01-01
  • 2011-04-17
  • 2021-04-16
  • 2012-11-09
相关资源
最近更新 更多