繁体   English   中英

屏幕颜色反转如何在OS X中工作?

[英]How does on-screen color inversion work in OS X?

这就是OS X内置的颜色反转功能可以将您的屏幕转换为:

在此输入图像描述

它可以反转所有颜色,将它们变为灰度,调整对比度。 现在我想构建自己的实现,因此需要专业人士的建议。

无法捕获倒置屏幕让我觉得反转是一种调整层,它位于所有窗口之上,并且不会暴露于交互事件。 是这样吗? 它是通过OpenGL库完成的吗?

我不介绍实际的编码帮助,而是研究解决问题的设计/方法。 在我的目标应用程序中,我需要定义输出颜色diapasons并应用颜色转换规则(input => output)。

提前致谢。

Mac OS进行颜色反转的方式(可能)是通过使用Quartz Display Services来修改显卡的伽玛表。

图形卡有两个这样的表,用于在合成后修改颜色输出到最终帧缓冲区。 其中一个可以被应用程序修改,以改变屏幕显示任何RGB值的方式。

这是反转显示的代码:

//ApplicationServices includes CoreGraphics
#import <ApplicationServices/ApplicationServices.h>

int main(int argc, const char * argv[])
{
    CGGammaValue table[] = {1, 0};
    CGSetDisplayTransferByTable(CGMainDisplayID(), sizeof(table) / sizeof(table[0]), table, table, table);
    sleep(3);
    return 0;
}

在某种程度上,您可以使用Core Image过滤器执行此操作。 但是,这是私有API,因此您需要小心,因为这些内容可能会在未来的OS X版本中发生变化或消失,您显然无法将应用程序提交到App Store。 我不认为使用公共API可以做到这一点。

编辑:请参阅Nikolai Ruhe的答案,了解使用公共API的更好方法。 你可以用Core Image过滤器做一些你无法用伽玛表做的事情(例如应用模糊滤镜等),所以我会在这里留下我的答案。

这是一个如何反转窗口背后的例子:

//Declarations to avoid compiler warnings (because of private APIs):
typedef void * CGSConnection;
typedef void * CGSWindowID;
extern OSStatus CGSNewConnection(const void **attributes, CGSConnection * id);
typedef void *CGSWindowFilterRef;
extern CGError CGSNewCIFilterByName(CGSConnection cid, CFStringRef filterName, CGSWindowFilterRef *outFilter);
extern CGError CGSAddWindowFilter(CGSConnection cid, CGSWindowID wid, CGSWindowFilterRef filter, int flags);
extern CGError CGSSetCIFilterValuesFromDictionary(CGSConnection cid, CGSWindowFilterRef filter, CFDictionaryRef filterValues);

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [self.window setOpaque:NO];
    [self.window setAlphaValue:1.0];
    [self.window setBackgroundColor:[NSColor colorWithCalibratedWhite:0.0 alpha:0.1]];
    self.window.level = NSDockWindowLevel;

    CGSConnection thisConnection;
    CGSWindowFilterRef compositingFilter;
    int compositingType = 1; // under the window
    CGSNewConnection(NULL, &thisConnection);
    CGSNewCIFilterByName(thisConnection, CFSTR("CIColorInvert"), &compositingFilter);
    NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:3.0] forKey:@"inputRadius"];
    CGSSetCIFilterValuesFromDictionary(thisConnection, compositingFilter, (CFDictionaryRef)options);
    CGSAddWindowFilter(thisConnection, (CGSWindowID)[self.window windowNumber], compositingFilter, compositingType);    
}

@end

(改编自Steven Troughton Smith的文章

截图

效果并不完美,因为由于某种原因,窗户必须具有不完全透明的背景颜色,但它非常接近。

要影响整个屏幕,您可以创建一个无边框窗口,将ignoresMouseEvents设置为YES (这样您就可以单击它)。

您可以尝试其他过滤器,但并非所有过滤器都适用于此。 这个反向工程标题中有一些关于CGS...函数的信息: http//code.google.com/p/undocumented-goodness/source/browse/trunk/CoreGraphics/CGSPrivate.h

OS X本身的方式是通过一组未记录的CoreGraphics API调用。 我不认为它们是在任何官方头文件中声明的,但你总是可以自己声明原型。

// clang -g -O2 -std=c11 -Wall -framework ApplicationServices

#include <stdio.h>
#include <ApplicationServices/ApplicationServices.h>

CG_EXTERN bool CGDisplayUsesInvertedPolarity(void);
CG_EXTERN void CGDisplaySetInvertedPolarity(bool invertedPolarity);

int
main(int argc, char** argv)
{
    bool isInverted = CGDisplayUsesInvertedPolarity();
    printf("isInverted = %d\n", isInverted);

    sleep(2);
    CGDisplaySetInvertedPolarity(!isInverted);
    printf("Polarity is now: %d\n", CGDisplayUsesInvertedPolarity());

    sleep(2);
    CGDisplaySetInvertedPolarity(isInverted);
    printf("Polarity is now: %d\n", CGDisplayUsesInvertedPolarity());

    return 0;
}

对其他辅助功能有类似的API调用,例如灰度:

CG_EXTERN bool CGDisplayUsesForceToGray(void);
CG_EXTERN void CGDisplayForceToGray(bool forceToGray);

这篇文章解释了另一个用户如何颠倒他的颜色,但这不是一个叠加,它仍然可以实现你的目标。 虽然这在C#中可能是你的基本前提,因为这些相同的想法可以在Obj-c中起作用。

基本上这篇文章说要在HSV模式下转换RGB颜色然后反转Hue值。 要执行此操作,您必须通过360-Hue更改Hue,然后转换回RGB模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM