Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/108.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS:勾勒部分透明图像的不透明部分_Ios_Image Processing_Graphics_Uiimage - Fatal编程技术网

iOS:勾勒部分透明图像的不透明部分

iOS:勾勒部分透明图像的不透明部分,ios,image-processing,graphics,uiimage,Ios,Image Processing,Graphics,Uiimage,我有一个应用程序,它要求在部分透明的UIImage周围绘制一个实心的黑色轮廓。不是围绕图像的框架,而是围绕图像本身的所有不透明部分。例如,想象一个透明的PNG,上面有一个不透明的白色“X”——我需要用黑色勾勒出“X”的轮廓 为了让事情变得更复杂,在绘制轮廓后,原始图像的不透明度将被调整,但轮廓必须保持不透明——因此我生成的轮廓必须只包括轮廓,而不是原始图像 我目前的技术是: 创建一个新的ui视图,该视图具有原始图像的尺寸 将ui图像复制4次,并将复制的图像添加为ui视图的子视图,每个ui图像与

我有一个应用程序,它要求在部分透明的
UIImage
周围绘制一个实心的黑色轮廓。不是围绕图像的框架,而是围绕图像本身的所有不透明部分。例如,想象一个透明的PNG,上面有一个不透明的白色“X”——我需要用黑色勾勒出“X”的轮廓

为了让事情变得更复杂,在绘制轮廓后,原始图像的不透明度将被调整,但轮廓必须保持不透明——因此我生成的轮廓必须只包括轮廓,而不是原始图像

我目前的技术是:

  • 创建一个新的
    ui视图
    ,该视图具有原始图像的尺寸
  • ui图像
    复制4次,并将复制的图像添加为
    ui视图
    的子视图,每个
    ui图像
    与原始位置成对角线偏移一对像素
  • 将该
    ui视图
    转换为图像(通过典型的
    UIGraphicsGetImageFromCurrentImageContext
    方法)
  • 使用
    cgimageskcreate
    cgimagescreatewithmask
    ,从新图像中减去原始图像,因此只保留轮廓
它起作用了。即使只有4张偏移图像,效果也相当不错。然而,它的效率非常低,并且在iPhone4上会导致4秒的延迟

因此,我需要的是一个好的、快速的、高效的方法来实现同样的目标,这是iOS 4.0完全支持的


有什么好主意吗?:)

您只需要实现一个算法,但不要使用亮度或颜色来确定边缘的位置,而是使用不透明度。有很多不同的方法可以做到这一点。例如,您可以查看每个像素及其相邻像素,以确定不透明度超过您设置的阈值的区域。每当你需要在MacOS X或iOS中查看图像的每个像素时,想想看。有一系列有用的博客文章介绍了如何实现自定义核心图像过滤器——我将从这里开始构建边缘检测过滤器。

为了提供新想法:

当前实现中的一个变体将使用
CALayer
对阴影的支持,它根据层的实际像素内容计算阴影,而不仅仅是其边界矩形,并使用GPU。您可以尝试将
阴影不透明度
放大到某个较大的值,以消除羽化;如果无法渲染到合适的CGContext,请仅取出alpha层并手动处理它以对alpha值应用阈值测试,将其推到完全不透明或完全透明

即使在ES 1下,您也可以通过多种方式在GPU上实现最终处理步骤。你可以使用alpha测试来应用实际的阈值,比如说,你可以将深度缓冲设置为1.0,禁用颜色输出和深度测试,绘制深度为0.5的阴影版本,在深度为1.0的情况下绘制没有阴影的版本,然后启用颜色输出和深度测试,并在深度为0.75的情况下绘制纯黑全屏四元图。因此,这就像使用深度缓冲区来模拟模具(因为在支持ES 2的设备之前,Apple使用的GPU不支持模具缓冲区)

当然,这是假设
CALayer
阴影出现在合成器的外部,我没有检查


或者,如果您愿意限制对ES 2设备(所有3GS+)的支持,那么您可以将图像作为纹理上传,并在GPU上完成整个过程。但从技术上讲,这将使一些支持iOS 4的设备不受支持,因此我认为这不是一个选项。

我想指出,虽然有一些人建议使用边缘检测,但这不是一个合适的解决方案。边缘检测是指在图像数据中没有明显的精确边缘表示的情况下,查找图像数据中的边缘

对于您来说,边的定义更加明确,您正在寻找定义良好的轮廓。在你的例子中,边缘是在完全透明的像素上的任何像素,而在不完全透明的像素旁边的任何像素,就这么简单!迭代图像中的每个像素,如果它们满足这些条件,则将它们设置为黑色

或者,对于抗锯齿结果,获取图像的布尔表示,并将一个小的抗锯齿圆内核传递给它。我知道你说不支持自定义过滤器,但如果你可以直接访问图像数据,那么手工实现也不会太困难


干杯,希望这能有所帮助。

我建议使用UIView,只需推送如下上下文:

UIGraphicsBeginImageContextWithOptions(image.size,NO,0.0);
//draw your image 4 times and mask it whatever you like, you can just copy & paste
//current drawing code here.
....
outlinedimage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

这将比您的UIView快得多。

与使用UI/CG工具相比,您应该能够直接操作图像数据。那么步骤应该相当快。弄清楚图像格式并不难。主要的技巧是,当你将图像添加到一起时,你需要将每个像素除以4(右移2),以确保不会发生溢出。你可能还想研究其他方案的“边缘检测”以实现你的目标。可能会给你一些关于如何“破解”UIImage的想法。一般来说,这是一个很好的建议,但我认为目前核心映像的iOS实现不支持定制过滤器。因此,作者可能需要转换为CG位图上下文,以便让CPU访问内容并在那里运行过滤器(希望得到GCD的帮助)。这似乎是一种可行的方法——我假设可以调整算法以绘制比1px更厚的边。然而,在我花大量时间实现这个(似乎并不琐碎)之前,与我现在使用的方法相比,你认为它会有多高的效率?@Tommy Doh!在iOS上不受支持。太糟糕了。@DanM核心图像过滤器的一个妙处是它们可以在GPU上运行,GPU是为eff设计的