【问题标题】:drawing image from CALayers从 CALayers 绘制图像
【发布时间】:2011-01-31 14:43:34
【问题描述】:

我正在构建某种审查应用程序。到目前为止,我已经可以完成用我的 iPhone 拍摄的图像的像素化。

但我想最终实现这样的图像:http://images-mediawiki-sites.thefullwiki.org/11/4/8/8/8328511755287292.jpg

所以我的想法是对图像进行完全像素化,然后在其上添加蒙版,以达到预期的效果。因此,就图层而言,它就像: originalImage + maskedPixelatedVersionOfImage .. 我想在触摸图像时为蒙版设置动画,将蒙版缩放到所需的大小。您将手指放在图像上的时间越长,蒙版就越大...

经过一番搜索,我想这可以使用 CALayers 和 CAAnimation 来完成。但是,我如何将这些图层合成为可以保存在 iphone 相册中的图像?

我在这里采取了正确的方法吗?

编辑:

好的,我猜 Ole 的解决方案是正确的,虽然我仍然没有得到我想要的:我使用的代码是:

    CALayer *maskLayer = [CALayer layer];
    CALayer *mosaicLayer = [CALayer layer];

    // Mask image ends with 0.15 opacity on both sides. Set the background color of the layer
    // to the same value so the layer can extend the mask image.
    mosaicLayer.contents = (id)[img CGImage];
    mosaicLayer.frame = CGRectMake(0,0, img.size.width, img.size.height);
    UIImage *maskImg = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"mask" ofType:@"png"]];
    maskLayer.contents = (id)[maskImg CGImage];
    maskLayer.frame = CGRectMake(100,150, maskImg.size.width, maskImg.size.height);

    mosaicLayer.mask = maskLayer;

    [imageView.layer addSublayer:mosaicLayer];

    UIGraphicsBeginImageContext(imageView.layer.bounds.size);
    [imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *saver = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

所以在我的 imageView 中我做了:setImage,它具有照片的原始(未编辑)版本。最重要的是我添加了一个子层,mosaicLayer,它有一个遮罩属性:maskLayer。我想通过渲染 imageView 的根层,一切都会好起来的。这不正确吗?

另外,我还发现了一些别的东西:我的面具被拉伸和旋转了,我猜这与 imageOrientation 有关吗?我注意到不小心将mosaicLayer 保存到我的库中,这也解释了我遇到的问题,即蒙版似乎掩盖了我图像的错误部分......

【问题讨论】:

    标签: iphone objective-c core-graphics core-animation quartz-graphics


    【解决方案1】:

    要渲染层树,将所有层放在一个公共容器层中并调用:

    UIGraphicsBeginImageContext(containerLayer.bounds.size);
    [containerLayer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    

    【讨论】:

    • 好的,谢谢,我会试试这个。你认为我在其他方面的做法是正确的吗?
    • 值得注意的是,这种方法会阻止您在后台线程上进行渲染。如果您需要线程安全,请避免使用UI 函数并创建自己的CGBitmapContextdeveloper.apple.com/library/ios/#documentation/GraphicsImaging/…
    • 这也可能无法从 AVCaptureVideoPreviewLayer 捕获图像,如果他使用它来呈现实时摄像机帧。
    【解决方案2】:

    如果您愿意放弃对 iPhone 3G S 之前的设备(iPhone 和 iPhone 3G)的支持,我建议为此使用 OpenGL ES 2.0 着色器。虽然覆盖包含图像像素化版本的 CALayer 可能很容易,但我认为您会发现性能不足。

    my tests 中,对 480 x 320 图像的每个像素执行基于 CPU 的简单计算会导致 iPhone 4 上的帧速率约为 4 FPS。您可能只能对这些像素的一小部分进行采样以达到预期的效果,但重新绘制像素化图像以匹配实时视频仍然是一个缓慢的操作。

    相反,如果您使用 OpenGL ES 2.0 片段着色器来处理传入的实时视频图像,您应该能够获取原始相机图像,在所需区域上选择性地应用此滤镜,然后显示或保存结果相机图像。这种处理几乎完全在 GPU 上进行,我发现它可以在 iPhone 4 上以 60 FPS 的速度执行类似这样的简单操作。

    虽然让片段着色器正常工作可能需要一些设置,但您可以使用我编写的this sample application 来处理相机输入和进行颜色跟踪,这是一个不错的起点。你也可以看看我在那里使用的触摸手势,我将最初的触摸点作为效果居中的位置,然后是随后的拖动距离来控制效果的强度或半径。

    【讨论】:

    • 很有趣,我一定会看看你的代码,尤其是触摸手势。但我正在尝试拍摄照片,没有现场视频。我现在得到的性能已经足够了。我考虑过openGL,但认为仅一张照片就有点过头了.. :) 无论如何谢谢
    • @ThomasM - 即使您只关心图像,您仍然需要进行某种实时预览。这可以提供这种带有实时反馈的预览,同时在用户完成拍摄时可以非常快速地处理全尺寸图像以进行保存。
    • 不,重点是拍张照片,然后对其进行审查。所以我真的不需要真人表演。我看了你的项目,当时对我来说似乎有点太复杂了。我实际上是一名 AS3 开发人员,我正在 iOs 开发中迈出第一步。我发现 obj c 真的很痛苦,即使只是试图阅读它:) 尽管如此,我认为我可以使用您的项目或其中的一部分来进一步学习并作为某些代码的资源。看看事情如何做得最好是最好的学习吗?
    • @ThomasM - 用户是否还想要实时预览?因为他们需要指定要“审查”的区域的位置和大小,如果用户点击并拖动以选择没有可见反馈的区域,我可以看到用户很快就会感到沮丧,只是发现当他们拍照时它没有不会变成他们想要的样子。如果您的照片的主题是不会坐下来进行多次重拍的人,则尤其如此。实时预览是一种保证事情会按照他们想要的方式发展的方式。
    • @ThomasM - 作为额外的学习资源,我去年教了一门高级 iOS 开发课程,视频可在 iTunes U 上找到:itunes.apple.com/WebObjects/MZStore.woa/wa/…。特别是,您可能对相机、OpenGL ES 2.0 和 Core Animation 部分感兴趣。
    猜你喜欢
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    • 2019-08-17
    • 2018-06-14
    • 1970-01-01
    • 2013-02-28
    • 1970-01-01
    相关资源
    最近更新 更多