⚠️ Forum Maintenance: Feb 6th, 8am - 14pm (UTC+2)

Copy QImage to QLabel pixmap inside QScrollArea WITHOUT smooth

  • Hello people and thank you for reading.
    Although the topic might sound easy like a question asked hundreds of times that are usually answered by "just do sth like"
    @ setPixmap(QPixmap::fromImage(img).scaled(dest->width(), dest->height(), Qt::KeepAspectRatio, Qt::FastTransformation)) @
    this is more complicated i think.

    As my project is quiet big and has many dependencies I created a quick video that shows the actual situation which is 95% of what i want to do instead of uploading it.
    "Project_Video":https://www.dropbox.com/s/6q15bm3pw1pi3do/video_qt_problem.mp4 (1MB, 67 seconds)

    The point is:
    I DO NOT want the big left image to be smoothed when zoomed as for image-processing pixels is what i want to see.
    The right zoom-window is of type QLabel and the big left is of type ImageLabel which inherits QLabel.
    Even when I create also the big left Widget of type QLabel i get the same problem as long as it is put inside of a QScrollArea. When the widget is placed outside the QScrollArea this problem disappears no matter if its a QLabel or ImageLabel.

    The strange thing I dont understand is: Where does the smooth come from and: How can i avoid it?

    One thing that can be seen in the video I want to mention:
    I want the QScrollArea to work on a bigger area than the ImageLabel. This is because I want the pink box in the middle of the QScrollArea to be able to reach the corners of the Image.
    To achieve this I added margins around the ImageLabel that change their size on every imageload depending on the imagesize.

    This brought me to code like this:
    if (marginForSelection)
    getImageDisplay()->m_leftRightMargin = (getScrollArea()->width() - 60) / 2; // TODO: Achtung: 60 ist der CSS hinterlegten Style-Sheet info in vs.ui. Muss dynamisch werden (Auflösungsunabhängig)
    getImageDisplay()->m_topBottomMargin = (getScrollArea()->height() - 60) / 2;
    getImageDisplay()->m_leftRightMargin = 0;
    getImageDisplay()->m_topBottomMargin = 0;
    QString leftRightHalf = QString::number(getImageDisplay()->m_leftRightMargin);
    QString topBottomHalf = QString::number(getImageDisplay()->m_topBottomMargin);
    getImageDisplay()->setStyleSheet("padding-left: " + leftRightHalf + "px; padding-right: " + leftRightHalf + "px; padding-top: " + topBottomHalf + "px; padding-bottom: " + topBottomHalf + "px;");

    QTHelper::putImage(mat, getImageDisplay(), false);


    while QTHelper::putImage is taken from here:
    void putImage(const cv::Mat& src, QLabel* dest, bool resizeAndAspect)
    // 8-bits unsigned, NO. OF CHANNELS=1
    QVector<QRgb> colorTable;
    for (int i=0; i<256; i++)
    const uchar qImageBuffer = (const uchar)src.data;
    QImage img(qImageBuffer, src.cols, src.rows, src.step, QImage::Format_Indexed8);
    if (resizeAndAspect)
    dest->setPixmap(QPixmap::fromImage(img).scaled(dest->width(), dest->height(), Qt::KeepAspectRatio, Qt::FastTransformation));
    dest->setPixmap(QPixmap::fromImage(img).scaled(img.width(), img.height(), Qt::KeepAspectRatio, Qt::FastTransformation));

    I'm using this putImage also for the small right image which is non-smoothed as I want it to:
    void BildDisplay::updatePreview()
    if (!_preview)

    cv::Rect selectionArea = getAbsoluteImageCoordinatesOfBoxRoi();
    _previewImage = cv::Mat(_displayImage, selectionArea);
    QTHelper::putImage(_previewImage, _preview, true);


    For zooming I took the examplecode form here but added my margin-stuff:
    "QT5.2 ImageViewer Example":http://qt-project.org/doc/qt-5/qtwidgets-widgets-imageviewer-example.html
    void BildDisplay::scaleImage(double factor)
    if (!getImageDisplay()->pixmap())
    getImageDisplay()->m_scaleFactor *= factor;

    getImageDisplay()->resize(getImageDisplay()->m_scaleFactor * getImageDisplay()->pixmap()->width() + 2 * getImageDisplay()->m_leftRightMargin,
                              getImageDisplay()->m_scaleFactor * getImageDisplay()->pixmap()->height() + 2 * getImageDisplay()->m_topBottomMargin);
    adjustScrollBar(getScrollArea()->horizontalScrollBar(), factor);
    adjustScrollBar(getScrollArea()->verticalScrollBar(), factor);
    ui->groesser->setEnabled(getImageDisplay()->m_scaleFactor < _maxZoom);
    ui->kleiner->setEnabled(getImageDisplay()->m_scaleFactor > _minZoom);


    I already tried overriding the
    @ void ImageLabel::paintEvent(QPaintEvent *ev) @
    which I maybe did wrong and should be the solution?
    I know that a QPainter is able to put the pixmap non-smoothed with
    @ painter.setRenderHint(QPainter::SmoothPixmapTransform, false); @
    but when not calling
    @ QLabel::paintEvent(ev); @
    inside paintEvent I am not able to respect the margins and stylesheets correctly.
    Is this the right approach?
    I took a look at the source of QLabel.cpp which uses a lot of
    QRect cr = contentsRect();
    cr.adjust(d->margin, d->margin, -d->margin, -d->margin);
    which I cant use because I cant access QLabelPrivate.
    The interesting point is that i saw that QLabel.cpp does
    @ d->scaledpixmap = new QPixmap(QPixmap::fromImage(d->cachedimage->scaled(cr.size(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation))); @
    which I dont want to happen because of the smooth!

    As every hardware the project runs on supports OpenGL4 I'm also willing to switch my approach completly and use QOpenGLPaintDevice instead of inheriting from QLabel if that helps.

    Should I provide other parts of the project-code?
    Ubuntu 13.10 QT 5.2.1 QTCreator 3.1.0 GCC 4.8.1 OpenCV 2.4.8
    Thanks for any help!

Log in to reply