Search code examples
qtblurmotion-blur

Qt motion (linear) blur


Is there simple solution to add motion blur to an image in Qt? Haven't found any good tutorial about blur. I need something really simple, that I could understand, and would really good if I could change blur angles.


Solution

  • Qt hasn't a motion blur filter. I looked at the code of QGraphicsBlurEffect; it uses QPixmapBlurEffect which itself uses an internal helper method called expblur (exponential blur).

    expblur itself uses a one-dimensional blur effect (motion blur in X direction, method qt_blurrow) twice. It rotates the image between the two blurs by 90 degrees and afterwards rotates it back.

    So actually, Qt has a motion blur effect but this is internal only. So you need to write your own effect. To do so, have a look at the code of qt_blurrrow, which you can find in the Qt sources at src/gui/qpixmapfilter.cpp. This will give you a good quality for the filter, since it is an exponential blur filter instead of a linear one.

    If you don't want to go so deep into the Qt source code, take this pseudo-code as a start:

    foreach pixel (x, y) in image {
        for dx = -r to r with x+dx within image {
            for dy = -r to r with y+dy within image {
                Add pixel (x+dx, y+dy) of the source image with ↩
                factor (matrix[dx, dy]) to the target image.
            }
        }
    }
    

    where matrix might be defined like this (for horizontal motion blur with radius 2):

    0   0   0   0   0
    0   0   0   0   0
    0.1 0.2 0.4 0.2 0.1
    0   0   0   0   0
    0   0   0   0   0
    

    Notice that the sum of all entries has to be 1, or you have to divide the colors by the sum of the matrix entries.

    Building this matrix for a given radius r and angle α is difficult when you want to allow arbitrary angles for α (not only 90 degrees steps). [EDIT: See comment 3 for an easy generation of such a matrix.]