Qt, high dpi and frameGeometry - qt

I've enabled HDPI by setting QT_SCALE_FACTOR environment variable.
Then I've found that my main window appears somewhere behind the screen.
After some debugging I've found that frameGeometry() returns less than zero.
P.s. : There are 2 monitors in the system also. One has 96 dpi, other is in 144 dpi mode.
For example:
left top = {-1920, -30}
width, height = {968, 820}
Has anyone faced any similar problem?

Related

Qt: Why DPI decrease on increasing Scaling from OS

I have a Qt application and I need to adapt the application (zoom-in/zoom-out) as the scaling changes from the OS in Display Settings.
I have read from Internet that:
The standard DPI settings are 100% (96 DPI), 125% (120 DPI), and 150%
(144 DPI)
But, I am getting below DPI values when logged from the Qt application:
Scale - Physical DPI X - Physical DPI Y
100% - 158, 159
125% - 158, 159
150% - 79, 79
175% - 79, 79
So, as per the above values, the application text size has no difference for the 100% and 125% scale. Same behavior applies for 150% and 175%.
Below is the Qt code that I used:
#include <QWidget>
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QWidget widget;
qInfo() << "Hello Qt";
int dpiX = widget.physicalDpiX();
int dpiY = widget.physicalDpiY();
qInfo() << dpiX;
qInfo() << dpiY;
Can anyone please guide? What I am trying to achieve is that the Qt application behaves (changes application size/ font size) depending on scaling set in Display Settings of the OS.
I initially suggested using QWindow::devicePixelRatio() in this answer. However, as of Qt 5.12, this does not actually work correctly yet. Qt will avoid fractional scaling ratios due to a bug in Qt's UI scaling implementation. So for 125%, it will still return a 1.0 scaling factor. At 175%, it will return 2.0 instead of 1.75.
So for now, you should fall back to querying the DPI. However, query the logical DPI, not the physical DPI as you are doing now. Replace calls to physicalDpi() functions with calls to logicalDpi() ones. This should give you the standard 96/120/144 DPI reported by Microsoft Windows.
The previous part of the answer below can be used once Qt fixes the bug.
Previous answer, applicable once Qt fixes their scaling bug
Query the scaling ratio directly, don't try to infer it from the DPI. You use QWindow::devicePixelRatio() for this. At 100% scaling, this will return 1.0. At 125% scaling, it will return 1.25. And so on. Since this is a scaling factor, you use it as a multiplier for your sizes.
You should call devicePixelRatio() on the window your widget is currently in. This is because different windows can be on different displays on multi-monitor setups.
The window the widget is in can be obtained with QWidget::windowHandle(). This can return null if the widget is not a window. So you should probably write a small helper function that returns the correct DPR (Device Pixel Ratio) for a widget. It should take a QWidget as argument, and if windowHandle() returns null for the widget, walk up the parent tree, calling windowHandle() on each parent until it finds the first one that doesn't return null. Then return windowHandle()->devicePixelRatio(). This will be the correct DPR to use in that widget.

Can QFontMetrics account for windows dpi scaling?

I was under the impression that if you do this in your application
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication* app = new QApplication(temp, NULL);
then Fonts gets automatically scaled up on high resolution display. Same if you explicitly increase font scaling in Windows 10 (Settings-->System->Custom Scaling).
However, when running the following code with 100% and then 200% scaling in Windows 10, it does not return doubled size.
QFont font = QFont("arial", 10);
QFontMetrics fm(font);
int width = fm.width("abcdefgABCDEFG");
Strangely there is only 1 pixel difference.
100% --> width = 108 pixels
200% --> width = 109 pixels
Why is that? Can I get QFontMetrics to account for Windows scaling? Or do I need to use Logical / Physical DPI to deduce that font size must be increased by a factor 2?
Thanks
For the proper scaling of custom-drawn items use QScreen::physicalDotPerInch property to realize the scaling coefficient to apply to actual drawings:
qreal myScale = pScreen->physicalDotPerInch() / constStandardPerInch;
P.S. The question still needs to be revised.

Retrieve resolution of an uploaded image using ImageResizer

Does ImageResizer.Net for asp.net have any method by which we can know the resolution of any uploaded Image. I know one method:
ImageResizer.ImageBuilder.LoadImageInfo (object source, IEnumerable< string > requestedInfo )
that gives me Height, Width, Mimetype & extension of image file, but I have a requirement where I need to validate the resolution of an uploaded image.
As far as I know dpi is something what connected to devices where images will be rendered.
So, if it is Desktop dpi can be or 72 (MAC) or 96 (Windows), but if you will print it dpi can be 150 or 300.
So to check if image will be correctly printed (with good quality) on paper with size 200x200 milimeters you can calculate min size if image you need in pixels.
So, we have the following input:
- dpi of printing is 150
- size of paper is 200x200 milimeters
200 mm is 7.9 inch
=> min resolution of image should be 7.9*150 = 1185 pixels
So only images with height and width equal or more than 1185 will be printed with good quality.
So question for you - what for you need resolution(dpi) check?
As far as you have Height and Width you can calculate DPI using this formula:
dp = sqrt(width^2 + height^2) (Pythagorean theorem)
then, you should know size of the screen in inches (di). Simply:
dpi = dp / di

