Search code examples
arraysvb.netbitmapellipselockbits

How to use DrawEllipse in a LockBits array (How to generate a set of pixels that forms an ellipse)


I'm using this class to fill pixels of a bitmap based on the LockBits function:

Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices.Marshal

Public Class Fill

    Public Shared Function Process(ByVal b As Bitmap) As Bitmap

    Dim bmd As BitmapData = _
    b.LockBits(New Rectangle(0, 0, b.Width, b.Height), _
    System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)

    Dim scan0 As IntPtr = bmd.Scan0
    Dim stride As Integer = bmd.Stride

    ' Here's the speedier method.
    ' define an array to store each pixels color as an int32 
    Dim pixels(b.Width * b.Height - 1) As Integer

    ' this is system.runtime.interopservices.marshall.copy
    Copy(scan0, pixels, 0, pixels.Length)

    ' loop through all pixels and fill

    For i As Integer = 0 To pixels.Length - 1
        pixels(i) = Color.Red.ToArgb
    Next

    ' Copy the data back from the array to the locked memory
    Copy(pixels, 0, scan0, pixels.Length)

    ' finally we unlock the bits. 
    b.UnlockBits(bmd)
    Return b
    End Function
End Class

Now, instead of filling all the pixels, I need to fill an ellipse (actually it's going to be many ellipses, that's why I use LockBits), so I googled for a way to draw an ellipse pixel by pixel using some kind of formula, but I didn't find much help, also I'm not good with this math stuff. So, my question is: how to create an array of pixels that forms a filled ellipse? thank you

.

supplement (feel free to ignore):

I'll explain exactly what I'm trying to do, so it might help you understand my situation.. Actually, I'm working on a function that's supposed to generate filled ellipses with random width & height (in specific range) on a specific area of a bitmap, while the filled pixels must have a percentage of the total number of pixels in that area, that's why I need to draw the ellipse pixel by pixel (or using an array of pixels) to keep track of the number of filled pixels.


Solution

  • The formula for all the points inside an ellipse is:

    (x - h) * (x - h) / a * a + (y - k) * (y - k) / b * b <= 1

    where
    x,y are the coordinates of any point on the ellipse,
    a, b are the radius on the x and y axes respectively and
    h,k the coordinates of the center

    So the code:

    Dim h, k, a, b, x, y As Integer
    Dim res As Double
    
    'arbitrary values of ellipse
    h = 200
    k = 200
    a = 80
    b = 60
    
    For x = h - a To h + a
        For y = k - b To k + b
            res = CDbl((x - h) * (x - h)) / CDbl(a * a) + CDbl((y - k) * (y - k)) / CDbl(b * b)
    
            If res <= 1.0 Then
                'the point (x, y) is inside
            End If
    
        Next
    Next