This article is a personal blog backup article, the original address:
http://validvoid.net/win2d-dpi-dips/
This article is intended to explain the difference between physical pixels and device-independent pixels (DIPs, devices independent pixels), and how win2d handles DPI (dots per inch/in dots).
WIN2D is designed to be self-aware of the device environment to render the correct visual representation on devices of varying dpi, so most applications can ignore the difference between DIPs and DPI. If your app has more specific needs, or you want to customize the default perceptual behavior yourself, you can continue reading the details below ...
What is DPI?
DPI stands for dots per inch, which can roughly measure the pixel density rendered on display output devices such as computer monitors or phone screens. The larger the DPI, the more points the display output renders, and the smaller the size.
Because not all display hardware can accurately report display data, DPI is only a coarse measure. Some computer monitors do not report DPI values to the operating system at all, and it is possible for users to configure a DPI that does not match the actual hardware to render the system (such as changing the size of the UI text elements). The application can refer to DPI to determine how a large object is drawn, but it should not be calculated as a precise physical measure of the size of the display device.
The recommended default value for DPI is 96.
What is a pixel?
A pixel is an independent color point. The image in computer graphics is composed of many pixels in a two-dimensional grid. You can interpret pixels as atoms that make up all the images.
In different display devices, the actual physical size of a pixel can vary enormously. When a computer is connected to a monitor or external display device with a large size but very small resolution, the pixel (physical size) is very large, but the pixel (physical size) is very small on a screen that is only a few inches but with a resolution of 1080p phones.
In win2d, when you see the API using an integer data type (or a BitmapSize
structure that encapsulates integer members), specifying the location or size means that the API is operating in pixels.
Most win2d APIs operate on a DIP rather than a pixel basis.
What is DIP?
DIP refers to "device independent pixels", which is a virtualized unit that may be larger or smaller than the size of a physical pixel.
The ratio between the physical pixels and the DIP depends on the DPI:
pixels = dips * dpi / 96
When the DPI is 96 o'clock, the number of pixels is equal to the DIP value. The higher the DPI, the more a DIP is larger than the size of one pixel (or portions of multiple pixels, since the DPI is usually not an absolute multiple of 96).
Including win2d, most Windows runtime APIs operate on a DIP rather than a pixel basis. This facilitates the rendering of graphs that are approximately equal in physical size, regardless of the display device on which the application is running. For example, the app specifies a button with a width of DIP, and when the app is running on a high-DPI device such as a phone or 4k monitor, the physical pixel width of the button is automatically scaled to greater than 100 pixels so that the user can click. And if the size of the button is set in pixels, the buttons become surprisingly small on such high-DPI display devices, and the app will have to spend more time laying out adjustments for different types of screens.
In win2d, when you see the API using a floating-point data type (or a Vector2
Size
structure that encapsulates floating-point value members), specifying a location or size means that the API is operating in dips.
To convert between dips and pixels, you can use both Convertdipstopixels (single, canvasdpirounding) and Convertpixelstodips (Int32) methods.
win2d Resources with DPI
All win2d resources that contain bitmap images have a DPI attribute:
- Canvasbitmap
- Canvasrendertarget
- Canvasswapchain
- Canvascontrol
- Canvasvirtualcontrol
- Canvasanimatedcontrol
- Canvasimagesource
All other resources are DPI-independent. For example, a canvasdevice (canvas device) instance can be used to draw a variety of different DPI controls or render targets (rendertarget), so the device itself does not have a DPI attribute.
Similarly, the canvascommandlist (Canvas command list) does not have a DPI attribute because it contains vector drawing directives rather than bitmaps. DPI plays a role in the rasterization process when the list of commands is drawn to a render target (rendertarget) or control.
Control DPI
The win2d controls (Canvascontrol, Canvasvirtualcontrol, and Canvasanimatedcontrol) automatically use the same DPI in the app's currently running display device. This is consistent with the coordinate system used by XAML, CoreWindow, and other Windows runtime APIs.
If the DPI changes (for example, the app moves to another display device), the control fires the CreateResources
event and passes a Canvascreateresourcesreason type enumeration parameter with a value of dpichanged. The app should recreate any resources (such as rendertargets) that depend on the DPI of the control in the event response.
RenderTarget (render target) DPI
Objects that can be drawn as targets (except Canvasrendertarget and class rendertarget types such as Canvasswapchain and Canvasimagesource) also have DPI properties on their own. Unlike controls, however, these types are not directly related to the display device, so win2d cannot automatically specify the best DPI for it. If you draw the content to a render target (RenderTarget) that will be output to the screen later, you should use the same DPI as the screen, and if you are drawing for other purposes (for example, to upload a picture for uploading to a website), then the default of-DPI is recommended.
To facilitate this type of usage, WIN2D provides two constructor overloads:
Canvasrendertarget (icanvasresourcecreator, width, height, dpi) canvasrendertarget (icanvasresourcecreatorwithdpi, width, height)
CanvasDevice
And the win2d control both implement the Icanvasresourcecreator interface. Because the device itself does not specify any dpi, you must explicitly specify the DPI when you create a render target (rendertarget). For example, create a DIP with pixels that are always equal to the default DPI render target:
Const float the ; var New Canvasrendertarget (canvasdevice, width, height, defaultdpi);
The ICANVASRESOURCECREATORWITHDPI interface extends the interface by adding a DPI property ICanvasResourceCreator
. The win2d control implements this interface, simplifying the process of creating a render target (RenderTarget) that automatically inherits DPI from the source control:
var New Canvasrendertarget (Canvascontrol, width, height);
Bitmap DPI
Unlike render targets (RenderTarget), Canvasbitmap does not automatically inherit DPI values from source controls. The method of creating and loading a bitmap contains multiple overloads that can be explicitly specified in DPI, but if you do not manually specify a DPI value, the bitmap DPI is automatically set to the default of 96 regardless of the current display device's configuration.
Bitmaps are different from other types because they are input data sources, not output targets for plotting. So for bitmaps, the key is to input the dpi of the image rather than the output target dpi. The dpi of the input image is completely unrelated to the current display device's DPI setting.
If you have a 100x100, DPI default bitmap that draws it to a render target (rendertarget), the bitmap will be scaled from the size of the 100-dpi (that is, the pixel) to the size of the render target dpi (if the render target DPI is greater than the original DPI of the bitmap, the output pixel will be greater than 100 pixels. The final result image will always maintain the size of the DIP (so there will be no unexpected layout exceptions), but if the source bitmap is dpi low, the scaled high DPI target image will blur.
To ensure optimal clarity at high DPI, some applications may want to provide multiple sets of bitmap images for different resolutions, and at load time select the resource that best matches the DPI of the target control. Other applications, however, choose to encapsulate only high-dpi bitmaps, allowing win2d to zoom out when running on low-DPI display devices (the effect is always better than zooming in). In both cases, the bitmap DPI can be specified as a parameter to the LoadAsync (Icanvasresourcecreator, String, single) method.
Note that some bitmap file formats themselves have DPI metadata, but given that these metadata are often inaccurate, win2d ignores them when loaded. By contrast, the DPI must be explicitly specified when the bitmap is loaded.
Canvasdrawingsession DPI
Canvasdrawingsession inherits DPI from any control, render target (RenderTarget), Swapchain, and so on, as its drawing target.
By default, all drawing operations are done based on dips. If you want to work with pixels, you can do so by changing the Units property.
How to test the DPI response of your app
The easiest way to test if your app is correctly responding to DPI changes is to run your app in a Windows 10 environment and then change the display settings during run time:
- Right-click the desktop background and select
显示选项
- Drag
更改文本、应用和其它项目大小
the slider
- Click the ' Apply ' button
- Select ' Sign out later '
If you don't have a Windows 10 environment, you can also test through the Windows emulator. On the Visual Studio toolbar, change the debug target from 本机
modified to 模拟器
, and then click the Modify Resolution button on the emulator to toggle between the following analog resolutions:
- 100% (dpi=96)
- 140% (dpi=134.4)
- 180% (dpi=172.8)
WIN2D Official Article Series Translations-DPI (dots per inch) and DIPs (device independent pixels)