reading jpg image pixel values

Posted on 2004-11-30
Medium Priority
Last Modified: 2008-02-01
OK, here is what I have...

I have a program that scans via twain image driver.

We have what is called a routing slip similar to a scantron where people are coloring in circles.

I want to be able to read pixel values from any point.  because we are scanning at such a high resolution the image goes outside of the visible picture box.  

my problem is that I cannot read any part of an image that is not visible in a picture box.

my goal is to read pixel rgb values given an x,y coordinate in pixels for any point in the image without dealing with a picture box or external dll objects.

we are using this object as an activeX web object.

Thank you so much for all your help
Question by:icredes
  • 4
  • 2
  • 2
  • +2
LVL 32

Expert Comment

ID: 12709914
How does the image get to the picturebox?
Are you passed any info about the image dimensions?

Author Comment

ID: 12709962
the only information that I have is the file path
LVL 28

Expert Comment

ID: 12710303
I assume the image is hidden, though, yes?  Why not set the Picturebox AutoSize property to True?
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.


Author Comment

ID: 12710368
the issue is that I need to be able to view the image at 100% 300 dpi

getting the image dimentions is not too difficult.

my concern is getting the pixel values

I am going to assume that the image is the correct size.

Author Comment

ID: 12710509
the autosize feature is interesting, but the point here is not to use the picture box

even if I get the correct size, the image is too big to fit on the screen.

is there another way....

lets assume that I were to do this in a module without the use of a form if possible.
LVL 32

Accepted Solution

Erick37 earned 2000 total points
ID: 12710555
You can use a memoryDC to load the picture into.  Then you can read the pixels using the GetPixel API.  All of the following code can be adapted for use in a module because no picturebox is used.

Option Explicit

Private Type BITMAP
        bmType As Long
        bmWidth As Long
        bmHeight As Long
        bmWidthBytes As Long
        bmPlanes As Integer
        bmBitsPixel As Integer
        bmBits As Long
End Type
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long

Private Sub Command1_Click()

    Dim pic As StdPicture
    Dim memDC As Long
    Dim px As Long
    Dim bm As BITMAP
    'Load a picture
    Set pic = LoadPicture("c:\thumb.jpg")
    'Create a DC compatible with the screen
    memDC = CreateCompatibleDC(0)
    'Select the picture into the DC
    Call SelectObject(memDC, pic.Handle)
    'Get the bitmap info
    Call GetObjectAPI(pic.Handle, LenB(bm), bm)
    Debug.Print "Picture dimensions: ", bm.bmHeight, bm.bmWidth
    'Here we read the center pixel color using GetPixel
    px = GetPixel(memDC, bm.bmWidth / 2, bm.bmHeight / 2)
    Debug.Print "The color is " & Hex(px)
    'Done, Clean Up
    Call DeleteDC(memDC)

End Sub

LVL 17

Expert Comment

ID: 12710923
@ icredes

The following program needs a source Picbox(no matter if visible or invisible) and a destination picbox(visible).

It works without API. You will get all the r-g-b values of the picture and of each pixel.

'Needs 2 Pictureboxes
Const Pic = "C:\WINDOWS\Desktop\LAPTOP.JPG"

Private Sub Form_Activate()
AutoRedraw = -1: Picture2.ScaleMode = 3
Move 0, 0: Picture1.BackColor = vbBlue
Picture1.Move 15 * 70, 15 * 15, 15 * 360, 15 * 290
Picture1.BorderStyle = 0: Picture1.ScaleMode = 3
Picture2.BorderStyle = 0: Picture1.BackColor = vbWhite: Picture2.BackColor = vbWhite
Picture2.Move Picture1.Left + Picture1.Width + 15 * 9, 15 * 15, 15 * 30, 15 * 18
Picture1.Picture = LoadPicture("C:\WINDOWS\Desktop\LAPTOP.JPG")
For YY = 0 To Picture1.Picture.Width
For XX = 0 To Picture1.Picture.Height

Picture2.PaintPicture Picture1.Picture, 0, 0, 1, 1, XX, YY, 1, 1

col = Picture2.Point(0, 0) 'BGR
Picture2.BackColor = col

b = (col And 16711680) / 65536 '     16711680  = FF0000
g = (col And 65280) / 256 '          65280     = FF00
r = col And 255

MsgBox XX & "  ,  " & YY & vbCrLf _
       & "r , g , b" & vbCrLf & r & " , " & g & " , " & b

Next: End

End Sub
LVL 17

Expert Comment

ID: 12713871
I found a good way to do this.   What it does is map an array's memory to point to a picture's memory.  But the cute thing is that you map a UDT array so that you don't have to do any maths to get the pixel values. This makes it very fast.

I took the concept from here:


(Also search goolge for safearray2d for more inhfo/examples like the same.

And then made the leap into using a UDT array. You can either use a 2 dimensional array, or in some cases for faster image processing, you can use a single dimensional array.

I renamed the class zPicArray, so for example:

Dim PA as zPicArray

Set picAnyPic.Picture = LoadPicture("C:\........jpg")
Set PA = New zPicArray
PA.LoadImage picAnyPic
Pa.ProcessImage Actions.ConvertToGreyScale

' extract from the class (single dimension version) the following converts a colour image to greay scale

Sub ProccessImage(Action As Actions)

Dim cp As Long
Dim Av As Long
Dim bt As Byte
Dim GreyFactor As Single

GreyFactor = 0.333333
cp = 0

Select Case Action
    Case Is = Actions.ConvertToGreyScale

    ' loop through image
    Do While cp < aSize ' asize is the size of the pic in pixels
        Av = (0& + Data(cp).Red + Data(cp).Green + Data(cp).Blue) * GreyFactor
        bt = Av
        ' Save the greyed pixel values back into the picture box
        Data(cp).Red = bt
        Data(cp).Green = bt
        Data(cp).Blue = bt
        cp = cp + 1
End Select

End Sub

In you case you may wish to stay with 2 dim array. So to modify the example from visualbasicforum to use UDT's you need:

Private Type PixelDef
  Blue As Byte
  Green As Byte
  Red As Byte
End Type

Private Data() As PixelDef ' was byte

And in the LoadImage sub change

.cbElements = 3 ' was 1 to point to a byte

If you need any more info with this concept.
LVL 17

Expert Comment

ID: 12713905
And also in the loadimage change:

.Bounds(1).cElements = BMP.bmWidthBytes


.Bounds(1).cElements = BMP.bmWidth

So after your loadimage you can then loop image.  I posted a single dim example, here is a 2 dim example of looping through an image:

' filter out red
For y = 0 To mvarUBoundY
    For x = 0 To mvarUBoundX
       Datal(x,y).Red = 0

Author Comment

ID: 12716036
Erick37  you nailed it

that works great for me...thanks

Featured Post


Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses
Course of the Month16 days, 19 hours left to enroll

862 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