Я пытаюсь получить средний цвет 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:]
, но получаю аналогичные ошибки.
Все немного сложнее, чем я думал изначально. Я делаю это в части Objective-C фильтра Core Image, и оказывается, что мой код усреднения работает каждый раз, когда вызывается фильтр. Когда это удается, есть частичная обратная трассировка
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
В ответе предлагается использовать CIContext
, созданный из контекста GL (не EAGL, это macOS). Используя этот подход, я получаю сообщение об ошибке консоли. Невозможно отобразить изображение (с входной металлической текстурой) с использованием контекста opengl. когда в трассировке упоминается CA::OGL::emit_filter
, но в любом случае я не получаю ненулевой средний цвет.
В моем конкретном случае у меня есть обходной путь. Я хотел, чтобы средний цвет передавался в качестве параметра ядру моего фильтра. Но вместо этого я могу передать усредненное цветное изображение ядру в качестве сэмплера и позволить ядру сэмплировать его, чтобы получить цвет. Так что бороться с этим, наверное, не стоит.