2013-01-04 3 views
4

Это то, что встроенная функция инверсии цвета может превратить ваш экран в OS Икса:Как работает инверсия цвета на экране в OS X?

enter image description here

Это может перевернуть все цвета, включите их в оттенках серого, отрегулируйте контрастность. Теперь я хочу построить свою собственную реализацию и, следовательно, нуждаюсь в советах профессионалов.

Невозможность захватить инвертированный экран заставила меня думать, что инверсия - это своего рода корректирующий слой, который находится над всеми окнами и просто не подвергается событиям взаимодействия. Это так? Это делается через OpenGL libs?

Я не рассматриваю фактическую помощь в кодировании, а скорее проект/подход к решению проблемы. В моем целевом приложении мне нужно будет определить диапазоны выходных цветов и применить правила преобразования цвета (input => output).

Заранее спасибо.

ответ

10

Путь 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; 
} 
+0

Очень интересно! Я не знал об этом. – omz

1

This статья объясняет, как другой пользователь перевернул свои цвета, однако это не было бы оверлейным, это все равно выполнило бы вашу цель. Хотя это в C#, который, возможно, был бы вашей основной предпосылкой, эти те же идеи могут работать в Obj-c.

В основном в этой статье говорится, чтобы преобразовать цвет RGB в режим HSV, а затем инвертировать значение оттенка. Для этого вы должны изменить Hue на 360-Hue, а затем преобразовать обратно в режим RGB.

+0

Спасибо за ссылку. Однако это не совсем то, что я искал. –

+0

@AlexksandrMakov Хорошо, я увижу, что еще существует. –

+0

Хотя это может технически ответить на вопрос, [было бы предпочтительнее] (http://meta.exackexchange.com/q/8259), чтобы вы могли обобщить связанный материал здесь. В противном случае ответ рискует потерять свою полезность из-за связи гниения. –

4

В какой-то степени вы можете сделать это с помощью фильтров Core Image. Однако это частный API, поэтому вам нужно быть осторожным, потому что эти вещи могут измениться или исчезнуть в будущих выпусках OS X, и вы, очевидно, не сможете отправить приложение в App Store. Я не думаю, что это возможно с помощью публичных API.

Edit: ответ Николаю 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's article here)

screenshot

Эффект не является совершенным, потому что по какой-то причине необходимо, чтобы в окне есть цвет фона, который не является полностью прозрачным, но он довольно близок.

Чтобы повлиять на весь экран, вы можете создать окно без полей, которое имеет ignoresMouseEvents, установленное на YES (так что вы можете щелкнуть по нему).

Вы можете поэкспериментировать с другими фильтрами, но не все из них могут работать для этого. Там какая-то информация о CGS... функциях в этом обратном спроектированном заголовке: http://code.google.com/p/undocumented-goodness/source/browse/trunk/CoreGraphics/CGSPrivate.h

+0

Спасибо. Очень полезно. Wether это делается с помощью частного или публичного API, это все равно API, который является C (Objective-C), основанным в любом случае. Тогда я предполагаю, что спуск кроличьей дыры - это то, что я ищу. Дополнительная благодарность за ссылку на статью. –

2

Путь сама 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); 

 Смежные вопросы

  • Нет связанных вопросов^_^