이 문서에서는 물리적 픽셀과 디바이스 독립적 픽셀(DIP)의 차이점과 Win2D에서 DPI(인치당 점)를 처리하는 방법을 설명합니다.
Win2D는 많은 앱이 이러한 구분을 무시할 수 있도록 설계되었기 때문에 낮은 DPI 장치와 높은 DPI 장치 모두에서 실행할 때 올바른 동작을 하는 합리적인 기본 동작을 제공합니다. 앱에 더 전문적인 요구 사항이 있거나 "합리적인 기본값"의 의미에 대해 다른 의견이 있는 경우 세부 정보를 읽어보세요...
DPI란?
DPI는 "인치당 점"을 의미합니다. 컴퓨터 모니터 또는 휴대폰 화면과 같은 출력 디스플레이의 픽셀 밀도에 대한 대략적인 측정값입니다. DPI가 높을수록 더 작은 점이 디스플레이를 구성합니다.
모든 디스플레이 하드웨어가 정확한 정보를 보고할 수 있는 것은 아니므로 DPI는 대략적인 수치일 뿐입니다. 일부 컴퓨터 모니터는 운영 체제에 DPI를 전혀 보고하지 않거나 사용자가 실제 하드웨어와 다른 DPI를 사용하여 렌더링하도록 시스템을 구성했을 수 있습니다(예: UI 텍스트 요소의 크기 변경). 애플리케이션은 DPI를 사용하여 사물을 얼마나 크게 그릴지 선택할 수 있지만, 디스플레이 크기의 정확한 물리적 측정값으로 사용해서는 안 됩니다.
DPI 값 96은 중립적인 기본값으로 간주됩니다.
픽셀이란?
픽셀은 단일 색의 점입니다. 컴퓨터 그래픽의 이미지는 2차원 그리드로 정렬된 많은 픽셀로 구성됩니다. 픽셀을 모든 이미지가 빌드되는 원자로 생각할 수 있습니다.
픽셀의 물리적 크기는 디스플레이마다 크게 다를 수 있습니다. 컴퓨터가 크지만 해상도가 낮은 모니터나 외부 디스플레이에 연결되어 있으면 픽셀이 상당히 커질 수 있지만, 가로가 몇 인치밖에 되지 않는 1080p 디스플레이가 있는 휴대폰에서는 픽셀이 작아집니다.
Win2D에서 정수 데이터 형식(또는 정수가 포함된 BitmapSize와 같은 구조체)을 사용하여 위치 또는 크기를 지정하는 API가 표시될 때마다 API가 픽셀 단위로 작동합니다.
대부분의 Win2D API는 픽셀이 아닌 DIP에서 작동합니다.
DIP란?
DIP는 "디바이스 독립적 픽셀"을 의미합니다. 실제 픽셀과 같거나, 크거나, 작을 수 있는 가상화된 단위입니다.
픽셀과 DIP 간의 비율은 DPI에 의해 결정됩니다.
pixels = dips * dpi / 96
DPI가 96이면 픽셀과 DIP가 동일합니다. 더 높은 DPI를 사용하는 경우 단일 DIP는 둘 이상의 픽셀(또는 DPI가 96의 정확한 배수가 아닌 일반적인 경우 픽셀의 일부)에 해당할 수 있습니다.
Win2D를 비롯한 대부분의 Windows 런타임 API는 픽셀이 아닌 DIP를 사용합니다. 이렇게 하면 앱이 실행되는 디스플레이에 관계없이 그래픽을 실제 크기와 거의 동일하게 유지할 수 있다는 장점이 있습니다. 예를 들어 앱에서 단추 너비가 100 DIP라고 지정하는 경우 휴대폰 또는 4k 모니터와 같은 높은 DPI 디바이스에서 실행할 때 이 단추는 자동으로 너비가 100픽셀 이상으로 조정되므로 사용자가 클릭할 수 있는 적당한 크기로 유지됩니다. 반면에 버튼 크기를 픽셀 단위로 지정하면 이런 종류의 높은 DPI 디스플레이에서는 터무니없이 작게 표시되므로 앱이 화면 종류에 따라 레이아웃을 다르게 조정하기 위해 더 많은 작업을 수행해야 합니다.
Win2D에서 부동 소수점 데이터 형식(또는 부동 소수점 값이 포함된 Vector2 또는 Size와 같은 구조체)을 사용하여 위치 또는 크기를 지정하는 API가 표시될 때마다 API가 DIP에서 작동한다는 의미입니다.
DIP와 픽셀 간에 변환하려면 메서드 ConvertDipsToPixels(Single, CanvasDpiRounding)
및 ConvertPixelsToDips(Int32)
를 사용합니다.
DPI가 있는 Win2D 리소스
비트맵 이미지를 포함하는 모든 Win2D 리소스에도 연결된 DPI 속성이 있습니다.
CanvasBitmap
CanvasRenderTarget
CanvasSwapChain
CanvasControl
CanvasVirtualControl
CanvasAnimatedControl
CanvasImageSource
다른 모든 리소스 종류는 DPI와 독립적입니다. 예를 들어 단일 CanvasDevice
인스턴스를 사용하여 다양한 DPI의 컨트롤 또는 렌더 대상을 그릴 수 있으므로 디바이스에는 자체 DPI가 없습니다.
마찬가지로 CanvasCommandList
는 비트맵 이미지가 아닌 벡터 그리기 명령이 포함되어 있으므로 DPI가 없습니다. DPI는 명령 목록이 rendertarget 또는 컨트롤(DPI 포함)에 그려지는 경우 래스터화 프로세스 중에만 재생됩니다.
컨트롤 DPI
Win2D 컨트롤(CanvasControl
CanvasVirtualControl
및CanvasAnimatedControl
)은 앱이 실행 중인 디스플레이와 동일한 DPI를 자동으로 사용합니다. XAML, CoreWindow 및 기타 Windows 런타임 API에서 사용하는 좌표계와 일치합니다.
DPI가 변경되면(예: 앱이 다른 디스플레이로 이동하는 경우) 컨트롤이 CreateResources
이벤트를 발생시키고 CanvasCreateResourcesReason
of DpiChanged
을 전달합니다. 앱은 컨트롤의 DPI에 종속된 리소스(예: rendertargets)를 다시 만들어 이 이벤트에 응답해야 합니다.
Rendertarget DPI
이러한 것들은 (CanvasRenderTarget
뿐만 아니라 렌더링 대상과 유사한 형식 CanvasSwapChain
및 CanvasImageSource
) 자체 DPI가 있지만 컨트롤과 달리 이러한 유형은 디스플레이에 직접 연결되어 있지 않으므로 Win2D가 자동으로 DPI를 결정할 수 없습니다. 나중에 화면에 복사될 rendertarget에 그리는 경우 해당 rendertarget이 화면과 동일한 DPI를 사용하려고 하지만 다른 용도로 그리는 경우(예: 웹 사이트에 업로드할 이미지 생성) 기본 96 DPI가 더 적합합니다.
이러한 두 사용 패턴을 쉽게 만들기 위해 Win2D는 두 가지 유형의 생성자 오버로드를 제공합니다.
CanvasRenderTarget(ICanvasResourceCreator, width, height, dpi)
CanvasRenderTarget(ICanvasResourceCreatorWithDpi, width, height)
ICanvasResourceCreator
인터페이스는 Win2D 컨트롤뿐만 아니라 CanvasDevice
로 구현됩니다. 디바이스에는 고유한 특정 DPI가 없으므로 하나의 렌더 대상을 만들 때 DPI를 명시적으로 지정해야 합니다.
예를 들어 DIP 및 픽셀이 항상 동일한 기본 DPI rendertarget을 만들려면 다음을 수행합니다.
const float defaultDpi = 96;
var rtWithFixedDpi = new CanvasRenderTarget(canvasDevice, width, height, defaultDpi);
ICanvasResourceCreatorWithDpi
는 DPI 속성을 추가하여 ICanvasResourceCreator
을 확장합니다. 이 인터페이스는 Win2D 컨트롤에 의해 구현되며, 만든 컨트롤과 동일한 DPI를 자동으로 상속하는 rendertarget을 쉽게 만들 수 있습니다.
var rtWithSameDpiAsDisplay = new CanvasRenderTarget(canvasControl, width, height);
비트맵 DPI
CanvasBitmap
는 rendertarget과 달리 컨트롤에서 DPI를 자동으로 상속하지 않습니다. 비트맵을 만들고 로드하는 방법에는 DPI를 명시적으로 지정하는 오버로드가 포함되지만, 이를 제외하면 비트맵 DPI는 현재 표시 구성에 관계없이 기본적으로 96으로 설정됩니다.
비트맵이 다른 형식과 다른 이유는 비트맵이 그려지는 출력이 아니라 입력 데이터의 원본이기 때문입니다. 따라서 비트맵의 중요한 점은 해당 출력이 끝나는 DPI가 아니라 현재 디스플레이 설정과 전혀 관련이 없는 원본 이미지의 DPI입니다.
100x100 기본 DPI 비트맵을 로드한 다음 rendertarget에 그리면 비트맵은 대상 렌더 대상의 DPI에서 96DPI(100픽셀)에서 100 DIP(높은 DPI rendertarget인 경우 더 많은 수의 픽셀일 수 있음)로 크기가 조정됩니다. 결과 이미지는 항상 100 DIP 크기가 되지만(따라서 레이아웃이 불쾌하지 않습니다), 낮은 DPI 소스 비트맵을 더 높은 DPI 대상으로 확대하면 약간의 흐림 현상이 발생할 수 있습니다.
높은 DPI에서 선명도를 극대화하기 위해 일부 애플리케이션은 서로 다른 해상도의 여러 비트맵 이미지 집합을 제공하고 로드 시 대상 컨트롤의 DPI에 가장 근접한 버전을 선택해야 할 수 있습니다. 다른 앱은 높은 DPI 비트맵만 제공하고, 낮은 DPI 디스플레이에서 실행할 때는 Win2D가 이를 축소하도록 할 수 있습니다(축소하는 것이 확대하는 것보다 보기 좋을 수 있습니다). 두 경우 모두 비트맵 DPI를 매개 변수 LoadAsync(ICanvasResourceCreator, String, Single)
로 지정할 수 있습니다.
일부 비트맵 파일 형식에는 자체의 DPI 메타데이터가 포함되어 있지만 Win2D는 잘못 설정된 경우가 많기 때문에 이를 무시합니다. 대신 비트맵을 로드할 때 DPI를 명시적으로 지정해야 합니다.
CanvasDrawingSession DPI
CanvasDrawingSession
는 그리는 컨트롤, rendertarget, swapchain 등에서 해당 DPI를 상속합니다.
기본적으로 모든 그리기 작업은 DIP에서 작동합니다. 픽셀 단위로 작업하려는 경우 Units
속성을 통해 변경할 수 있습니다.
효과 DPI
이미지 효과 파이프라인은 효과가 그려지는 CanvasDrawingSession
가 무엇이든 간에 DPI를 상속합니다. 내부적으로 효과 처리는 항상 픽셀 단위로 작동합니다. 크기 또는 위치와 같은 매개 변수 값은 DIP에 지정되지만 실제 이미지 조작이 수행되기 전에 이러한 단위는 픽셀로 변환됩니다.
대상 그리기 세션과 다른 DPI의 비트맵이 효과 원본 이미지로 사용되는 경우 비트맵과 효과 사이에 내부 DpiCompensationEffect
가 자동으로 삽입됩니다. 이렇게 하면 비트맵이 대상 DPI와 일치하도록 크기가 조정됩니다. 일반적으로 원하는 대상 DPI입니다. 원하는 인스턴스가 아닌 경우 고유한 DpiCompensationEffect
의 인스턴스를 삽입하여 동작을 사용자 지정할 수 있습니다.
참고 항목
사용자 지정 효과를 구현하는 경우 기본 제공 Win2D 효과와 함께 사용할 때 일관된 동작을 보장하기 위해 해당하는 DPI 처리 체계를 적용하는 것이 좋습니다.
컴퍼지션 API
Microsoft.Graphics.Canvas.Composition
API는 Win2D XAML 컨트롤보다 낮은 수준에서 작동하므로 사용자를 대신하여 DPI를 자동으로 처리하려고 시도하지 않습니다. 원하는 단위를 결정하고 컴퍼지션 시각적 트리의 일부로 이를 달성하는 데 필요한 변환을 설정하는 것은 사용자의 몫입니다.
CreateDrawingSurface
같은 Windows.UI.Composition
API는 항상 픽셀 단위로 크기를 지정합니다. Win2D를 사용하여 컴퍼지션 화면에 그릴 때 CreateDrawingSession(CompositionDrawingSurface, Rect, Single)
을 호출할 때 사용할 DPI를 지정할 수 있습니다. 반환된 CanvasDrawingSession
을 통해 수행되는 모든 드로잉은 그에 따라 스케일 업 또는 다운됩니다.
DPI 처리를 테스트하는 방법
디스플레이 DPI 변경에 대한 응답으로 앱이 올바른 작업을 수행하는지 테스트하는 가장 쉬운 방법은 Windows 10 또는 Windows 11에서 실행하고 앱이 실행되는 동안 디스플레이 설정을 변경하는 것입니다.
- 바탕 화면 배경을 마우스 오른쪽 단추로 클릭하고 '설정 표시'를 선택합니다.
- '텍스트, 앱 및 기타 항목의 크기 변경'이라는 레이블이 지정된 슬라이더를 이동합니다.
- '적용' 단추를 클릭합니다.
- '나중에 로그아웃'을 선택합니다.
windows 10 또는 windows 11이 없는 경우 Windows 시뮬레이터를 사용하여 테스트할 수도 있습니다. Visual Studio 도구 모음에서 "로컬 컴퓨터" 설정을 "시뮬레이터"로 변경한 다음, 변경 확인 아이콘을 사용하여 시뮬레이션된 디스플레이를 다음 간에 전환합니다.
- 100% (DPI = 96)
- 140% (DPI = 134.4)
- 180% (DPI = 172.8)
Windows developer