【发布时间】:2020-11-13 11:46:25
【问题描述】:
我正在尝试使用类似于 this question 的代码来获取 CIImage 的平均颜色,但我在控制台中收到错误消息
Cannot render image (with an input GL texture) using a metal-DG context.
Failed to render 1 pixels because a CIKernel's ROI function did not allow tiling.
我猜CIImage 最初来自 OpenGL,但我在哪里要求金属上下文?如何避免此错误?
我的代码:
CIFilter* aveFilter = [CIFilter filterWithName: @"CIAreaAverage"];
[aveFilter setValue: inputImage forKey: @"inputImage"];
CGRect srcExtent = [inputImage extent];
CIVector* extentVec = [CIVector
vectorWithX: srcExtent.origin.x
Y: srcExtent.origin.y
Z: srcExtent.size.width
W: srcExtent.size.height ];
[aveFilter setValue: extentVec forKey: @"inputExtent"];
CIImage* aveColorPixel = [aveFilter valueForKey: @"outputImage"];
CIContext* bitContext = [[[CIContext alloc]
initWithOptions: @{
kCIContextWorkingColorSpace: [NSNull null],
kCIContextWorkingFormat: @(kCIFormatRGBA8)
}] autorelease];
unsigned char bitmap[4];
[bitContext render: aveColorPixel
toBitmap: bitmap
rowBytes: 4
bounds: CGRectMake( 0.0, 0.0, 1.0, 1.0 )
format: kCIFormatRGBA8
colorSpace: nil];
我尝试了其他一些方法,例如从 CIImage 创建一个 NSBitmapImageRep 并使用 -[NSBitmapImageRep colorAtX: y:],但得到了类似的错误。
事情比我最初想象的要复杂一些。我在 Core Image 过滤器的 Objective-C 部分执行此操作,结果表明,每隔一次调用过滤器时,我的平均代码就会起作用。成功时有部分回溯
frame #3: 0x00007fff41a35351 QuartzCore`CA::OGL::apply_cifilter(CA::Render::Filter const*, void const*) + 123
frame #4: 0x00007fff419cbc34 QuartzCore`CA::OGL::emit_filter(CA::OGL::Renderer&, CA::OGL::Filter const&, CA::OGL::Layer const&, float, CA::OGL::Surface*, float, CA::Vec2<float>, CA::Shape const*, float*) + 1678
frame #5: 0x00007fff41949ddd QuartzCore`CA::OGL::FilterNode::apply(float, CA::OGL::Surface**, float*) + 673
frame #6: 0x00007fff41936889 QuartzCore`CA::OGL::ImagingNode::render(CA::OGL::ImagingNode::RenderClosure*, unsigned int) + 473
frame #7: 0x00007fff4193edad QuartzCore`CA::OGL::ImagingNode::retain_surface(float&, unsigned int) + 171
frame #8: 0x00007fff41936743 QuartzCore`CA::OGL::ImagingNode::render(CA::OGL::ImagingNode::RenderClosure*, unsigned int) + 147
而当它失败并显示控制台日志错误消息时,部分回溯是:
frame #3: 0x00007fff41a35351 QuartzCore`CA::OGL::apply_cifilter(CA::Render::Filter const*, void const*) + 123
frame #4: 0x00007fff41942cd3 QuartzCore`CA::OGL::measure_filter(CA::OGL::Renderer&, CA::OGL::Filter const&, CA::OGL::Layer const&, CA::OGL::Gstate const&, CA::Bounds const&, CA::Bounds&) + 267
frame #5: 0x00007fff41942b2c QuartzCore`CA::OGL::FilterNode::propagate_roi(CA::Bounds const&) + 58
frame #6: 0x00007fff41935c2b QuartzCore`CA::OGL::ImagingNode::set_roi(CA::Shape const*) + 405
frame #7: 0x00007fff419356d8 QuartzCore`CA::OGL::prepare_layers_roi(CA::OGL::Renderer&, CA::OGL::Layer*, CA::OGL::Gstate const&) + 974
frame #8: 0x00007fff41a42a3d QuartzCore`CA::OGL::LayerNode::prepare_sublayers_roi_if_needed() + 43
frame #9: 0x00007fff41937f08 QuartzCore`CA::OGL::LayerNode::apply(float, CA::OGL::Surface**, float*) + 150
frame #10: 0x00007fff41936889 QuartzCore`CA::OGL::ImagingNode::render(CA::OGL::ImagingNode::RenderClosure*, unsigned int) + 473
答案建议使用从 GL 上下文(不是 EAGL,这是 macOS)创建的 CIContext。使用这种方法,我收到一条控制台错误消息“无法使用 opengl 上下文渲染图像(带有输入金属纹理)”。当回溯提到CA::OGL::emit_filter,但无论哪种情况,我都没有得到非零的平均颜色。
在我的特殊情况下,我确实有一个解决方法。我希望平均颜色作为参数传递给过滤器的内核。但相反,我可以将平均彩色图像作为采样器传递给内核,让内核对其进行采样以获得颜色。所以可能不值得与之抗争。
【问题讨论】:
标签: objective-c macos cifilter ciimage