【问题标题】:How can I get the average color of a CIImage without errors如何在没有错误的情况下获得 CIImage 的平均颜色
【发布时间】: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


    【解决方案1】:

    当您使用initinitWithOptions: 初始化CIContext 时,它现在将在所有平台上默认使用Metal。您需要使用contextWithEAGLContext:options: 初始化器并传递您用于创建inputImage 纹理的EGAGLContext,然后Core Image 可以使用该图像。

    但请注意,OpenGL 在所有平台上均已弃用。所以这可能会在不久的将来停止工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-11
      • 1970-01-01
      • 2012-09-06
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      • 2014-08-19
      相关资源
      最近更新 更多