如何获得没有错误的CIImage的平均颜色

时间:2020-07-23 17:03:17

标签: objective-c macos cifilter ciimage

我正在尝试使用类似于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];

我尝试了其他一些操作,例如从NSBitmapImageRep创建CIImage并使用-[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上下文渲染图像(带有输入的Metal纹理)。”回溯中提到CA::OGL::emit_filter时,但无论哪种情况,我都不会得到非零的平均颜色。

在我的特定情况下,我确实有一种解决方法。我希望将平均颜色作为参数传递给滤镜的内核。但是我可以将平均彩色图像作为采样器传递给内核,然后让内核对其进行采样以获得颜色。因此,可能不值得与之抗争。

1 个答案:

答案 0 :(得分:1)

使用@inject ICourseService _courseService . . . <select asp-for="CategoryID" class="form-control round"> @foreach (var item in await _courseService.GetAllCourceCategory()){ <option value="@item.ID">@item.Description</option> } </select> CIContext初始化init时,默认情况下它将在所有平台上使用Metal。您需要使用initWithOptions:初始化程序,并传递用于创建contextWithEAGLContext:options:纹理的相同 EGAGLContext,然后Core Image才能使用该图像。 / p>

但是请注意,所有平台均不推荐使用OpenGL。因此,这可能会在不久的将来停止。