6

これは、OS X に組み込まれている色反転機能で画面を次のように変えることができるものです。

ここに画像の説明を入力

すべての色を反転したり、グレースケールにしたり、コントラストを調整したりできます。今、私は独自の実装を構築したいので、専門家のアドバイスが必要です。

反転した画面をキャプチャできないので、反転は一種の調整レイヤーであり、すべてのウィンドウの上にあり、単に相互作用イベントにさらされていないと考えました。そうですか?それは OpenGL ライブラリ経由で行われますか?

私は実際のコーディングのヘルプではなく、問題を解決するための設計/アプローチを検討しています。私の目標アプリでは、出力カラー ダイアパソンを定義し、カラー変換ルール (入力 => 出力) を適用する必要があります。

前もって感謝します。

4

4 に答える 4

14

Mac OS が色反転を行う方法は、(おそらく) Quartz Display Servicesを使用してグラフィック カードのガンマ テーブルを変更することです。

グラフィックス カードには、最終的なフレーム バッファーへの合成後にカラー出力を変更するためのこれらのテーブルが 2 つあります。そのうちの 1 つはアプリケーションで変更して、画面に 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;
}
于 2013-01-04T21:46:31.433 に答える
5

ある程度は、Core Image フィルターを使用してこれを行うことができます。ただし、これはプライベート API であるため、これらは将来の OS X リリースで変更または廃止される可能性があり、明らかにアプリを App Store に提出できないため、注意が必要です。パブリック API では、このようなことは不可能だと思います。

編集:パブリック API を使用するより良い方法については、Nikolai Ruhe の回答を参照してください。ガンマ テーブルではできなかったことが 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

(スティーブン・トラウトン・スミスの記事はこちら)

スクリーンショット

何らかの理由でウィンドウの背景色が完全に透明ではない必要があるため、効果は完全ではありませんが、かなり近い色です。

画面全体に影響を与えるには、にignoresMouseEvents設定されたボーダレス ウィンドウを作成するYESことができます (そのため、クリックすることができます)。

他のフィルターを試すことはできますが、すべてのフィルターがこの目的で機能するとは限りません。CGS...このリバース エンジニアリングされたヘッダーには、関数に関する情報がいくつかあります: http://code.google.com/p/undocumented-goodness/source/browse/trunk/CoreGraphics/CGSPrivate.h

于 2013-01-04T20:36:08.920 に答える
3

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);
于 2016-02-27T22:27:29.530 に答える
1

この記事では、別のユーザーがどのように色を反転したかを説明していますが、それはオーバーレイではなく、目的を達成するものです。これはおそらく基本的な前提となるC#ですが、同じアイデアがObj-cでも機能するためです。

基本的に、この記事では、HSV モードで RGB カラーを変換してから、色相値を反転するように指示しています。これを行うには、Hue を 360-Hue ごとに変更してから、RGB モードに戻す必要があります。

于 2013-01-04T19:44:55.357 に答える