2017-11-18 8 views
0

Windows OS (7,8,10)에서 GammaRamp (SetDeviceGammaRamp)를 사용하여 화면을 회색조로 변환 할 수 있습니까? E-Ink 리더를 시뮬레이션하려면이 코드가 필요합니다. 이 클래스를 사용하여 색온도를 제어하고 다음 요소를 사용하여 RGB 이미지를 그레이 스케일로 변환하는 알고리즘을 구현하려고했습니다. red * 0.2126; 녹색 * 0.7152; 이 article에서 읽은 청색 * 0.0722 . 결과가 순수한 회색 음영이 아니 었습니다. SetDeviceGammaRamp에 의해 설정된 gammaramp 배열이 색상을 변경하는 방법과 회색조 알고리즘을 구현할 수없는 이유를 이해하지 못합니다. SetDeviceGammaRamp?를 사용하여이 클래스에서 회색 음영 변환을 구현하는 방법에 대한 제안 사항이 있습니까?Windows OS에서 그레이 스케일로 화면 전환

public static class GammaRamp 
    { 
     [DllImport("gdi32.dll")] 
     private unsafe static extern bool SetDeviceGammaRamp(Int32 hdc, ushort* ramp); 

     [DllImport("gdi32")] 
     private unsafe static extern bool GetDeviceGammaRamp(Int32 hdc, ushort* ramp); 

     private static Int32 hdc; 

     public static unsafe void Set(int aBrightness, int aRed, int aGreen, int aBlue) 
     { 
      double red = 1, green = 1, blue = 1; 

      red = (double)aRed/(double)255; 
      green = (double)aGreen/(double)255; 
      blue = (double)aBlue/(double)255; 

      //Memory allocated through stackalloc is automatically free'd by the CLR. 
      ushort* rgbArray = stackalloc ushort[768]; //3 * 256 
      ushort* idx = rgbArray; 

      for (int j = 0; j < 3; j++) 
      { 
       for (int i = 0; i < 256; i++) 
       { 
        double arrayVal = (double)(i * (aBrightness + 128)); 

        if (arrayVal > 65535) 
         arrayVal = (double)65535; 

        if (j == 0) //red 
         arrayVal = arrayVal * red * 0.2126; 
        else if (j == 1) //green 
         arrayVal = arrayVal * green * 0.7152; 
        else //blue 
         arrayVal = arrayVal * blue * 0.0722; 

        *idx = (ushort)arrayVal; 
        idx++; 
       } 
      } 

      hdc = Graphics.FromHwnd(IntPtr.Zero).GetHdc().ToInt32(); 
      SetDeviceGammaRamp(hdc, rgbArray); 
     } 
} 

그것이이 승리 7, 8 및 10 supportted 때문에 내가 선호 무엇 GammaRamp를 사용할 수없는 경우, 나는 새로운 기능을 사용하지만

enter image description here 윈도우 (10)에 대한 것입니다 나는 레지스트리 키

컴퓨터 \ HKEY_CURRENT_USER \ 소프트웨어 \ 마이크로 소프트 \ ColorFiltering가 활성 \ = 1다음 변경해야 WPF 응용 프로그램에서이 설정을 제어 할 뿐이다

컴퓨터 \ HKEY_CURRENT_USER \ 소프트웨어 \ 마이크로 소프트 \ ColorFiltering \ FilterType = 나는 쉽게,하지만 어떻게 윈도우 OS가 레지스트리에서이 새로운 설정을 새로 고칠 수 있도록하기 위해 할 수있는

0? 이것은 유용한 대답입니다.

마지막으로 나는 GammaRamp 또는 다른 옵션을 사용할 방법이 없다면 Windows 용으로 사용하는 MagSetColorEffect winAPI에 대해 알고 있다고 말할 것입니다.하지만 Aero를 활성화해야하기 때문에 마지막 옵션입니다. 종류의 제한.

+1

