-
Notifications
You must be signed in to change notification settings - Fork 675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The image quality deteriorates on SwapChainPanel(with Direct2D) #9794
Comments
Hi I'm an AI powered bot that finds similar issues based off the issue title. Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one. Thank you! Closed similar issues:
|
I cannot test your code (cannot compile C+/WinRT on my PC), but in C# your .png image is correct if I draw it with D2D1_BITMAP_INTERPOLATION_MODE_LINEAR (I loaded it with WIC, LoadBitmapFromFile function from WinUI3_Direct2D_Effects that I adapted from MS) |
Direct2D's high DPI support is surprising in places, but I can guarantee one thing, it doesn't set anything to match SwapChainPanel. The DPI has always been configurable on the ID2D1RenderTarget interface, and ID2D1DeviceContext allows you to set Direct2D's unit mode to pixels and not DIPs. One other issue is that it is difficult to see what is going on due to you clearing the swap chain surface to the same colour as the Xaml background. Things get interesting if I make one single modification to your code. If I change your: Is what I get if I run the application, but what happens if I resize the window? The pink area is the area drawn to by Direct2D, so what your code is doing is taking the source image and then shrinking it down thus resulting in this loss of quality. My system is at 125%, so this is effectively taking the 500x500px image and scaling it down to 400x400px. (width / 1.25 and height / 1.25). There are three things to remember here. First, it is more than likely that SwapChainPanel is placing a scaling transform on the swapchain surface itself, and after all other drawing occurs. Secondly, SwapChainPanel sizes itself to the size of the swapchain automatically, this means that it will be the width and height scaled by the window scaling factor. Third, it seems as if it doesn't care about the window size, if the window's client rectangle is smaller than the scaled swapchains size, then it will just let some of it go off of the end. |
@castorix @DarranRowe |
Did you try to draw the image with D2D1_BITMAP_INTERPOLATION_MODE_LINEAR ? |
I did not use I don't want any scaling to be performed in the application. Let me explain what I mean. In my Win32 + Direct2D application, I was using the following: SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); By executing this, the client area of a window always operates at 96 DPI regardless of the display's DPI scaling. The parts outside the client area operate according to the display's DPI scaling. I want to do the same thing with WinUI3 + Direct2D. |
@castorix |
Yes, I have let the default 1,1 scaling for the SwapChainPanel
XAML (scpD2D in a grid) :
and I get : |
@DarranRowe @castorix The yellow dots indicate the differences. The output is 500x500 pixels, but due to internal scaling within the application, differences can be observed. On the other hand, the comparison below shows the screenshot of a Win32 application with DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 enabled (taken with the display's DPI scaling set to 150%) (on the right). Since no scaling is applied, the image quality remains unchanged. I want to achieve this with WinUI3 and |
I get (nearly) the same images from the above test with RenderTransform : |
(I attached the wrong file in my previous post, so I deleted it and am reposting it now.) I understand what you are saying. When I used Source code: SwapChainPanelTest.zip Here is an important point to note: setting a value less than 1.0 for Therefore, it becomes necessary to change the size of The code example is as follows: MainWindow.xaml <SwapChainPanel
x:Name="swapChainPanel"
Width="1" Height="1"
HorizontalAlignment="Left" VerticalAlignment="Top"
Loaded="swapChainPanel_Loaded"/> MainWindow.xaml.cpp //
// Get composition scales of SwapChainPanel
//
auto panel = this->swapChainPanel();
auto compositionScaleX = panel.CompositionScaleX();
auto compositionScaleY = panel.CompositionScaleY();
//
// Set RenderTransform of SwapChainPanel
//
auto scaleTransform = Media::ScaleTransform();
scaleTransform.ScaleX(1.0 / compositionScaleX);
scaleTransform.ScaleY(1.0 / compositionScaleY);
panel.RenderTransform(scaleTransform);
//
// Resize the window size
//
AppWindow().ResizeClient(SizeInt32(imageWidth, imageHeight));
//
// Resize SwapChainPanel size
//
panel.Width(static_cast<double>(imageWidth) * compositionScaleX);
panel.Height(static_cast<double>(imageHeight) * compositionScaleY);
Also, in Direct2D, there is no need to consider DPI. It is perfectly fine to always set all DPIs to 96.0. With this, I was able to achieve what I was looking for with WinUI3 and I am truly grateful to @castorix and @DarranRowe. Thank you very much. |
Is anyone here still blocked or have the issues been resolved? |
Describe the bug
When drawing an image to
SwapChainPanel
withDirect2D
when the display's DPI scaling is set to anything other than 100%, the transfer does not occur pixel-by-pixel, resulting in a degradation of image quality.Steps to reproduce the bug
Source code SwapChainPanelTest.zip
CompositionScaleX
andCompositionScaleY
ofSwapChainPanel
Assets\test.png
)ID2D1DeviceContext
IDXGIFactory2
SwapChain
(IDXGISwapChain1
) usingCreateSwapChainForComposition
ISwapChainPanelNative
fromSwapChainPanel
and setSwapChain
BackBufferBitmap
(ID2D1Bitmap1
,dpiX = 96 x CompositionScaleX
anddpiY = 96 x CompositionScaleY
) for the back buffer fromIDXGISurface
SourceBitmap
(ID2D1Bitmap1
,dpiX = 96 x CompositionScaleX
anddpiY = 96 x CompositionScaleY
) for the source imageCopyFromMemory
to copy the source image toSourceBitmap
BeginDraw
DrawBitmap
to renderSourceBitmap
ontoBackBufferBitmap
(The rectangles of both Bitmaps are (0, 0,image width / compositionScaleX
,image height / compositionScaleY
))EndDraw
andPresent
When the display's DPI scaling is set to anything other than 100%,
SwapChainPanel
usesdevice-independent pixels
. To match this,Direct2D
also sets the DPI to usedevice-independent pixels
. At first glance,DrawBitmap
method appears to perform a pixel-by-pixel transfer because the rectangles ofSourceBitmap
andBackBufferBitmap
are the same. However, scaling is actually performed. This can be confirmed by observing that the image quality changes whenD2D1_INTERPOLATION_MODE
is changed.Expected behavior
Display the source image without any modifications.
Screenshots
DPI scaling = 100%
DPI scaling = 150%
NuGet package version
WinUI 3 - Windows App SDK 1.5.4: 1.5.240607001
Windows version
Windows 11 (22H2): Build 22621
Additional context
I have read this.
SwapChainPanel scales SwapChain content by DPI scale · Issue #8219
The text was updated successfully, but these errors were encountered: