Poor scaling of pixmap images in iOS using QT5.4

  • Hi, I'm trying to port over an app created using QT that works amazing in Android, but is having scaling difficulty under iOS and the more high resolution displays.

    The Setup
    If you imagine I have some code like this (where device is an object containing device properties such as screen size):
    @ bottom_ad_label = new QLabel();
    bottom_ad_label->setMinimumHeight(device->getScreenHeight() * bottom_ad_height);
    bottom_ad_label->setMaximumHeight(device->getScreenHeight() * bottom_ad_height);
    bottom_ad_label_pixmap = new QPixmap(bottom_ad_label_file);
    bottom_ad_label->setPixmap(bottom_ad_label_pixmap->scaled(bottom_ad_label->width(), bottom_ad_label->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    bottom_ad_label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);@

    The image just comes out nasty on the new Apple devices.

    Possible solutions and things that seem to matter:

    Using ​setDevicePixelRatio:
    I've tried using the "QPixmap::​setDevicePixelRatio(2.0)" method after the loading of the pixmap file, but all that does is shrink the image on screen by half.

    This appears to be essential.
    I noticed that without the "app.setAttribute(Qt::AA_UseHighDpiPixmaps);" in the main.cpp portion, custom icons being used for checkboxes and radio buttons also come out pixelated on Apple displays. With it set they come out fine.

    Since the checkbox icons seem to come out fine, I figured why not try loading the pixmap into a QIcon first and then sizing it and grabbing the pixmap from the icon. This didn't seem to work either, just gave the same blurry images on the labels.

    Am I just missing something obvious that makes this all click together?


    • Erik

  • The solution is to use setDevicePixelRatio(2.0) ... but in the right way :-P
    The QPixmap follow some convention and assumption used on the iOS platform for supporting retina display.
    I'll explain with an example:

    Suppose you have the icon of the label in a .png file called "Label.png" with dimension of 100x100 pixel.
    The iOS platform pretend that you must provide for retina display a file image called "Label@2x.png" with double dimension, 200x200 pixel that it's assumed to by displayed into a 100x100 pixel space using high resolution way.

    So, you need to create a version of your icon with double size and name them with "@2x" suffix, and the load them with QPixmap that use the same rules imposed for iOS platform:

    new QPixmap( "Label@2x.png" );

    There is no need to explicit set the devicePixelRatio because it's done automatically by QPixmap because the file name as "@2x" suffix.

    Try ... and you'll see that magically works :-)

  • Thanks for the assist, Gianluca!

    It did work and here are a couple of hints for anyone else that's looking for some help:

    1. Create the @2x files
    2. Use the @2x files if you are on a device that has a QScreen::devicePixelRatio() >= 2
    3. If you're scaling the QPixmap, don't use the Qt::SmoothTransformation on the QPIxmap::scaled function on devices with a pixelRatio >=2 or it will make things look messy.
    4. You will want to enable SmoothTransformation for devices with pixelRatio < 2 so they look nice

    Thanks again, Gianluca, and I hope this help some other folks!

Log in to reply

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.