Home > Mobile >  Why does increasing the devicePixelRatio decrease the size of my QImage?
Why does increasing the devicePixelRatio decrease the size of my QImage?

Time:10-03

The devicePixelRatio is used to translate the device independent pixels into the actual physical pixels on the device. Therefore taking the example from the enter image description here

CodePudding user response:

This is very logical but a bit complicated at the first sight from the library users' perspective. And very complicated considering all implementation details in Qt library. But you do not need to care about most of the details, fortunately.

With widgets it is easy: you specify the logical size and the physical size on screen is derived from the logical size multiplied by the application DPR.

widget_physical_size_on_screen = widget_logical_size * application_dpr

But with images (and also icons and pixmaps) you need to distinguish between the image physical resolution and the physical size on screen. They can differ. And you also need to distinguish between the application DPR and the image DPR. They can also differ. The final physical size on screen is calculated using logical size as an intermediary step.

So with images you first specify the physical resolution in the constructor QImage(width, height), the parameters width and height represent physical pixels of your image resolution. Then you can specify image DPR (as you did in your code). Then your image logical pixel size is derived from its physical resolution by dividing with the image DPR. And when the image is displayed in application, it is then resized to physical size by multiplying with the application DPR (not the image DPR).

image_logical_size = physical_image_resolution / image_dpr
image_physical_size_on_screen = image_logical_size * application_dpr

Therefore if you display image with physical resolution 600x400 with image DPR 2 (then it has logical size 300x200) in application which has DPR 1, then it will have physical size 300x200 pixels, because in application with DPR 1, one logical pixel translates to one physical pixel on screen. This is exactly what hapenned in your case - increasing DPR to 2 leads to smaller image on screen because your application still has DPR 1. E.g. image with resolution 600x400 with image DPR 2 appears as 300x200 on screen.

If you display the same image in application with application DPR 2, then the image will have 600x400 physical pixels. Because in application with DPR 2, one logical pixel translates to 2 physical pixels. I.e. your image will have its original size if and only if your application has the same DPR as is the image DPR.

If you display this image in application with DPR 3 (e.g. if you have really large 8k HighDPI display), then the image will have 900x600 physical pixels. And it will scale up badly (if you get a closer look on your fancy 8k display, the image will be slightly pixelated) because the original image does not have such a big resolution.

Actually setting DPR for images is not strictly needed, you can leave it with default value, which is DPR 1. But then you will need to do some more size recalculations and image resizings yourself. So if you want image with logical pixel size 300x200 then for application with DPR 1 you would need to create image with resolution 300x200, for application with DPR 2 you would need image with resolution 600x400 etc. Otherwise if you display image with physical resolution 300x200 and DPR 1 (i.e. it has logical size 300x200) in application with DPR 2, the image will be scaled-up to physical size 600x400 but it will be pixelated because the actual physical resolution of the image is still just 300x200.

So keeping images with DPR 1 can actually save some memory in some cases since you will allocate smaller images, only as big as you really need. But the drawback is doing more calculations in code yourself. It may be tempting to do these calculations yourself at the first sight. But I should warn you, in the text above I left out one important detail. In general case there is not a single application-wide DPR. In multiscreen set up the application can occupy more screens, each with different DPR. So it is not the application which specifies the DPR but DPR is specified for each widget individually. And widgets can move from screen to screen if you move your window and hence their DPR can change. And believe, then you do not want to recalculate the size of your images yourself in your code.

But if you are 100 % sure you do not want to support multiscreen mixed DPR scenario, then you can leave your images with DPR 1 (the default) and resize your images yourself. It can save you save memory and processing power in some cases because you can avoid allocating unneccessarily big images and avoid scaling down if the big resoltion is not needed. But I would probably not recommend going this way.

And one last very important note: always test your application in low-DPI scenarion with DPR == 1 and high-DPI scenario with DPR = 2. And ideally test your application also with fractional DPR, i.e. when DPR is a floating point number such as 1.25 or 1.5. Your application should work well in all these cases. If not, then fix it.

  • Related