 Mirror

Draw a filled circle using ScanLine (Views: 100)

 Problem/Question/Abstract:I am looking for some code to draw a filled circle on a bitmap or change colors of pixels within a circle on it, using Bitmap.Scanline. Any suggestions or ideas on how to do this, the edges need to be perfect and it has to be fast.Answer:Perfect edges mean you will have to work with an alpha channel and do anti-aliasing. This means, that you either have to use a 32-bit bitmap (see e.g. Graphics32) or you have to first draw the background image in the bitmap and directly blend it when rendering the circle. Next question: do you want to use integer precision or floating point precision for the circle properties like center point and diameter? If you use integer, you only have to draw 1/8 of the circle and the rest can be copied/mirrored/flipped around. Assuming floating point, and a grayscale bitmap, here's an approach:CX, CY: center of circle (single)R: radius of circle (single)F: feather size (the number of pixels used as blend area, usually 1 pix) (single)Determine bounds in Y (integers):LX := floor(CX - R - F * 0.5);RX := ceil(CX + R + F * 0.5);LY := floor(CY - R - F * 0.5);RY := ceil(CY + R + F * 0.5);Determine some helpful values (singles)RPF2 = sqr(R + F/2);RMF2 = sqr(R - F/2);{ ... }var  P: PByteArray  sqdist: single;  { ... }    {Loop through Y values}    {for y := LY to RY do begin -> not very safe}  for y := max(LY, 0) to Min(RY, Bitmap.Height - 1) do    P := Bitmap.Scanline[y];  {Loop through X values}  for x := Max(LX, 0) to Min(RX, Bitmap.Width - 1) do  begin    {Determine squared distance from center for this pixel}    sqdist := sqr(y - CY) + sqr(x - CX); {Or use hypot() function}    {Inside outer circle?}    if sqdist < RPF2 then    begin      {Inside inner circle?}      if sqdist < RMF1 then        {Inside the inner circle.. just give the scanline the new color}        P[x] := 255      else      begin        {We are inbetween the inner and outer bound, now mix the color}        Fact := Max(0, Min(255, round(((R - sqrt(sqdist)) * 2 / F) * 128 + 128)));        P[x] := (255 - Fact) * P[x] + Fact;      end;    end;    { ... }This algorithm is optimized a bit but could be made faster probably. Untested!

<< Back to main page