Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 1053229
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 16, 20262026-05-16T17:13:11+00:00 2026-05-16T17:13:11+00:00

I need a very simple function to draw a bunch of lines with anti-aliasing.

  • 0

I need a very simple function to draw a bunch of lines with anti-aliasing. It has to follow Delphi paradigm: self contained and SYSTEM INDEPENDENT (no DLL hell), fast, simple.
Anybody knows such a library?

Until now I have tried:

WuLine
swissdelphicenter.ch/torry/showcode.php?id=1812
I don’t think that the author of this code ever run it. It takes one second to draw a single line! It is obviously only for educational purposes 🙂

Anti aliased drawing from TMetaFile
Link: blog.synopse.info/post/2010/04/02/Antialiased-drawing-from-TMetaFile
Haven’t really tried this yet (I may do it soon). It works only with TMetaFiles. It only loads an EMF file and draw it using anti aliasing functions. Plus, much code on that web site is only demonstrational/educational.

Image32
Very nice library – most complete until now. I might use it but it is overkill for what I need.
Disadvantages:
– The footprint added to application is pretty big.
– Really difficult to use.
– You need to go really deep in its obscure documentation even for simple tasks.
– Demo code provided is way too complex.
– Buggy!
– No recent updates (to fix the bugs)

Anti-Grain Geometry library
The library needs a decent installer. The writers of the library are Linux/Mac users. The Windows implementation looks weird. I cannot say something else about the library itself.

Xiaolin Wu’s based function (by Andreas Rejbrand)
Just see few posts below. Andreas Rejbrand provided a very compact solution. Best solution until now.


