?
Solved

Getting shape coordinates.

Posted on 2010-09-06
8
Medium Priority
?
475 Views
Last Modified: 2012-05-10
Hi, I have a problem:

I have an image of a square (for example). I want to get the coordinates of the square into an array of points.
A bit like a shape created by a “join the dots” kind of thing.

How the hell do I do this?

I’ve thought of scanning pixel by pixel across the image but this doesn’t give me a point to point array.

The purpose of this is I’ve built an application you can add shapes to on the form.
So I want to be able to draw the shapes in ms paint, then get the coordinates and import them into my application at runtime.
Just solid shapes are all I need.
0
Comment
Question by:Kinger247
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
8 Comments
 
LVL 10

Author Comment

by:Kinger247
ID: 33611532
Ok, typical I ponder over something for hours then post something on here, then a quick visit to the loo and I Ive found how to do it !!!

I'll post the code after :)
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 33617663
Were you talking about creating polygons?  
0
 
LVL 12

Expert Comment

by:omegaomega
ID: 33621551
Or possibly something more scatological?  ;-)

The coordinates of a square are pretty simple, so I suspect this is just an illustration of more complex shapes that you might need to deal with.  Is the GraphicsPath.PathPoints of any possible use to you?

Cheers,
Randy
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 10

Author Comment

by:Kinger247
ID: 33625392
Ok, this is what I cam up with.

If you create a black outline of an image in ms paint, like a square or one of the predefined shapes like star etc.
It'll recreate the image in a point to point array.

Might be a better way of doing it but this is my quick solution.
Pretty fast too.
Public Class Form1
  Public oMapImage As New MapImage
  Private oPoints() As Point = Nothing

  Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim Background As New Bitmap("C:\Data\Development Tests\Get Image Regions\Image1.bmp")
    oPoints = oMapImage.Map(Background)
  End Sub

  Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    If oPoints Is Nothing Then Exit Sub

    Using gr As Graphics = e.Graphics
      gr.Clear(Color.White)
      gr.DrawLines(Pens.Black, oPoints)
    End Using
  End Sub
End Class

Public Class MapImage
  Private oPoints() As Point = Nothing

  Public Function Map(ByVal Background As Bitmap) As Point()
    Dim MatrixStart As Point = Nothing
    Dim MatrixCentre As New Point(-1, -1)
    Dim PreviousPoint As Point = Nothing
    Dim Finished As Boolean = False
    Dim Y As Integer = 0
    Dim X As Integer = 0
    Dim FirstWhiteCell As Boolean = False
    Dim iPosToCheck As Integer = 1
    Dim BackgroundColor As Color = Background.GetPixel(0, 0)

    '//-- Get first black pixel - scan pixels left to right / top to bottom
    For Y = 0 To Background.Width - 1
      For X = 0 To Background.Height - 1
        If Background.GetPixel(X, Y).ToArgb <> BackgroundColor.ToArgb Then
          '//-- Add first point to array !
          MatrixCentre = AddPoint(X, Y)
          Exit For
        End If
      Next
      If MatrixCentre.X <> -1 Then Exit For
    Next

    '//-- Worm your way around the pixel to find the next black pixel clockwise starting with the current
    MatrixStart = MatrixCentre
    While Not Finished
      FirstWhiteCell = False

      Do
        Select Case iPosToCheck
          Case 1 : X = MatrixCentre.X - 1 : Y = MatrixCentre.Y
          Case 2 : X = MatrixCentre.X - 1 : Y = MatrixCentre.Y - 1
          Case 3 : X = MatrixCentre.X : Y = MatrixCentre.Y - 1
          Case 4 : X = MatrixCentre.X + 1 : Y = MatrixCentre.Y - 1
          Case 5 : X = MatrixCentre.X + 1 : Y = MatrixCentre.Y
          Case 6 : X = MatrixCentre.X + 1 : Y = MatrixCentre.Y + 1
          Case 7 : X = MatrixCentre.X : Y = MatrixCentre.Y + 1
          Case 8 : X = MatrixCentre.X - 1 : Y = MatrixCentre.Y + 1
        End Select

        If Background.GetPixel(X, Y).ToArgb = BackgroundColor.ToArgb Then FirstWhiteCell = True
        If FirstWhiteCell AndAlso Background.GetPixel(X, Y).ToArgb <> BackgroundColor.ToArgb Then
          '//-- Add next point to array !
          MatrixCentre = AddPoint(X, Y)

          Select Case iPosToCheck
            Case 1 : iPosToCheck = 5
            Case 2 : iPosToCheck = 6
            Case 3 : iPosToCheck = 7
            Case 4 : iPosToCheck = 8
            Case 5 : iPosToCheck = 1
            Case 6 : iPosToCheck = 2
            Case 7 : iPosToCheck = 3
            Case 8 : iPosToCheck = 4
          End Select

          FirstWhiteCell = False

          If MatrixStart = MatrixCentre Then
            Finished = True
            Exit Do
          End If
        Else
          iPosToCheck += 1
          If iPosToCheck > 8 Then iPosToCheck = 1
        End If
      Loop

    End While

    Return oPoints
  End Function

  Private Function AddPoint(ByVal X As Integer, ByVal Y As Integer) As Point
    If oPoints Is Nothing Then
      ReDim oPoints(0)
      oPoints(0).X = X
      oPoints(0).Y = Y
    Else
      Dim Counter As Integer = oPoints.Length
      ReDim Preserve oPoints(Counter)
      oPoints(Counter).X = X
      oPoints(Counter).Y = Y
    End If

    Return New Point(X, Y)
  End Function
End Class

Open in new window

0
 
LVL 96

Accepted Solution

by:
Bob Learned earned 2000 total points
ID: 33625503
Oh, now I get it.  You want to pick out a shape from a drawn Bitmap.  GetPixel is not the fastest method for scanning Bitmaps.  Bob Powell describes a faster method, using LockBits and BitmapData, in this article:

Using the LockBits method to access image data
http://www.bobpowell.net/lockingbits.htm

"Using the LockBits method to access image data
Many image processing tasks and even file type conversions, say from 32 bit-per-pixel to 8 bit-per-pixel can be speeded up by accessing the pixel data array directly, rather than relying on GetPixel and SetPixel or other methods."
Dim x As Integer
Dim y As Integer
Dim PixelSize As Integer = 4
Dim bmd As BitmapData = bm.LockBits(new Rectangle(0, 0, 10, 10), System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat)

For y = 0 To bmd.Height - 1
    For x = 0 To bmd.Width - 1
       Marshal.WriteByte(bmd.Scan0, (bmd.Stride * y) + (4 * x) , 255)
    Next
Next

Open in new window

0
 
LVL 10

Author Closing Comment

by:Kinger247
ID: 33625573
Wow, not seen that before thanks.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 33625700
I would think that you might benefit more optimizations.  

1) Use generics--List(Of Point), and list.Add(point)

2) If you are just building points to redraw a line, you might be able to remove points that are on a similar line, so that you only have the end-points.  Determine direction of line, by comparing two points, and see if Math.Abs(x1 - x2) < tolerance or if Math.Abs(y1 - y2) < tolerance.

Example:
(1, 1)
(1, 2)
(1, 3)
(1, 4)

would become just (1, 1) and (1, 4)
0
 
LVL 10

Author Comment

by:Kinger247
ID: 33626649
TheLearnedOne, you are genius once again !

Never used List before, so good to learn something new.

I was trying to work out how I was going to remove duplicate points too, my idea wasn’t as tidy as yours though!

Cheers for your help !
0

Featured Post

Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
Suggested Courses

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question