CIColorMap不会对输入图像均匀应用梯度 [英] CIColorMap doesn't apply gradient uniformly to input image

查看:295
本文介绍了CIColorMap不会对输入图像均匀应用梯度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过加载附加的蓝色到红色渐变图片创建了一个CIColorMap过滤器。





然后我试图将它应用于灰度输入图像,这只是一个线性渐变





当我在CIContext中绘制CIColorMap的图像时,目的是使黑色呈深蓝色,白色呈深红色,中间灰色呈白色。但实际结果如下:





正如你所看到的,中间的灰色实际上映射为淡蓝色,而不是我预期的白色。



下面是源代码。我不知道我是否使用CIColorMap错误地给出了非常稀缺的文档。

  //接口文件
#import< ; Cocoa / Cocoa.h>
@interface ColorMapView:NSView
@end

//实现文件
#import< QuartzCore / QuartzCore.h>
#importColorMapView.h

static size_t imageWitdh = 512;
static size_t imageHeight = 125;

@implementation ColorMapView {
CIImage * m_backgroundImage;
CIImage * m_colorMapGradient;
CIFilter * m_colorMapFilter;
CIContext * m_ciContext;
}

- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder]
if(self){
[self initBackgroundImage];
[self initColorMapGradient];
}
return self;
}

- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];

if(!m_ciContext){
m_ciContext = [CIContext contextWithCGContext:[NSGraphicsContext currentContext] .graphicsPort options:nil];
}

CGFloat x =(self.bounds.size.width - imageWitdh)/ 2;
CGFloat y =(self.bounds.size.height - imageHeight)/ 2;

//这里绘制代码。
[m_colorMapFilter setValue:m_backgroundImage forKey:kCIInputImageKey];
[m_ciContext drawImage:[m_colorMapFilter valueForKey:kCIOutputImageKey] inRect:CGRectMake(x,y,imageWitdh,imageHeight)fromRect:m_backgroundImage.extent];
}

- (void)initBackgroundImage {
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
CGContextRef context = CGBitmapContextCreate(NULL,imageWitdh,imageHeight,8,imageWitdh,colorSpace,(CGBitmapInfo)kCGImageAlphaNone);
CGFloat locations [2] = {0.0,1.0};
CGFloat components [4] = {0.0,1.0,1.0,1.0};
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace,components,locations,2);
CGContextDrawLinearGradient(context,gradient,CGPointMake(0,0),CGPointMake(imageWitdh,0),NO);
CGImageRef gradientImage = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
m_backgroundImage = [CIImage imageWithCGImage:gradientImage];
CGImageRelease(gradientImage);
}

- (void)initColorMapGradient {
NSString * imagePath = [[NSBundle mainBundle] pathForResource:@blue_red_scale_gradientofType:@png];
CGDataProviderRef dataProvider = CGDataProviderCreateWithFilename(imagePath.UTF8String);
CGImageRef image = CGImageCreateWithPNGDataProvider(dataProvider,NULL,NO,kCGRenderingIntentDefault);
m_colorMapGradient = [CIImage imageWithCGImage:image];
CGImageRelease(image);
m_colorMapFilter = [CIFilter filterWithName:@CIColorMap];
[m_colorMapFilter setValue:m_colorMapGradient forKey:@inputGradientImage];
}

@end


解决方案>

这似乎是与颜色管理问题有关。如果我在创建CIContext对象时将kCIContextWorkingColorSpace设置为NSNull,我将得到预期的结果。

  if(!m_ciContext){
NSDictionary * options = @ {kCIContextWorkingColorSpace:[NSNull null]};
m_ciContext = [CIContext contextWithCGContext:[NSGraphicsContext currentContext] .graphicsPort options:options];
}


I created a CIColorMap filter by loading the attached blue-to-red gradient image.

Then I tried to apply this to a gray scale input image, which is simply a linear gradient from black to white.

When I draw the out image of CIColorMap in a CIContext, the intention is to render black color in dark blue, white color in dark red, and mid gray in white. However the actual result looks like:

As you can see, the mid gray is actually mapped to light blue, instead of white as I have expected.

Below is the source code. I wonder if I have been using CIColorMap incorrectly given the very scarce documentation.

// Interface file
#import <Cocoa/Cocoa.h>
@interface ColorMapView : NSView
@end

// Implementation file
#import <QuartzCore/QuartzCore.h>
#import "ColorMapView.h"

static size_t imageWitdh = 512;
static size_t imageHeight = 125;

@implementation ColorMapView {
    CIImage *m_backgroundImage;
    CIImage *m_colorMapGradient;
    CIFilter *m_colorMapFilter;
    CIContext *m_ciContext;
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        [self initBackgroundImage];
        [self initColorMapGradient];
    }
    return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    if (!m_ciContext)  {
        m_ciContext = [CIContext contextWithCGContext:[NSGraphicsContext currentContext].graphicsPort options:nil];
    }

    CGFloat x = (self.bounds.size.width - imageWitdh) / 2;
    CGFloat y = (self.bounds.size.height - imageHeight) / 2;

    // Drawing code here.
    [m_colorMapFilter setValue:m_backgroundImage forKey:kCIInputImageKey];
    [m_ciContext drawImage:[m_colorMapFilter valueForKey:kCIOutputImageKey] inRect:CGRectMake(x, y, imageWitdh, imageHeight) fromRect:m_backgroundImage.extent];
}

- (void)initBackgroundImage {
     CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
    CGContextRef context = CGBitmapContextCreate(NULL, imageWitdh, imageHeight, 8, imageWitdh, colorSpace, (CGBitmapInfo)kCGImageAlphaNone);
    CGFloat locations[2] = {0.0, 1.0};
    CGFloat components[4] = {0.0, 1.0, 1.0, 1.0};
    CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, 2);
    CGContextDrawLinearGradient(context, gradient, CGPointMake(0, 0), CGPointMake(imageWitdh, 0), NO);
    CGImageRef gradientImage = CGBitmapContextCreateImage(context);
    CGContextRelease(context);
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorSpace);
    m_backgroundImage = [CIImage imageWithCGImage:gradientImage];
    CGImageRelease(gradientImage);
}

- (void)initColorMapGradient {
    NSString* imagePath = [[NSBundle mainBundle] pathForResource:@"blue_red_scale_gradient" ofType:@"png"];
    CGDataProviderRef dataProvider = CGDataProviderCreateWithFilename(imagePath.UTF8String);
    CGImageRef image = CGImageCreateWithPNGDataProvider(dataProvider, NULL, NO, kCGRenderingIntentDefault);
    m_colorMapGradient = [CIImage imageWithCGImage:image];
    CGImageRelease(image);
    m_colorMapFilter = [CIFilter filterWithName:@"CIColorMap"];
    [m_colorMapFilter setValue:m_colorMapGradient forKey:@"inputGradientImage"];
}

@end

解决方案

It seems this is related to color management issue. If I set kCIContextWorkingColorSpace to NSNull when creating CIContext object, I will get expected result.

if (!m_ciContext)  {
    NSDictionary *options = @{kCIContextWorkingColorSpace : [NSNull null]};
    m_ciContext = [CIContext contextWithCGContext:[NSGraphicsContext currentContext].graphicsPort options:options];
}

这篇关于CIColorMap不会对输入图像均匀应用梯度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