It looks like I have to explain why I don’t like large 3rd party libraries and VCL’s:

  • you have to install them
  • large library means large number of bugs which means
  • you have to check for updates (and install them again)
  • when you reinstall Delphi, you have to install them one more time (yes I hate installing VCLs)
  • for VCLs, it means you have to load some extra icons in your already crowded palette.
  • (sometimes) no support
  • LARGE footprint added to your application size
  • large library means (well not always but in most cases) difficult to use – more difficult than you need.
  • (for external DLLs and API) your application becomes system-dependent – really nasty!
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-16T17:13:12+00:00Added an answer on May 16, 2026 at 5:13 pm

    It is not very hard to implement Xiaolin Wu’s anti-aliasing line-rendering algorithm in Delphi. I used the Wikipedia article as a reference when I wrote the following procedure (actually, I just translated the pseudo-code to Delphi and corrected a bug, and added support for a coloured background):

    procedure DrawAntialisedLine(Canvas: TCanvas; const AX1, AY1, AX2, AY2: real; const LineColor: TColor);
    
    var
      swapped: boolean;
    
      procedure plot(const x, y, c: real);
      var
        resclr: TColor;
      begin
        if swapped then
          resclr := Canvas.Pixels[round(y), round(x)]
        else
          resclr := Canvas.Pixels[round(x), round(y)];
        resclr := RGB(round(GetRValue(resclr) * (1-c) + GetRValue(LineColor) * c),
                      round(GetGValue(resclr) * (1-c) + GetGValue(LineColor) * c),
                      round(GetBValue(resclr) * (1-c) + GetBValue(LineColor) * c));
        if swapped then
          Canvas.Pixels[round(y), round(x)] := resclr
        else
          Canvas.Pixels[round(x), round(y)] := resclr;
      end;
    
      function rfrac(const x: real): real; inline;
      begin
        rfrac := 1 - frac(x);
      end;
    
      procedure swap(var a, b: real);
      var
        tmp: real;
      begin
        tmp := a;
        a := b;
        b := tmp;
      end;
    
    var
      x1, x2, y1, y2, dx, dy, gradient, xend, yend, xgap, xpxl1, ypxl1,
      xpxl2, ypxl2, intery: real;
      x: integer;
    
    begin
    
      x1 := AX1;
      x2 := AX2;
      y1 := AY1;
      y2 := AY2;
    
      dx := x2 - x1;
      dy := y2 - y1;
      swapped := abs(dx) < abs(dy);
      if swapped then
      begin
        swap(x1, y1);
        swap(x2, y2);
        swap(dx, dy);
      end;
      if x2 < x1 then
      begin
        swap(x1, x2);
        swap(y1, y2);
      end;
    
      gradient := dy / dx;
    
      xend := round(x1);
      yend := y1 + gradient * (xend - x1);
      xgap := rfrac(x1 + 0.5);
      xpxl1 := xend;
      ypxl1 := floor(yend);
      plot(xpxl1, ypxl1, rfrac(yend) * xgap);
      plot(xpxl1, ypxl1 + 1, frac(yend) * xgap);
      intery := yend + gradient;
    
      xend := round(x2);
      yend := y2 + gradient * (xend - x2);
      xgap := frac(x2 + 0.5);
      xpxl2 := xend;
      ypxl2 := floor(yend);
      plot(xpxl2, ypxl2, rfrac(yend) * xgap);
      plot(xpxl2, ypxl2 + 1, frac(yend) * xgap);
    
      for x := round(xpxl1) + 1 to round(xpxl2) - 1 do
      begin
        plot(x, floor(intery), rfrac(intery));
        plot(x, floor(intery) + 1, frac(intery));
        intery := intery + gradient;
      end;
    
    end;
    

    To use this function, simply provide the canvas to draw to (in a manner rather similar to the Windows GDI functions that require a device context (DC)), and specify the initial and final points on the line. Notice that the code above draws a black line, and that the background has to be white. It is not difficult to generalize this to any situation, not even alpha-transparent drawings. Simply adjust the plot function, in which c \in [0, 1] is the opacity of the pixel at (x, y).

    Example usage:

    Create a new VCL project and add

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Canvas.Brush.Style := bsSolid;
      Canvas.Brush.Color := clWhite;
    end;
    
    procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    begin
      Canvas.FillRect(ClientRect);
      DrawAntialisedLine(Canvas, Width div 2, Height div 2, X, Y, clBlack);
    end;
    

    Click to magnify
    (Magnify)

    OpenGL

    If you need high-performance and high-quality rendering in 2D or 3D, and you do all the drawing yourself, then OpenGL is generally the best choice. It is very easy to write an OpenGL application in Delphi. See http://privat.rejbrand.se/smooth.exe for an example I made in just ten minutes. Use the right mouse button to toggle between filled polygons and outlines, and click and hold the left mouse button to shoot!

    Update

    I just made the code work on a coloured background (for instance, a photograph).

    Click to magnify
    (Magnify)

    Update – The Ultra-Fast Method

    The above code is rather slow because the Bitmap.Pixels property is amazingly slow. When I work with graphics, I always represent a bitmap using a two-dimensional array of colour values, which is much, much, much faster. And when I am done with the image, I convert it to a GDI bitmap. I also have a function that creates a pixmap array from a GDI bitmap.

    I modified the code above to draw on an array instead of a GDI bitmap, and the result is promising:

    • Time required to render 100 lines
    • GDI Bitmap: 2.86 s
    • Pixel array: 0.01 s

    If we let

    type
      TPixmap = array of packed array of RGBQUAD;
    

    and define

    procedure TForm3.DrawAntialisedLineOnPixmap(var Pixmap: TPixmap; const AX1, AY1, AX2, AY2: real; const LineColor: TColor);
    var
      swapped: boolean;
    
      procedure plot(const x, y, c: real);
      var
        resclr: TRGBQuad;
      begin
        if swapped then
        begin
          if (x < 0) or (y < 0) or (x >= ClientWidth) or (y >= ClientHeight) then
            Exit;
          resclr := Pixmap[round(y), round(x)]
        end
        else
        begin
          if (y < 0) or (x < 0) or (y >= ClientWidth) or (x >= ClientHeight) then
            Exit;
          resclr := Pixmap[round(x), round(y)];
        end;
        resclr.rgbRed := round(resclr.rgbRed * (1-c) + GetRValue(LineColor) * c);
        resclr.rgbGreen := round(resclr.rgbGreen * (1-c) + GetGValue(LineColor) * c);
        resclr.rgbBlue := round(resclr.rgbBlue * (1-c) + GetBValue(LineColor) * c);
        if swapped then
          Pixmap[round(y), round(x)] := resclr
        else
          Pixmap[round(x), round(y)] := resclr;
      end;
    
      function rfrac(const x: real): real; inline;
      begin
        rfrac := 1 - frac(x);
      end;
    
      procedure swap(var a, b: real);
      var
        tmp: real;
      begin
        tmp := a;
        a := b;
        b := tmp;
      end;
    
    var
      x1, x2, y1, y2, dx, dy, gradient, xend, yend, xgap, xpxl1, ypxl1,
      xpxl2, ypxl2, intery: real;
      x: integer;
    
    begin
    
      x1 := AX1;
      x2 := AX2;
      y1 := AY1;
      y2 := AY2;
    
      dx := x2 - x1;
      dy := y2 - y1;
      swapped := abs(dx) < abs(dy);
      if swapped then
      begin
        swap(x1, y1);
        swap(x2, y2);
        swap(dx, dy);
      end;
      if x2 < x1 then
      begin
        swap(x1, x2);
        swap(y1, y2);
      end;
    
      gradient := dy / dx;
    
      xend := round(x1);
      yend := y1 + gradient * (xend - x1);
      xgap := rfrac(x1 + 0.5);
      xpxl1 := xend;
      ypxl1 := floor(yend);
      plot(xpxl1, ypxl1, rfrac(yend) * xgap);
      plot(xpxl1, ypxl1 + 1, frac(yend) * xgap);
      intery := yend + gradient;
    
      xend := round(x2);
      yend := y2 + gradient * (xend - x2);
      xgap := frac(x2 + 0.5);
      xpxl2 := xend;
      ypxl2 := floor(yend);
      plot(xpxl2, ypxl2, rfrac(yend) * xgap);
      plot(xpxl2, ypxl2 + 1, frac(yend) * xgap);
    
      for x := round(xpxl1) + 1 to round(xpxl2) - 1 do
      begin
        plot(x, floor(intery), rfrac(intery));
        plot(x, floor(intery) + 1, frac(intery));
        intery := intery + gradient;
      end;
    
    end;
    

    and the conversion functions

    var
      pixmap: TPixmap;
    
    procedure TForm3.CanvasToPixmap;
    var
      y: Integer;
      Bitmap: TBitmap;
    begin
    
      Bitmap := TBitmap.Create;
      try
        Bitmap.SetSize(ClientWidth, ClientHeight);
        Bitmap.PixelFormat := pf32bit;
    
        BitBlt(Bitmap.Canvas.Handle, 0, 0, ClientWidth, ClientHeight, Canvas.Handle, 0, 0, SRCCOPY);
    
        SetLength(pixmap, ClientHeight, ClientWidth);
        for y := 0 to ClientHeight - 1 do
          CopyMemory(@(pixmap[y][0]), Bitmap.ScanLine[y], ClientWidth * sizeof(RGBQUAD));
    
      finally
        Bitmap.Free;
      end;
    
    end;
    
    procedure TForm3.PixmapToCanvas;
    var
      y: Integer;
      Bitmap: TBitmap;
    begin
      Bitmap := TBitmap.Create;
    
      try
        Bitmap.PixelFormat := pf32bit;
        Bitmap.SetSize(ClientWidth, ClientHeight);
    
        for y := 0 to Bitmap.Height - 1 do
          CopyMemory(Bitmap.ScanLine[y], @(Pixmap[y][0]), ClientWidth * sizeof(RGBQUAD));
    
        Canvas.Draw(0, 0, Bitmap);
    
      finally
        Bitmap.Free;
      end;
    
    end;
    

    then we can write

    procedure TForm3.FormPaint(Sender: TObject);
    begin
    
      // Get the canvas as a bitmap, and convert this to a pixmap
      CanvasToPixmap;
    
      // Draw on this pixmap (very fast!)
      for i := 0 to 99 do
        DrawAntialisedLineOnPixmap(pixmap, Random(ClientWidth), Random(ClientHeight), Random(ClientWidth), Random(ClientHeight), clRed);
    
      // Convert the pixmap to a bitmap, and draw on the canvas
      PixmapToCanvas;
    
    end;
    

    which will render 100 anti-aliased lines on the form, in less than one hundredth of a second.

    There seems to be a small bug in the code, though, probably in the Canvas -> Pixmap function. But right now I am way too tired to debug (just got home from work).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I need a very simple and clear example of how to create an OCX
I need to be able to merge two (very simple) JavaScript objects at runtime.
I need to do a few very simple URL manipulations in Java. Like get
i have very simple problem. I need to create model, that represent element of
This should be very simple. I have a function f(x) , and I want
I have a very simple animation task for Java. I need to create a
I need to create a php script . The idea is very simple: When
Grrrrrr, trying to implement a very simple tree. It doesn't need to be bidirectional
I need a very quick fix in a mod_rewrite expression for drupal we have
I need a very accurate way to time parts of my program. I could

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.