簡體   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