フェード効果の使用
ディスプレイのフェード効果は、フルスクリーンモードまたはディスプレイモードの切り替え時に使用されることが多い、ディスプレイのコンテンツとモノクロカラーブレンドとのスムーズな遷移です。モノクロームの色への遷移およびモノクロームの色からの遷移は、フェードアウトおよびフェードイン効果と呼ばれることがあります。
Quartz は、構成の変更中にすべてのオンラインディスプレイを自動的にフェードします。デフォルトのフェード効果の時間設定は、フェードアウトするのに 0.3 秒、フェードインするのに 0.5 秒です。フェード色は通常のデスクトップではフレンチブルーで、キャプチャされたディスプレイでは黒です。構成処理中に、この組み込みのフェード効果をカスタマイズできます - 処理(Transaction) を使用したディスプレイの構成 内の例を参照してください。
カスタムフェード効果を使用して、構成変更以外の遷移を指定することができます。たとえば、黒にフェードアウトして、ディスプレイをキャプチャし、スクリーンに描画し、黒からフェードインできます。以下の節では、このタスクを実行する 2 つの方法を示します。
すべてのディスプレイをフェードする
Quartz Display Services は、すべてのオンラインディスプレイで同時にカスタムフェード効果を実行できるようにする関数を提供します。最初のステップは、CGAcquireDisplayFadeReservation を呼び出して、指定された間隔でフェードエンジンを予約することです。この関数は、新しいフェード予約を表すトークンを返します。あなたのアプリケーションは、CGDisplayFade へのその後の呼び出しでこのトークンを引数として使用します。フェード予約期間中、あなたのアプリケーションはフェードエンジンを使用する排他的な権利を持ちます。予約を解除するには、CGReleaseDisplayFadeReservation を呼び出して下さい。
リスト 1 は、フェードエンジンを予約し、黒からのフェード効果と黒へのフェード効果を実行し、予約を解放する方法を示しています。番号付きコード行の詳細な説明は、リストの後に示します。
リスト 1 全てのディスプレイをフェードする
CGDisplayFadeReservationToken token; CGError err; err = CGAcquireDisplayFadeReservation (kCGMaxDisplayReservationInterval, &token); // 1 if (err == kCGErrorSuccess) { err = CGDisplayFade (token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, true); // 2 err = CGDisplayCapture (kCGDirectMainDisplay); // 3 /* draw something on the captured display */ err = CGDisplayFade (token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, true); // 4 err = CGReleaseDisplayFadeReservation (token); // 5 }
コードの動作は以下のとおりです。
- 最大許容間隔でフェードエンジンを予約します。あなたのアプリケーションがディスプレイ(複数) をフェードする前に、この手順を実行しなければなりません。この間、あなたのアプリケーションにはフェードエンジンを使用する排他的な権利があります。
- 0.3 秒間でディスプレイを黒にフェードします。関数呼び出しは同期的です。
- メインディスプレイをキャプチャします。ディスプレイはすでに黒色で、ユーザには何の変化も見えません。
- 黒からノーマルに 0.5 秒間でディスプレイをフェードします。関数呼び出しは同期的です。
- フェード予約を解放し、トークンを無効にします。
単一のディスプレイをフェードする
2 つ以上のディスプレイを備えたシステム上で単一のディスプレイをフェードするには、ディスプレイのガンマ式を段階的に調整するという別の方法を使用できます。
ガンマ値を調整するとき、最大ガンマ値が 1.0 であると仮定はできません。[システム環境設定] で異なる最大値をユーザーが指定した可能性があります。現在の設定を取得し、適切にスケーリングする必要があります。
リスト 2 は、指定されたディスプレイを黒色に戻してフェードさせる方法を示しています。スムーズなフェードを得るには、一定の遅延を持つループを使用します(もう 1 つの方法は、タイマーを使用して異なるシステムで固定フェード時間を保証することです)。
リスト 2 単一のディスプレイをフェードする
const double kMyFadeTime = 1.0; /* fade time in seconds */ const int kMyFadeSteps = 100; const double kMyFadeInterval = (kMyFadeTime / (double) kMyFadeSteps); const useconds_t kMySleepTime = (1000000 * kMyFadeInterval); /* delay in microseconds */ int step; double fade; CGGammaValue redMin, redMax, redGamma, greenMin, greenMax, greenGamma, blueMin, blueMax, blueGamma; CGError err; err = CGGetDisplayTransferByFormula (display, // 1 &redMin, &redMax, &redGamma, &greenMin, &greenMax, &greenGamma, &blueMin, &blueMax, &blueGamma); for (step = 0; step < kMyFadeSteps; ++step) { // 2 fade = 1.0 - (step / (double)kMyFadeSteps); err = CGSetDisplayTransferByFormula (display, redMin, fade*redMax, redGamma, greenMin, fade*greenMax, greenGamma, blueMin, fade*blueMax, blueGamma); usleep (kMySleepTime); // 3 } err = CGDisplayCapture (display); /* draw something on the captured display */ for (step = 0; step < kMyFadeSteps; ++step) { // 4 fade = (step / (double)kMyFadeSteps); err = CGSetDisplayTransferByFormula (display, redMin, fade*redMax, redGamma, greenMin, fade*greenMax, greenGamma, blueMin, fade*blueMax, blueGamma); usleep (kMySleepTime); // 5 } CGDisplayRestoreColorSyncSettings(); // 6
コードの動作は以下のとおりです。
- ディスプレイのガンマ転送式の現在の係数を開始するガンマ値として取得します。
- ガンマ転送式の係数として指定されたディスプレイ用の色のガンマ関数を設定して、現在のガンマからフェードします。現在のガンマ(1.0 の係数で乗算した) で開始し、黒(0.0 の係数で乗算した) で終了します。
- 短い間隔で処理を中断します。滑らかなフェードアウト効果を得るには、ディスプレイガンマを変更する呼び出しが 100 マイクロ秒ほど以内に戻り、次の垂直ブランキング期間に実際のガンマが非同期的に適用されるため、タイマを使用するか短い遅延を挿入する必要があります。遅延がなければ、黒への瞬間的なスイッチとして現れるものを得るでしょう。
- 黒(0.0 の係数を乗算した) から元のガンマ(1.0 の係数で乗算した) にフェードします。
- スムーズなフェードイン効果を実現するために短い間隔の処理を一時停止します。
- ガンマテーブルをユーザーの ColorSync ディスプレイプロファイル内の値に戻します。