[SOLVED] Qt 5.4 beta on iOS - low pixmap quality
-
Hi all,
I have a problem with much lower pixmap quality on iOS than on Android. What you see on pictures is the same application, based on QGraphicsView and multiple QGraphicsPixmapItem stacked one on another. All icons (but at most it is visible with round ones) are displayed with lower quality on iOS than they should be.
My application runs on Android 4.0 and iOS 8, its the same code, just compiled for different platform.
I had problem with Qt 5.3.2 on iOS 8 (due to "QtBUG-41458":https://bugreports.qt-project.org/browse/QTBUG-41458 ) so I have compiled Qt 5.4 beta
I think that before iOS 8 and with Qt 5.3.1 this problem has not existed (or I haven't seen it).Is there something specific about iOS 8?
I have also noticed that with current iOS SDK (8.0) and Qt 5.4 beta pixmaps looks also very bad on older iPhones with iOS 6.1Pictures from Android:
!http://electra.neostrada.pl/android1.png(Android 1)!
!http://electra.neostrada.pl/android2.png(Android 2)!Pictures from iOS:
!http://electra.neostrada.pl/ios1.png(iOS 1)!
!http://electra.neostrada.pl/ios2.png(iOS 2)!
Best Regards
Marek -
On iOS are you providing the retina images via "@2x" suffix ??
-
Thanks for answer,
You mean the resolution?... resolution of the pixmap images is the same for Android and iOS.
You mean that for iPads and iPhones with retina display should I provide images with resolution x 2 ?
But... there is something I don't understand, my QGraphicsPixmapItems have boundingRectangle as big as QPixmap resolution. If I load pixmap to QPixmap and then I do setPixmap with bigger pixmaps, objects will be twice as big, right?
Lets take the exmple: Background image - floor plan. IPad or actually QGraphicsView reports that in full screen mode, screen resolution is (lets say 1136x960) I'm creating image with such a dimensions and it fills all the screen.
So how to fit twice as big image in the same screen resolution?Best Regards
Marek -
On retina display doesn't work as you said
There is the logic resolution of the screen, let's say 200x200 for make the example simple. And the Qt app report the logical resolution of 200x200, but in that space the iOS retina display has in reality 400x400 pixels.
The iOS system let you to provide two different images: image.png and image@2x.png.
The image.png is 200x200 pixel and it will cover all the screen in our example.
The image@2x.png is 400x400 and you might think that will occupy more than the screen but it's not true. Because, the physical device has 400x400 pixel and because it exists image.png with 200x200 pixel what it happens is that it will be displayed the image@2x.png into the 200x200 space using all the power of the retina physical device.And here, it comes Qt. Qt follow this standard, and if you create for each file image another with double dimension and the suffix @2x and the screen of the device is a retina display, it will load the @2x image and it will fit automatically into the logic dimension correctly but drawing the 4x pixels that means and incredible more resolution.
That it's the devicePixelRatio documented into the Qt QPixmap and QScreen classes.Finally, the @2x logic is used by Qt also on another platform like Android. That means and even on the android devices with a screen similar to a retina display of iOS that logic works.
-
OK,
I have found this:
@QPixmap::setDevicePixelRatio(qreal scaleFactor)@So If I create pixmap 200x200 and create object QPixmap with setDevicePixelRatio - 2, then QGraphicsPixmapItem with that QPixmap will look like a 100x100 pixmap, right ?
Just one more question:
My QGraphicsPixmapItems are stacked one on another. Lets take an example.
I'm creating background image with twice the resolution, so 2272x1920 and QPixmap ratio 2, so it is displayed as a full screen image. Next I need to put another QGraphicsPixmapItem exactly in the middle of the background image. This second pixmap is a child of the first one, so it has coordinates of parent object, should I position this second image according to screen resolution which would be 568x480 or according to real background image central point - in that case 1136x960 ?Marek
-
Answer to question 1: you are right, it will appear as 100x100 pixel
Answer to question 2: use the logic screen resolution (568x480) and not the real resolution of the QPixmap (1136x960)
As a remark of the question 2: this happens also with QPainter. For example, suppose you create a 2272x1920 QPixmap with pixelRatio to 2 and you want to draw into it using QPainter, then for drawing a circle at center you should specify the x and y at 568x480 and it will appear at the center of the QPixmap as if it would if the QPixmap was 1136x960 with ratio 1.
-
There are the good news.
I'm quite new to iOS ;)
How about this autoloader with suffix @2x.On first connection from my iOS application, my app is sending its screen resolution to the server to get properly scaled pixmaps and it saves it under "Documents/pixmaps"
Next, I have multiple QGraphicsPixmapItems with the same pixmap, so I'm using QPIxmap dictionary, something like this in my Helper class:
@
bool Helper::getPixmap(QString pixmap_code_name,QPixmap *pix) {
if(!Helper::pixDict.contains(pixmap_code_name)) {
if(!this->loadPixmap(pixmap_code_name))
return false;
}
*pix=pixDict[key];
return true;
}
bool Helper::loadPixmap(QString pixmap_code_name) {
QPixmap pixmap;
if(!pixmap.load(QString("%1.png").arg(pixmap_code_name))) {
return false;
}
Helper::pixDict.insert(pixmap_code_name,pixmap);
return true;
}
@
pixDict is simply:
@static QHash<QString,QPixmap> pixDict;@So lets say I need pixmap for window object, and they are saved in Documents/pixmap as "window_pixmap.png" and I'm calling my helper function:
@
Helper::dictToPix("window_pixmap"),&pixmap_for_qgrapics_object);
@If the device has retina display it will load into pixDict image called window_pixmap@x2.png (if available) instead of window_pixmap.png that I have actually requested ?
Marek
-
If you load the QPixmap directly using the .load method, the @2x suffix are not loaded automatically.
The autoloading of @2x images happens only for high-level classes that display images (let's say QLabel for example).But in your case, because you download from an external server the pixmaps, in order to avoid the download of both image.png and image@2x.png for a retina device and also to get more flexible with new coming device I suggest the following strategy:
- you send to the server not only the screen resolution but also the device pixel ratio (see QScreen class)
- the server send to the device the proper pixmap considering the device pixel ratio; so in case of 100x100 pixmap for a 2x ratio, it will send a 200x200 pixmap. (there is coming out some android device with 3x pixel ratio)
- in your loadPixmap setup also the correct devicePixelRatio: pixmap.setDevicePixelRatio( deviceRatio)
In this way, you get a flexible mechanism for any devices and you save a lot of network traffic.
-
Thanks man, you have saved me a lot of work.
I will try this out today and will let you know.Cheers
Marek -
Hi,
It works!
Thanks for your help!Just two hints in case anyone reads that
- Use setDevicePixelRatio after loading pixmap to QPixmap
- Update your app layout with size=pixmap.size()/pixelRatio
Cheers
Marek