title: Canvas Drawing - How can I Improve this Alpha Drawing routine?
body: <p><strong>I am drawing onto a canvas with Opacity (Alpha Transparency) abilities like so:</strong></p>
  
  <pre><code>var
    Form1: TForm1;
  
    IsDrawing: Boolean;
  
  implementation
  
  {$R *.dfm}
  
  procedure DrawOpacityBrush(ACanvas: TCanvas; X, Y: Integer; AColor: TColor; ASize: Integer; Opacity: Byte);
  var
    Bmp: TBitmap;
    I, J: Integer;
    Pixels: PRGBQuad;
    ColorRgb: Integer;
    ColorR, ColorG, ColorB: Byte;
  begin
    Bmp := TBitmap.Create;
    try
      Bmp.PixelFormat := pf32Bit; // needed for an alpha channel
      Bmp.SetSize(ASize, ASize);
  
      with Bmp.Canvas do
      begin
        Brush.Color := clFuchsia; // background color to mask out
        ColorRgb := ColorToRGB(Brush.Color);
        FillRect(Rect(0, 0, ASize, ASize));
        Pen.Color := AColor;
        Pen.Style := psSolid;
        Pen.Width := ASize;
        MoveTo(ASize div 2, ASize div 2);
        LineTo(ASize div 2, ASize div 2);
      end;
  
      ColorR := GetRValue(ColorRgb);
      ColorG := GetGValue(ColorRgb);
      ColorB := GetBValue(ColorRgb);
  
      for I := 0 to Bmp.Height-1 do
      begin
        Pixels := PRGBQuad(Bmp.ScanLine[I]);
        for J := 0 to Bmp.Width-1 do
        begin
          with Pixels^ do
          begin
            if (rgbRed = ColorR) and (rgbGreen = ColorG) and (rgbBlue = ColorB) then
              rgbReserved := 0
            else
              rgbReserved := Opacity;
            // must pre-multiply the pixel with its alpha channel before drawing
            rgbRed := (rgbRed * rgbReserved) div $FF;
            rgbGreen := (rgbGreen * rgbReserved) div $FF;
            rgbBlue := (rgbBlue * rgbReserved) div $FF;
          end;
          Inc(Pixels);
        end;
      end;
  
      ACanvas.Draw(X, Y, Bmp, 255);
    finally
      Bmp.Free;
    end;
  end;
  
  procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
  begin
    case Button of
      mbLeft:
      begin
        IsDrawing := True;
        DrawOpacityBrush(Form1.Canvas, X, Y, clRed, 50, 85);
      end;
    end;
  end;
  
  procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
    Y: Integer);
  begin
    if (GetAsyncKeyState(VK_LBUTTON) &lt;&gt; 0) and
       (IsDrawing) then
    begin
      DrawOpacityBrush(Form1.Canvas, X, Y, clRed, 50, 85);
    end;
  end;
  
  procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
  begin
    IsDrawing := False;
  end;
  </code></pre>
  
  <p>The draw <code>DrawOpacityBrush()</code> procedure was an update by Remy Lebeau on a previous question I recently asked: <a href="https://stackoverflow.com/questions/10342603/how-to-paint-on-a-canvas-with-transparency-and-opacity/10343272#10343272">How to paint on a Canvas with Transparency and Opacity?</a></p>
  
  <p>While this works, the results are not satisfactory to what I now need.</p>
  
  <p>Currently, every time the <code>DrawOpacityBrush()</code> procedure is called in MouseMove it keeps on drawing the brush ellipse shape. This is bad because depending on how quick you move the mouse around the canvas, the output is not as hoped.</p>
  
  <p>These sample images should illustrate this better hopefully:</p>
  
  <p><img src="https://i.stack.imgur.com/RBmp9.png" alt="enter image description here"></p>
  
  <p><strong>-</strong> The first red brush I moved the mouse pretty rapidly from the bottom of the canvas to the top.<br>
  <strong>-</strong> The second red brush I moved a lot slower.</p>
  
  <p>As you can see the opacity is drawn correctly, except that the circle keeps on drawing repeatedly as well.</p>
  
  <p><strong>What I would like it to do instead is:</strong></p>
  
  <p><strong>(1)</strong> Paint with a opacity line around the ellipse.</p>
  
  <p><strong>(2)</strong> Have an option to prevent any ellipses been drawn at all.</p>
  
  <p>This mock sample image should give an idea of how I would like it to be drawn:</p>
  
  <p><img src="https://i.stack.imgur.com/DCZf0.png" alt="enter image description here"></p>
  
  <p>The 3 purple brush lines demonstrate <strong>option (1)</strong>.</p>
  
  <p>To achieve <strong>option (2)</strong> the circles inside the brush lines should not be there.</p>
  
  <p>This should then allow you to take time when drawing, not frantically moving the mouse around the canvas in hope of getting the result you need. Only when you decide to go back over the brush stroke you just made will the opacity for that area become darker etc.</p>
  
  <p><strong>How can I achieve these type of drawing effects?</strong></p>
  
  <p>I would like to be able to draw onto a TImage as that is what I am currently doing, so passing TCanvas as a parameter in a function or procedure would be ideal. I will also be using the MouseDown, MouseMove and and MouseUp events for my drawing.</p>
  
  <p><strong>This is the output I get using the method provided by NGLN:</strong></p>
  
  <p><img src="https://i.stack.imgur.com/Io38l.png" alt="enter image description here"></p>
  
  <p>Opacity seems to be applied to the image too, it should only be the poly lines.</p>