Can't get good looking antialiasing on lines [update: Workaround found]



  • Hi!

    I'm drawing some graphs on a QWidget using QPainter. When I enable antialiasing there is an effect more akin to a doubling of line thickness in places, and pixel jumble in other places. IMO it looks worse than no antialiasing - ref. the 4x magnified image below. Text comes out perfectly antialiased, i.e. it looks good and when zooming in you see a complex arrangement of pixels in many shades to give smooth lines with even thickness, unlike my graphs.

    Below is a tiny test program and an example of the output (4x mag.). I'm obviously missing something. Does anyone know what could cause antialiasing to look like that?

    Edit: at the very bottom I added an image with some examples of good antialiasing done by Qt, using setRenderHint( QPainter::Antialiasing ), just like I am trying to do.

    I'm using Qt 5.0.2 + MSVC2012 + Win7 64bit.

    @
    #include <QtGui>
    #include <QApplication>
    #include <QWidget>

    class AATester : public QWidget
    {
    public:
    AATester( QWidget *parent = 0 ) : QWidget( parent ) {}
    protected:
    void paintEvent( QPaintEvent *e )
    {
    QPainter p(this);
    p.setPen( Qt::blue );
    p.setRenderHint( QPainter::Antialiasing );
    QPolygon polyline;
    for( int x = 0; x < width(); x++ )
    {
    float y = sin( x * 6.28f / width() ) * height() / 2;
    polyline << QPoint( x, height() / 2 + (int) y );
    }
    p.drawPolyline( polyline );
    }
    };

    int main( int argc, char *argv[] )
    {
    QApplication app( argc, argv );

    AATester *a = new AATester();
    a->show();

    return app.exec();
    }
    @

    !http://i183.photobucket.com/albums/x152/aleistad/Private/QT_Antialiasing_zps254c3600.png!

    !http://i183.photobucket.com/albums/x152/aleistad/Private/QT_Antialiasing_good_zpsa44ec462.png!



  • "Anti-aliasing":http://www.wikipedia.org/wiki/Spatial_anti-aliasing looks like that because that is what it does to visually smooth the jaggies. Shaded pixels will be added by anti-aliasing horizontal/vertical lines that fall on pixel boundaries, lines that cross the area diagonally, etc.
    If you do not want Qt to do this then tell it not to.

    Looking at the image zoomed 4x will show this shading but this is not the same thing as drawing the image a 4x the size.



  • Chris, did you actually read my posting? I'm talking about AA quality...

    I do indeed want antialiasing, and I'm fully aware of what it is, how it's generally done and how it's supposed to look. Now, if you look at those images; the top one with a light grey background looks terrible as AA go (the result I'm getting), while the bottom one looks perfectly fine (the results someone else is getting). The images are magnified to show the readers clearly what is happening.



  • Bump!

    In case Chris' answer wrongly relegated the question to the "Qt and/or antialiasing not even for dummies" bin...



  • Yes, I read your posting. No, there's nothing you can do to simultaneously have anti-aliasing and not have anti-aliasing effects. That's what you are asking for.

    Depending on application you can avoid drawing in a fashion to invokes the worst-case line broadening. For example, draw verticals/horizontal lines only with integer width pens, and only on logical pixel coordinates that do not cause the pen to straddle pixels. See http://qt-project.org/doc/qt-5.0/qtgui/coordsys.html for how lines are mapped to pixels. This is not viable in the general case and obviously not useful for sloping lines.

    In your graphing example the problem is probably exacerbated by a multitude of overlapping, very short line segments.

    If you wish to implement your own line drawing algorithm that anti-aliases with a different intensity/algorithm that's entirely possible.



  • Of course I'm not asking for simultaneously having antialiasing and no antialiasing. That wouldn't make sense.

    What I am asking for is help in identifying why the antialiasing turned out like it did. The problem turns out to be exactly that drawPolyline doesn't handle antialiasing well if it's composed of short segments. That means there's no built in way of having arbitrary shaped curves antialiased, and I will have to look at other solutions, or simply forego antialiasing for this round (time is a factor).



  • (Antialiased) line drawing in Qt has been badly broken since 4.8, so maybe try compiling your code with 4.7.4 and it will work. Unfortunately, It doesn't seem like the line drawing will ever be fixed, because all concentrate on QML/QtQuick for smartphone apps.

    For reference, see my and others' bug reports here:
    https://bugreports.qt-project.org/browse/QTBUG-26013
    https://bugreports.qt-project.org/browse/QTBUG-25896
    https://bugreports.qt-project.org/browse/QTBUG-23430

    The first bug report was closed as "done" in the meanwhile, although it should have the status "will not fix". It's not fixed, and the official Qt comment is to keep using Qt 4.7.4 (see second bug report).



  • Aha! Thank you very much, DerManu!

    The first bug report, by yourself:
    https://bugreports.qt-project.org/browse/QTBUG-26013
    mentions the workaround:
    "Does not happen when discretizing the line data before passing it to the painter, i.e. passing a QLineF().toLine() instead of a QLineF() (This is not a valid workaround when you want to draw antialiased, because you lose floating point precision of start/end points)"

    Taking this on board, I experimented with various constellations of QLineF, QPointF, QPolygon, QPolygonF, .toLine() and .toPoint(), and found that the "secret" generally lies in keeping things in the floating point domain. So changing the example drawing code above to the exact example shown below (using QPolygonF and QPointF), I got nicely antialiased arbitrary shaped lines as show in the image below, even with line segment lengths of 1 pixel :-)

    I would have thought that both antialiased and straight up line drawing is fundamental, even on smartphones (I know nothing about the mobile platforms/apps though). Oh well... I can live with the workaround for now; all I have to do is keep some rounding errors in check.

    @
    void AATester::paintEvent( QPaintEvent *e )
    {
    QPainter p(this);
    p.setPen( Qt::blue );
    p.setRenderHint( QPainter::Antialiasing );
    QPolygonF polyline;
    int h_div_2 = height() / 2;
    for( int x = 0; x < width(); x++)
    {
    float y = h_div_2 + sin( x * 6.28f / width() ) * h_div_2;
    polyline << QPointF( x, y );
    }
    p.drawPolyline( polyline );
    }
    @

    !http://i183.photobucket.com/albums/x152/aleistad/Private/QT_Antialiasing_float_zpsa9511843.png!


Log in to reply
 

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