有人知道自定义CIF过滤器对图像大小的限制吗?我已经创建了一个过滤器,当图像高达2百万像素时,可以按预期执行,但是当图像较大时会产生非常奇怪的结果。我在我的可可应用程序和石英作曲家中测试过这个。我开发的滤波器是一种几何型失真滤波器,我认为它需要一个跨越整个输入图像的ROI和DOD。我创建了这个过滤器来重新映射全景图像,所以我希望这可以处理非常大的(50-100百万像素)图像。
作为一个简单的测试,考虑下面的CIFilter(可以在Quartz Composer中使用),它只是简单地翻译图像,使图像的左下角被转换为中心(我知道这可以用仿射来完成)转换,但我需要在更复杂的过滤器中执行此类操作)。当图像为2000x1000时,此滤镜按预期工作,但当输入图像为4000x2000像素时,此滤镜会产生奇数结果。问题是翻译不会将角落精确地移动到中心,或者图像输出完全消失。我注意到在大图像上有更复杂的过滤器的其他奇怪问题,但我认为这个简单的过滤器说明了我的问题,可以在Quartz Composer中复制。
kernel vec4 equidistantProjection(sampler src, __color color)
{
vec2 coordinate = samplerCoord(src);
vec2 result;
vec4 outputImage;
result.x = (coordinate.x - samplerSize(src).x / 2.0);
result.y = (coordinate.y - samplerSize(src).y / 2.0);
outputImage = unpremultiply(sample(src,result));
return premultiply(outputImage);
}
使用工作坐标而不是采样器坐标时会出现相同的奇怪行为,但在这种情况下,对于大小为2000x1000的图像会出现错误,但对于大小为1000x500的图像则可以正常工作
kernel vec4 equidistantProjection(sampler src, __color color, vec2 destinationDimensions)
{
vec2 coordinate = destCoord();
vec2 result;
vec4 outputImage;
result.x = (coordinate.x - destinationDimensions.x / 2.0);
result.y = (coordinate.y - destinationDimensions.y / 2.0);
outputImage = unpremultiply(sample(src,result));
outputImage = unpremultiply(sample(src,samplerTransform(src, result)));
return premultiply(outputImage);
}
作为参考,我已将我的过滤器的- (CIImage *)outputImage
方法的Objective-C部分添加到以下内容中,以将DOD设置为整个输入图像。
- (CIImage *)outputImage
{
CISampler *src = [CISampler samplerWithImage: inputImage];
NSArray * outputExtent = [NSArray arrayWithObjects:
[NSNumber numberWithInt:0],
[NSNumber numberWithInt:0],
[NSNumber numberWithFloat:[inputImage extent].size.width],
[NSNumber numberWithFloat:[inputImage extent].size.height],nil];
return [self apply: filterKernel, src, inputColor, zoom, viewBounds, inputOrigin,
kCIApplyOptionDefinition, [src definition], kCIApplyOptionExtent, outputExtent, nil];
}
此外,我添加了以下方法来设置我在- (id)init
方法中调用的投资回报率:[filterKernel setROISelector:@selector(regionOf:destRect:userInfo:)];
- (CGRect) regionOf:(int)samplerIndex destRect:(CGRect)r userInfo:obj
{
return r;
}
对此问题的任何帮助或建议将不胜感激。我确信CIFilters可以使用更大的图像,因为我已经使用了超过50万像素的CIBumpDistortion,所以我一定做错了。有什么想法吗?
答案 0 :(得分:4)
使用CoreImage我发现它会将大图像切割成零件。例如,在您的情况下,4k x 2k图像可以分割为4个2k x 1k图像并单独渲染。不幸的是,这种优化技巧会影响 samplerCoord ,并且一些坐标依赖的滤镜在大图像上的工作不正确。
我的解决方案是使用 destCoord 而不是 samplerCoord 。当然,您应该记住,图像可以以非零原点和 destCoord 呈现。我编写了自己的过滤器,因此我能够将整个范围作为vec4参数传递。
示例:尝试使用CIFilter生成图像,类似:
float gray = (samplerCoord.x / samplerSize.width) * (samplerCoord.y / samplerSize.height);
这个输出应该给我们(0,0)的黑色和(1,1)的白色,对吧?但是,对于大图像,您会看到很少的四边形,而不是单个渐变。这是因为来自CoreImage引擎的优化渲染,我还没有找到传递它的方法,但你可以这样重写内核:
float gray = ((destCoord.x - rect.x) / rect.size) * ((destCoord.y - rect.y) / rect.height)
rect 是真实范围,您必须传递的采样器。我为此目的使用了[inputImage extent],但它取决于过滤器,在你的情况下可能是其他东西。
希望这个解释清楚明白。购买方式,看起来系统内核即使使用大图像也能正常工作,所以你应该只担心自定义内核中的这些技巧。