당신은 이유를 명확히 할 수 'MagSetColorEffect'를 사용하고 싶지 않으십니까? 그것은 테마를 필요로하지 않고 데스크톱 구성 만 지원합니다 - Vista 이후 기본적으로 활성화되었습니다. Windows 8은 전원을 끌 수도있는 가능성을 제거했습니다. 'MagSetColorEffect'를 사용할 수있는 인구는 FCU에 추가 된 기능을 사용할 수있는 인구보다 확실히 많습니다. 나는 [야간 시력을 보존하기 위해이 API를 사용한다] (https://stackoverflow.com/questions/32928212/night-vision-mode-on-wpf-windows/32929962#32929962). – Mitch

+0

@Mitch [네거티브 스크린] (http://arcanesanctum.net/negativescreen/)과 같이 그레이 스케일로 화면을 전환시키는 몇 가지 앱을 알고 있으며, 그들은 Aero on Win 7을 돌리라고 요청합니다. 그렇지 않으면 작동하지 않습니다. 그리고 [아이리스] (https://iristech.co/type-dropdown-help/)에는 에어로가 필요합니다. 그래서 필자는 그것이 반드시 필요하다고 생각합니다. – vinsa

+1

DWM이 필요 없다고 말하는 것은 아니지만 대부분의 사람들이 Aero라고 부르는 것을 요구하지 않습니다. DWM은 전적으로 뒤에서 사용되는 합성 엔진입니다. 5 분 전에 테스트 한 결과,'MagSetFullscreenColorEffect'는 소프트웨어 GPU 만있는 VM에서 작동하고, 모든 효과가 비활성화 된 랩탑에서 작동하며, "클래식 테마"가 작동합니다. Win 8+에서는 구성을 사용 중지하는 합리적인 방법이 없습니다. [Windows 8에서 데스크톱 구성 사용 안 함] (https://superuser.com/questions/581673/disable-desktop-composition-in-windows-8-force-it)을 참조하십시오. – Mitch

답변

6

회색 음영 필터를 만들기 위해 SetDeviceGammaRamp과 같은 기능을 사용할 수 없습니다. 회색 음영 필터는 각 색상 채널에서 개별적으로 작동하기 때문입니다. lpRamp 매개 변수는 비디오 카드가 사용하는 LUT를 설정하여 (스크린 샷에 저장되는 것처럼) 픽셀 강도를 전송 된 강도 (VGA 커넥터의 핀에 배치되는 것처럼)에 매핑합니다. 이것은 주로 레거시 API이며 스크린 샷, 원격 데스크톱 또는 모든 그래픽 카드 작업에는 영향을 미치지 않습니다.

회색 음영 색상 필터를 만들려면 각 색상 채널에서 데이터를 가져 와서 혼합해야합니다. 선택적으로, 가중치 함수를 적용하여 결과 이미지가 인간의 인식을보다 정확하게 반영하도록 할 수 있습니다.

diagram showing mixing of red, green, and blue color channels

당신은 당신이 MagSetFullscreenColorEffect 기능으로 지정된 스케일링 요소 사용 (위의 윈도우 8 또는 실행 대부분의 모든 PC에서 사용할 수 있으며, 윈도우 7 PC의 대부분에) 할 수 있습니다. 나는 현재 FCU 머신에 액세스 할 수 없지만 설정의 새 옵션이 단지 MagSetFullscreenColorEffect이라고 의심 할 것입니다.

MagSetFullscreenColorEffect은 RGBX의 4 개 공간을 변형 할 수있는 색상 매트릭스를 사용합니다. 변환 행렬 on MSDN 또는 many other places에 대해 알아볼 수 있습니다. ColorMatrix Viewer (GitHub)은 이러한 색상 행렬을 테스트하고 조정하기위한 훌륭한 도구입니다.

이렇게하려면 MagSetFullscreenColorEffect을 사용하는 방법에 대한 예는 아래 샘플을 참조하십시오.

C++ :

#include <magnification.h> 
#pragma comment(lib, "magnification.lib") 

float redScale = 0.2126f, greenScale = 0.7152f, blueScale = 0.0722f; 
MAGCOLOREFFECT magEffectInvert = 
{ 
    { 
     { redScale, redScale, redScale, 0.0f, 0.0f }, 
     { greenScale, greenScale, greenScale, 0.0f, 0.0f }, 
     { blueScale, blueScale, blueScale, 0.0f, 0.0f }, 
     { 0.0f,  0.0f,  0.0f,  1.0f, 0.0f }, 
     { 0.0f,  0.0f,  0.0f,  0.0f, 1.0f } 
    } 
}; 

MagInitialize(); 
if (!MagSetFullscreenColorEffect(&magEffectInvert)) 
{ 
    std::cout << "Failed " << GetLastError() << std::endl; 
} 
system("pause"); 
MagUninitialize(); 

C 번호 :

using System; 
using System.Runtime.InteropServices; 

namespace ManagedColorPlayground 
{ 
    using static NativeMethods; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      float redScale = 0.2126f, greenScale = 0.7152f, blueScale = 0.0722f; 
      var magEffectInvert = new MAGCOLOREFFECT { 
       transform = new [] { 
        redScale, redScale, redScale, 0.0f, 0.0f, 
        greenScale, greenScale, greenScale, 0.0f, 0.0f, 
        blueScale, blueScale, blueScale, 0.0f, 0.0f, 
        0.0f,  0.0f,  0.0f,  1.0f, 0.0f, 
        0.0f,  0.0f,  0.0f,  0.0f, 1.0f 
       } 
      }; 

      MagInitialize(); 
      MagSetFullscreenColorEffect(ref magEffectInvert); 
      Console.ReadLine(); 
      MagUninitialize(); 
     } 
    } 

    static class NativeMethods 
    { 
     const string Magnification = "Magnification.dll"; 

     [DllImport(Magnification, ExactSpelling = true, SetLastError = true)] 
     public static extern bool MagInitialize(); 

     [DllImport(Magnification, ExactSpelling = true, SetLastError = true)] 
     public static extern bool MagUninitialize(); 

     [DllImport(Magnification, ExactSpelling = true, SetLastError = true)] 
     public static extern bool MagSetFullscreenColorEffect(ref MAGCOLOREFFECT pEffect); 

     public struct MAGCOLOREFFECT 
     { 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)] 
      public float[] transform; 
     } 
    } 
} 

MagSetFullscreenColorEffect 전 : color

MagSetFullscreenColorEffect 후 : grayscale

+0

** Mitch ** 대답은 아주 좋았습니다. 테스트 해 보았지만 Windows 7에서 C# 코드가 나를 던졌습니다. 'Magnification.dll'에서 'MagSetFullscreenColorEffect'라는 엔트리 포인트를 찾을 수 없습니다. ' 왜 그런지 알아? – vinsa

+0

Windows 7에는'MagSetFullscreenColorEffect'가 존재하지 않습니다. Windows 7에 존재하는 함수는'SetMagnificationDesktopColorEffect' (User32)이지만 문서화되어 있지 않습니다. – Mitch

+0

Win 10 및 Win 7 (Aero가 켜져있는 경우)에서 작동하므로 ** SetMagnificationDesktopColorEffect **를 사용하는 것이 더 좋습니다. public static extern bool SetMagnificationDesktopColorEffect (ref MAGCOLOREFFECT pEffect); ' MagSetFullscreenColorEffect를 SetMagnificationDesktopColorEffect로 바꾸려면 대답을 바꿀 수 있습니다. if [(DllImport ("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true) 당신의 대답이 받아 들여지고 현상금을 얻을 수있는 더 좋은 제안은 없습니다. – vinsa