[Interest] Confused about QtConcurrent mappedReduced() documentation

Sean Murphy Sean.M.Murphy at us.kbr.com
Fri Jun 3 23:04:55 CEST 2022


I've been playing around with the QtConcurrent module, and I'm struggling to understand one part of the QtConcurrent documentation on this page: https://doc.qt.io/qt-5/qtconcurrentmap.html. Specifically, the section on Concurrent Map-Reduce (https://doc.qt.io/qt-5/qtconcurrentmap.html#concurrent-map-reduce). They have a pseudo code example of taking a bunch of images in, scaling each original image to a 100x100 pixel thumbnail in the mapped function, and then creating a larger collage image made up of all of thumbnails in the reduce function.

What I'm struggling with is: is there any way to initialize the result parameter of the reduce function, before it is initially called? Because I think as they've written their example and/or the way they've defined QtConcurrent::mappedReduced() there's no way to do what their pseudo-example purports to show as cleanly as they describe it.

Here's the example pseudo-code they're provide:
    void addToCollage(QImage &collage, const QImage &thumbnail)
    {
        QPainter p(&collage);
        static QPoint offset = QPoint(0, 0);
        p.drawImage(offset, thumbnail);
        offset += ...;
    }
    QList<QImage> images = ...;
    QFuture<QImage> collage = QtConcurrent::mappedReduced(images, scaled, addToCollage);

The issue I'm seeing is that there doesn't appear to be any way to initialize the "collage" QImage BEFORE the first call to addToCollage(). Instead, it seems like behind the scenes, the mappedReduced() function creates a default constructed QImage, and then passes that to addToCollage(). Then the call to QPainter::drawImage() inside addToCollage() can't actually do anything because the underlying QImage is null. Each successive call to addToCollage() passes the previously "modified" QImage in to be modified further, but since it's still a null QImage, nothing actually happens.

I'm asking this because we're actually attempting to do something almost exactly like their example - we want to make a big image out of a bunch of little image thumbnails, where it takes a fair amount of processing to generate each thumbnail. So ideally before calling mappedReduced() I'd be able to set up the blank QImage with the desired final output size, and then somehow tell mappedReduced to use THAT non-null QImage in the addToCollage() calls, but I don't see a way to do that without a little extra work.

My approach at the moment is I've replaced the addToCollage() function with a lambda function that captures an already initialized QImage, and then in that lambda, I ignore the first parameter, and do the work on the captured image instead. Something like:

    QImage myImage(width, height, QImage:: Format_ARGB32);  // <- create QImage that is the size needed at the end
    std::function<void(QImage &collage, const QImage &thumbnail)> addToCollage = [&myImage](QImage &collage, const QImage &thumbnail) -> void
    {
        Q_UNUSED(collage)         // <- completely ignore the "collage" QImage that is passed in
        QPainter p(&myImage);  // <- operate on myImage instead
        static QPoint offset = QPoint(0, 0);
        p.drawImage(offset, thumbnail);
        offset += ...;
    };
    QList<QImage> images = ...;
    QFuture<QImage> collage = QtConcurrent::mappedReduced(images, scaled, addToCollage);

This works, but I feel like I'm somehow missing the point of the QtConcurrent::mappedReduced() design as it seems to imply that you're going to stumble across a similar issue anytime your reduce function's result type is a type that requires some initialization beyond whatever the default constructor for that type does?

Sean






This e-mail, including any attached files, may contain confidential information, privileged information and/or trade secrets for the sole use of the intended recipient. Any review, use, distribution, or disclosure by others is strictly prohibited. If you are not the intended recipient (or authorized to receive information for the intended recipient), please contact the sender by reply e-mail and delete all copies of this message.


More information about the Interest mailing list