[英]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.