Antialiased Lines

Type : A slow, ugly, and unoptimized but short method to perform antialiased lines in a framebuffer
References : Posted by arguru[AT]smartelectronix[DOT]com
Notes :
Simple code to perform antialiased lines in a 32-bit RGBA (1 byte/component) framebuffer.

pframebuffer <- unsigned char* to framebuffer bytes (important: Y flipped line order! [like in the way Win32 CreateDIBSection works...])

client_height=framebuffer height in lines
client_width=framebuffer width in pixels (not in bytes)

This doesnt perform any clip checl so it fails if coordinates are set out of bounds.

sorry for the engrish


Code :
//
// By Arguru
//
void PutTransPixel(int const x,int const y,UCHAR const r,UCHAR const g,UCHAR const b,UCHAR const a)
{
    unsigned char* ppix=pframebuffer+(x+(client_height-(y+1))*client_width)*4;
    ppix[0]=((a*b)+(255-a)*ppix[0])/256;
    ppix[1]=((a*g)+(255-a)*ppix[1])/256;
    ppix[2]=((a*r)+(255-a)*ppix[2])/256;
}

void LineAntialiased(int const x1,int const y1,int const x2,int const y2,UCHAR const r,UCHAR const g,UCHAR const b)
{
    // some useful constants first
    double const dw=x2-x1;
    double const dh=y2-y1;
    double const slx=dh/dw;
    double const sly=dw/dh;

    // determine wichever raster scanning behaviour to use
    if(fabs(slx)<1.0)
    {
        // x scan
        int tx1=x1;
        int tx2=x2;
        double raster=y1;

        if(x1>x2)
        {
            tx1=x2;
            tx2=x1;
            raster=y2;
        }

        for(int x=tx1;x<=tx2;x++)
        {
            int const ri=int(raster);

            double const in_y0=1.0-(raster-ri);
            double const in_y1=1.0-(ri+1-raster);

            PutTransPixel(x,ri+0,r,g,b,in_y0*255.0);
            PutTransPixel(x,ri+1,r,g,b,in_y1*255.0);

            raster+=slx;
        }
    }
    else
    {
        // y scan
        int ty1=y1;
        int ty2=y2;
        double raster=x1;

        if(y1>y2)
        {
            ty1=y2;
            ty2=y1;
            raster=x2;
        }

        for(int y=ty1;y<=ty2;y++)
        {
            int const ri=int(raster);

            double const in_x0=1.0-(raster-ri);
            double const in_x1=1.0-(ri+1-raster);

            PutTransPixel(ri+0,y,r,g,b,in_x0*255.0);
            PutTransPixel(ri+1,y,r,g,b,in_x1*255.0);

            raster+=sly;
        }
    }
}

Comments
from : Gog
comment : Sorry, but what does this have to do with music DSP ??

from : pav_101[AT]hotmail[DOT]com
comment : well, for drawing envelopes, waveforms, etc on screen in your DSP app....

from : Gog
comment : But... there are TONS of graphic toolkits to do just that. No reason to "roll your own". One f.i. is GDI+ (works darn well to be honest), or if you want non-M$ (and better!) go with AGG at (http://www.antigrain.com). And there are even open-source cross-platform toolkits (if you want to do Unix and Mac without coding). Graphics and GUIs is a very time-consuming task to do from scratch, therefore I think using libraries such as the above is the way to go, liberating energy to do the DSP stuff... ;-)

from : Rich
comment : I don't want a toolkit, I want antialiased line drawing and nothing more. Everything else is fine.

from : Justin
comment : Anyone know how to get the pointer to the framebuffer? Perhaps there is a different answer for different platforms?

from : daniel[DOT]schaack [ at ] basementarts[DOT]de
comment : you can also draw everything in a 2x (vertically and horizontally) higher resolution and then reduce the size again by always taking the average of 4 pixels. that works well.

from : aliloko[AT]gmail[DOT]com
comment : I think it can be useful to those designing graphical synths. But the Wu line algorithm is considerably more fast and works only with integers. http://en.wikipedia.org/wiki/Xiaolin_Wu's_line_algorith