View Full Version : Image handling
Isengard
08-07-2002, 05:13 AM
Well .. after trying this out and getting it to work in Java ( Tnx Dru Lee Parsec! :tu: ), I am now using Matrox Inspector which is based on Visual Basic 6.0. ( Gotta love those exec. ) The thing is .. I want to get the value of each pixel within a specified ROI.
The image is loaded with a little help from Inspector and stored as a string
Image$ = Insptr.ImgLoad( "Path" )
To get the pixelvalues, I got a suggestion declaring a function like this :
Declare Function GetPixel Lib "gdi32" Alias "GetPixel" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
But hdc, the image, is a String and not long. If I change the code to read and return a string, it get no error message, but I get no value either.
I want to search each pixel with two for loops, sort of like this. The if / else conditions are not important right now .. I got to get to the values first
:humbug:
for i = 1 to x
for j = 1 to y
if/else
pixelValue = getPixel( Image, i, j )
end for
end for
I've also read about a function named Point. Point( i, j ), but haven't gotten this to work.
:wtf:
Don't know if I've made myself understood on this .. but any help is appreciated.
comrade
08-08-2002, 01:11 AM
hDC is a handle to a device context, which is an internal type used by Windows. You do not have to use GetPixel to read the image. Assuming the string given by Insptr.ImgLoad consists of 24-bit RGB values, you can use these procedures to extract pixels:
Private Function GetPixel24(image As String, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long) As Long
ByVal nPos As Long
nPos = (y * nWidth + x) * 3
GetPixel24 = (Asc(Mid(image, nPos + 1, 1)) * 65536) + (Asc(Mid(image, nPos + 2, 1)) * 256) + (Asc(Mid(image, nPos + 3, 1)))
End Function
Private Function GetPixel24pad(image As String, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long) As Long
ByVal nPos As Long
nPos = y * nWidth * 3
If nPos And 3 Then
nPos = nPos + (4 - (nPos And 3))
End If
GetPixel24pad = (Asc(Mid(image, nPos + 1, 1)) * 65536) + (Asc(Mid(image, nPos + 2, 1)) * 256) + (Asc(Mid(image, nPos + 3, 1)))
End Function
GetPixel24pad should be used if the scanlines in the image are padded on a DWORD boundary (start on 4-byte boundaries).
If the image is in 32-bit format (extra byte per pixel, alpha-channel), the procedure needs little modification and becomes this:
Private Function GetPixel32(image As String, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long) As Long
ByVal nPos As Long
nPos = (y * nWidth + x) * 4
GetPixel32 = (Asc(Mid(image, nPos + 1, 1)) * 65536) + (Asc(Mid(image, nPos + 2, 1)) * 256) + (Asc(Mid(image, nPos + 3, 1)))
End Function
In the last case, if the image uses 16-bit format (which is very unlikely), the procedure will look like this:
Private Function GetPixel16(image As String, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long) As Long
ByVal nPos As Long
nPos = (y * nWidth + x) * 2
GetPixel16 = (Asc(Mid(image, nPos + 1, 1)) * 2048) + (Asc(Mid(image, nPos + 2, 1)) * 32) + (Asc(Mid(image, nPos + 3, 1)))
End Function
This will extract a 16-bit pixel (5-6-5). Another rare case is the 5-5-5 format, which should be handled like so:
Private Function GetPixel16old(image As String, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long) As Long
ByVal nPos As Long
nPos = (y * nWidth + x) * 2
GetPixel16old = (Asc(Mid(image, nPos + 1, 1)) * 1024) + (Asc(Mid(image, nPos + 2, 1)) * 32) + (Asc(Mid(image, nPos + 3, 1)))
End Function
The 5-5-5 format is used by older video cards, and by Windows OLE IPicture.LoadPicture() interface method.
To convert a 16-bit pixel (5-6-5) to a 24-bit RGB value, you would need to use this procedure:
Private Function Convert16to24(ByVal nColour As Long) As Long
Dim r As Long, g As Long, b As Long
r = (nColour \ 2048)
g = (nColour \ 32) Mod 64
b = (nColour) Mod 32
Convert16to24 = (r * 65536) + (g * 256) + (b)
End Function
Again, if you need to use the older 5-5-5 format, you can modify the above procedure:
Private Function Convert16to24old(ByVal nColour As Long) As Long
Dim r As Long, g As Long, b As Long
r = (nColour \ 1024)
g = (nColour \ 32) Mod 64
b = (nColour) Mod 32
Convert16to24old = (r * 65536) + (g * 256) + (b)
End Function
One last note is that sometimes the colours in 24-bit and 32-bit images will be stored in reverse byte order (silly little-endian), so you will have to swap Red with Blue in order to get the correct colour.
Isengard
08-08-2002, 02:19 AM
:tu:
TNX!
Only thing is .. I forgot to mention it ... it is grayscale ( 8 bit ) image, but it is also possible to work with RGB images for now, I'll just modify what I need, it I need it. The code looks exellent. Tnx again for the reply!
Isengard
08-08-2002, 04:55 AM
I tried this :
result = GetPixel24( I_nyRoi, 300, 450, 600 )
Just to test, but resultat gets the value 0. How come ? The value of that point is : r:200, g:208, b:208
Also .. I was wondering if you could explain just what nWidth is, and where I get it. I guess it is the width of the image, but is there any method to get this returned ?
The pictures I'm working with are .bmp, so I guess they are 24 bit images. What I do is run edge detection, histogram equalisation and such and converting it to 8 bit grayscale image. But it is possible to do those things on regular color image.
comrade
08-08-2002, 03:00 PM
I could further help you if you dumped the contents of Image string returned by ImgLoad into a file and posted it here, so we could determine the format.
comrade
08-08-2002, 03:01 PM
nWidth (width of image) is needed in order to determine how many bytes are on each scanline.
comrade
08-08-2002, 03:02 PM
Another thing I forgot to mention:
You CAN work with 24-bit images and convert the pixels to grayscale on the fly. Grayscale is simply average of all 3 components.
Isengard
08-09-2002, 03:14 AM
Aaa... of course. That I really should've known :biggrin:
Tnx for your help!
About dumping the file.. I don't exactly understand what you mean by that .. ?
comrade
08-09-2002, 04:30 AM
Open "C:\image.dmp" For Binary Access Write Lock Read Write As #1
Put #1,,Image
Close #1
Image being the string returned by ImgLoad of course. Then I guess you could ZIP C:\image.bmp and post here. :-p
Isengard
08-09-2002, 04:59 AM
Did that, and here is the picture. ( "bilde9detektert.bmp", it's norwegian and means "picture2detected.bmp" :-p )
The picture is edge detected, and I need to search the pixels and check their value to find the edges.. which would be represented by high values.
comrade
08-09-2002, 02:28 PM
Thanks, that helped. Basically the Image data returned by ImgLoad is not raw data, but actually a real Windows bitmap file with the standard bitmap headers. To get rid of them, simply do:
Dim nPos As Long
nPos = Asc(Mid(Image, 11, 1))
Image = Right(Image, Len(Image) - nPos)
...
colour = GetPixel24(...)
Isengard
08-12-2002, 03:30 AM
It finally worked!!
:D
Tnx for your help comrade!
Really appreciate it!
vBulletin® v3.7.0, Copyright ©2000-2009, Jelsoft Enterprises Ltd.