我有一个应用程序,它使用NSImage
- 特别是 -来显示照片[NSImage drawInRect:fromRect:operation:fraction:]
。我想像一些数码相机和图像处理应用程序一样,使用红色等颜色突出显示完全烧坏的照片区域(所有组件中的最大值,纯白色),以帮助用户查看图像是否曝光过度,以及有多糟糕。
我一直在摸索如何做到这一点。我考虑过的选项:
我可能可以编写一个 Core Image 过滤器来完成它;没有任何内置过滤器可以完成任务。不过,这似乎有点矫枉过正。我一直在阅读文档,它看起来相当复杂。大学习曲线。
我可以扫描图像的位图数据并根据需要进行修改。这很容易为一种位图格式编写代码,但是位图格式的众多使它成为一个相当烦人的练习,并且速度在这里很重要,因此编写通用代码将图像渲染为某种最大的通用格式并在此基础上工作位图对速度的影响太大。
碰巧的是,我已经在代码的较早位置扫描图像(处理所有不同的位图格式),以生成图像的直方图数据。那时我可以很容易地添加代码来记住烧坏的像素以供以后使用。不过,我不太确定最好的方法是什么。一个每像素 1 位的 NSBitmapImageRep?稍后我将如何绘制它,例如使 1 像素绘制为红色而 0 像素绘制为透明?我不想制作一个
NSBitmapImageRep
带有 alpha 通道的 32 位,而一切都只是为了这个目的,因为内存不是无限的,而且图像很大。但是必须有一种方法可以以某种方式以给定的颜色绘制一个 1 位掩码。
在采用其中一种方法之前,我想我会看看这里是否有人有更好的主意。或者可能已经实施了有问题的 CI 过滤器?除了学习曲线之外,这似乎是我迄今为止想到的最好的方法——没有内存开销,而且可能比其他选项更快。
谢谢...
本哈勒棒软件
好的,我实现了自己的核心图像过滤器来做到这一点。没有我预期的那么难,尽管文档对于这些东西并不好。文档示例都假设您使用的是 ARC,所以如果您不是,遵循这些示例将为您提供各种保留/释放错误。CIFilterConstructor 的东西也有一点奇怪,它并没有像记录的那样。但总体来说还算轻松。CI 很酷。我的代码如下,对于任何可能觉得它有用的人:
标题: #进口 @interface SSTintHighlightsFilter : CIFilter { CIImage *输入图像; CIColor *highlightColor; } @结尾 实现文件: #import "SSTintHighlightsFilter.h" 静态 CIKernel *tintHighlightsFilter = nil; @implementation SSTintHighlightsFilter + (void)初始化 { [CIFilter registerFilterName:@"SSTintHighlightsFilter" 构造函数:(id)self classAttributes:[NSDictionary dictionaryWithObjectsAndKeys:@"Tint Highlights", kCIAttributeFilterDisplayName, [NSArray arrayWithObjects:kCICategoryColorAdjustment, kCICategoryStillImage, nil], kCIAttributeFilterCategories, nil]]; } + (CIFilter *)filterWithName:(NSString *)name { CIFilter *filter = [[self alloc] init]; 返回[过滤器自动释放]; } - (id)初始化 { if (!tintHighlightsFilter) { NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSString *code = [NSString stringWithContentsOfFile:[bundle pathForResource:@"tintHighlightsAndShadows" ofType:@"cikernel"] encoding:NSASCIIStringEncoding error:NULL]; NSArray *kernels = [CIKernel kernelsWithString:code]; tintHighlightsFilter = [[kernels objectAtIndex:0] 保留]; } 返回[超级初始化]; } - (NSDictionary *)customAttributes { NSDictionary *attrs = @{ @"highlightColor" : @{ kCIAttributeClass : [CIColor 类], kCIAttributeType : kCIAttributeTypeOpaqueColor } }; 返回属性; } - (CIImage *)输出图像 { CISampler *src = [CISampler samplerWithImage:inputImage]; 返回[自我应用:tintHighlightsFilter 参数:[NSArray arrayWithObjects:src,highlightColor,nil] options:[NSDictionary dictionaryWithObjectsAndKeys:[src 定义], kCIApplyOptionDefinition, nil]]; } @结尾 tintHighlights.cikernel: 内核 vec4 tintHighlights(采样器 inputImage,__color highlightColor) { vec4 originalColor, tintedColor; 浮动总和; // 获取源像素 originalColor = sample(inputImage, samplerCoord(inputImage)); // 计算颜色分量总和作为测试我们是黑色还是白色的一种方式 总和 = originalColor.r + originalColor.g + originalColor.b; // 用高亮颜色替换白色的像素 tintedColor = (sum > 2.99999999999999999999999) ? highlightColor : originalColor; // 保留 alpha tintedColor.a = originalColor.a; 返回着色颜色; } 使用过滤器: + (NSImage *)showHighlightsInImage:(NSImage *)img dstRect:(NSRect)dstRect { NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; NSRect dstRectForCGImage = dstRect; // 因为下面的方法需要一个指针,我不相信它不会修改我的矩形... CGImageRef cgImage = [img CGImageForProposedRect:&dstRectForCGImage 上下文:currentContext 提示:nil]; CIImage *inputImage = [[CIImage alloc] initWithCGImage:cgImage]; [SSTintHighlightsFilter 类]; // 初始化我的过滤器 CIFilter *highlightFilter = [CIFilter filterWithName:@"SSTintHighlightsFilter"]; [highlightFilter setValue:inputImage forKey:@"inputImage"]; [highlightFilter setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0] forKey:@"highlightColor"]; [输入图片发布]; CIImage *outputImage = [highlightFilter valueForKey:@"outputImage"]; NSImage *resultImage = [[NSImage alloc] initWithSize:[img size]]; [resultImage addRepresentation:[NSCIImageRep imageRepWithCIImage:outputImage]]; 返回[结果图像自动释放]; }
我不确定我是否完全稳健地处理 alpha,存在预乘问题等等,但除了可能的故障之外,它工作得很好。