Scaling issue with mobile flex app

I have a couple of AS3 games that I want to run in a flex mobile app. I put my original games into a single library and then added it to my mobile app. So far so good.
The problem I get is when the game starts it doesn't scale itself to the StageScaleMode.SHOW_ALL I have specified in the games.
I'm starting the games like this:
var game:MyGame = new MyGame();
var container:UIComponent = new UIComponent();
addElement(container);
container.addChild(game);
this.actionBarVisible = false;
I tried setting the same scale option to the stage in my mxml but it doesn't change anything.
Any ideas?
Thanks.
Mobile device screens have varying screen densities, or DPI (dots per inch). You can specify the DPI value as 160, 240, or 320, depending on the screen density of the target device. When you enable automatic scaling, Flex optimizes the way it displays the application for the screen density of each device.
For example, suppose that you specify the target DPI value as 160 and enable automatic scaling. When you run the application on a device with a DPI value of 320, Flex automatically scales the application by a factor of 2. That is, Flex magnifies everything by 200%.
To specify the target DPI value, set it as the applicationDPI property of the tag or tag in the main application file:
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
firstView="views.HomeView"
applicationDPI="160">
If you choose to not auto-scale your application, you must handle the density changes for your layout manually, as required.
Devices can have different screen sizes or resolutions and different DPI values, or densities.
Resolution is the number of pixels high by the number of pixels wide: that is, the total number of pixels that a device supports.
DPI is the number of dots per square inch: that is, the density of pixels on a device’s screen. The term DPI is used interchangeably with PPI (pixels per inch).
applicationDPI (if setted) specifies the target DPI of the application. Flex automatically applies a scale factor to fit good on another devices with different DPI value.
Capabilities.screenDPI is the specific DPI value of the current device.
runtimeDPI is similar to Capabilities.screenDPI. This value is the current device DPI rounded to one of the constants defined by the DPIClassification class (160, 240 and 320 DPI).
If you want to know the real dimensions (width and height) of a component on the current screens you need to work with the scale factor as:
var scaleFactor:Number = runtimeDPI / applicationDPI;
var currentComponentSize:int =componentSize.height * scaleFactor;
If you haven’t access to applicationDPI and runtimeDPI values, you can calculate the scaleFactor manually using Capabilities.screenDPI as:
// Copy the applicationDPI setted in your application. ie:
var _applicationDPI:int = 160;
var _runtimeDPI:int;
if(Capabilities.screenDPI < 200)
_runtimeDPI = 160;
else if(Capabilities.screenDPI >=200 && Capabilities.screenDPI < 280)
_runtimeDPI = 240
else if (Capabilities.screenDPI >=280)
_runtimeDPI = 320;
var scaleFactor:Number = _runtimeDPI / _applicationDPI;
var currentComponentSize:int =componentSize.height * scaleFactor;
http://www.francescoflorio.info/?p=234

DirectShow: IVMRWindowlessControl::SetVideoPosition stride(?)

I have my own video source and using VMR7. When I use 24 color depth, my graph contains Color Space Converter filter which converts 24 bits to ARGB32. Everything works fine. When I use 32 bit color depth, my image looks desintegrated. In this case my source produces RGB32 images and passes them directly to VMR7 without color conversion. During window sizing I noticed that when destination height is changing the image becomes "integrated" (normal) in some specific value of destination height. I do not know where is the problem. Here are the example photos: http://talbot.szm.com/desintegrated.jpg and http://talbot.szm.com/integrated.jpg
Thank you for your help.
You need to check for a MediaType change in your FillBuffer method.
HRESULT hr = pSample->GetMediaType((AM_MEDIA_TYPE**)&pmt);
if (S_OK == hr)
{
SetMediaType(pmt);
DeleteMediaType(pmt);
}
Depending on your graphic you get different width for your buffer. This means, you connect with an image width of 1000 pixels but with the first sample you get a new width for your buffer. In my example it was 1024px.
Now you have the new image size in the BitmapInfoHeader.biWidth and got the old size in the VideoInfoHeader.rcSource. So one line of your image has a size of 1024 pixels and not 1000 pixels. If you don't remember this you can sometimes get pictures like you.

Resources