|
-
Jun 5th, 2001, 03:07 PM
#1
Thread Starter
New Member
Array Data to Image for Quick display
I'm having bigtime problems with this one. I have an array of data, which I loaded in of RAW format. The first n (width*height) number of pixel intensities is the red plane, the next n number of intensities is the green plane, etc. I need to display this in a quick fashion into a picturebox. Using the pset command to pset each pixel in a loop is rediculously slow. I can't seem to get any other method to work. This one is really stumping me and the performance of my application is really really suffering. PLEASE HELP. Source code is greatly appreciated.
Thanks,
-Richard
-
Jun 5th, 2001, 03:21 PM
#2
Good Ol' Platypus
This unfortunately is THE biggest problem some people have with graphics. SetPixel & GetPixel APIs are better (actually you should use SetPixelV) but there is still a lot of a performance loss. I suggest using directdraw (dx7).
All contents of the above post that aren't somebody elses are mine, not the property of some media corporation. 
(Just a heads-up)
-
Jun 5th, 2001, 03:25 PM
#3
Thread Starter
New Member
Array Data to Image for Quick display
If I use DirectX 7 API stuff will this work under Windows NT 4.0? My company has not upgraded yet and the platforms this will be running on will be windows NT. Is this much easier than using the impossible API calls CreateBitmap etc, which no matter what i do do not function correctly?
Thanks
-Richard
-
Jun 6th, 2001, 06:10 PM
#4
Lively Member
I used something like this for 8 bit images its quite fast, you might want to read up on these functions
Code:
'Source_DC is a memory DC created using CreateCompatibleDC
'temp is a long (acts as a pointer)
'Source_Array(0,0) is a byte array of data, note i pass the first value
'Info is a BITMAPINFO type which includes a BITMAPINFOHEADER and a RGBQUAD data types
temp = CreateDIBitmap(Dest_DC, Info.bmiHeader, CBM_INIT, Source_Array (0, 0), Info, 2)
SelectObject Source_DC, temp
BitBlt Form1.Display.hdc, 0, 0, Form1.Display.Width, Display.Height, Source_DC, 0, 0, vbSrcCopy
Display.Refresh
Note that the horizontal size of the array must be word aligned (even number of bytes). You can flip the image by making Info.bmiHeader.biHeight negative.
Hope this helps.
-
Jun 7th, 2001, 04:07 AM
#5
Frenzied Member
I found this one too and it's quite fast - you'll find it at the Unlimited Realities web site:
http://www.ur.co.nz
The only problem is that it doesn't work with BitBlt 
Hey Illuminator, do you think it's possible to use that to get (and edit) an array from a DC?
-
Jun 7th, 2001, 10:51 AM
#6
Lively Member
I think you can get the bits into an array from a DC using the GetDIBits function (you'll need a bitmap handle), you then modify the bits how you want then copy them back like above.
-
Jun 7th, 2001, 12:00 PM
#7
Thread Starter
New Member
I solved this, and it works pretty well.
What i did was wrote a DLL in C that loads the raw image into a character array. Then I populate the BITMAPFILEHEADER and BITMAPINFO structures and write them to a file in binary mode using fwrite.
The order to write these things is HEADER, INFO, DATA. The Pixel data must be interleaved b g r. Using fread and memcpy really increased the performance TONS. I can load a 600x449 raw image with 3 planes rrrrggggbbb convert to a bmp and display that bmp in VB in well under a second. I used the Picture1.Picture=LoadBitmap("blah.bmp") method. This is on a 500mhz AMD processor and reading from a mapped network drive. Not too shabby. I know I kind of cheesed out and didn't use vb but I was in it for the speed, and i am not so sure if I could have done it this fast in VB.
Thanks everyone for their help, if ya'll want the code just e-mail me and I'll send you the routine.
-Richard
-
Jun 8th, 2001, 06:26 AM
#8
Frenzied Member
Well... but do you have any idea as to getting the bitmap handle?
-
Jun 14th, 2001, 08:15 PM
#9
Fanatic Member
This is probably too late to be of any help, and you may already know it, but the handle would be like the return of CreateBitmap(), CreateCompatibleBitmap(), or the .Handle members of either IPictureDisp or StdPicture. The .Picture prop of a picturebox is StdPicture, and the default member is .Handle. Any of those can be shoved into a DC with SelectObject.
I'm baaaack...
VB5 Professional Edition, VC++ 6
Using a 1 gHz Thunderbird, 256 mb RAM, 40 gb HD system with Win98se
I feel special because I finally figured out how to loop midis: Post link
I'm a fanatic too 
-
Jun 15th, 2001, 12:07 PM
#10
Frenzied Member
Hey Kaverin, can you please show me some source code with that put to use? I don't understand a single word of what you're saying (I mean, just a bit - no one really thaught me that stuff of handles and all )
-
Jun 16th, 2001, 03:27 AM
#11
Fanatic Member
Sure, here's some stuff that uses it. Say you wanted to put a bitmap into the form, but didn't want to use VB's LoadPicture() function. You could use the APIs LoadImage() and SelectObject() to do it.
Code:
Option Explicit
'Paste this into a form, and click the form after you run it
Private Declare Function LoadImage Lib "user32" Alias "LoadImageA" (ByVal hInstance As Long, ByVal lpszFile As String, ByVal uType As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal uFlags As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Const LR_LOADFROMFILE As Long = &H10
Private Const IMAGE_BITMAP As Long = 0
Private Sub Form_Click()
Dim hBitmap As Long
hBitmap = LoadImage(App.hInstance, "c:\windows\clouds.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)
SelectObject Me.hDC, hBitmap
Me.Refresh
End Sub
I'm baaaack...
VB5 Professional Edition, VC++ 6
Using a 1 gHz Thunderbird, 256 mb RAM, 40 gb HD system with Win98se
I feel special because I finally figured out how to loop midis: Post link
I'm a fanatic too 
-
Jun 16th, 2001, 07:14 AM
#12
Frenzied Member
Heh, cool 
Is it possible to do exactly the opposite? I mean, dumping an hDc to a bitmap? Because that's exactly what I was trying to do...
-
Jun 16th, 2001, 12:13 PM
#13
Fanatic Member
I'm not quite sure how to save a bitmap directly from the DC that
it resides in (at least in an appropriate manner), but I'm sure it's
possible in some way. Assuming you had a picture in a
picturebox, an easy way would be to use VB's built in things.
Code:
SavePicture picPicture.Picture, "c:\mypicture.bmp"
I prefer using more API functions when possible, but I don't know
of way offhand to do this. I'll have to look around to see if there
is anything. There has to be a way, since Windows/VB already
does it . So until I (or you on your own if you want to research
it) can find out how, you can just stuff your pictures into a
picturebox and use the above way.
I'm baaaack...
VB5 Professional Edition, VC++ 6
Using a 1 gHz Thunderbird, 256 mb RAM, 40 gb HD system with Win98se
I feel special because I finally figured out how to loop midis: Post link
I'm a fanatic too 
-
Jun 18th, 2001, 08:54 AM
#14
Frenzied Member
Thanks. But using SavePicture() 30 times in a second doesn't seem very nice to me (my hard drive would burn )
-
Jun 19th, 2001, 01:43 PM
#15
Frenzied Member
-
Jun 19th, 2001, 03:36 PM
#16
Fanatic Member
For that thing I gave above, there were some things I noticed that I left out. If you only do something like this once it won't matter all that much, but over time this method could lead to problems as it chews up resources (from not deleting them). That was a slip on my part. This is how it should be done, with the changed parts in blue.
Code:
Option Explicit
'Paste this into a form, and click the form after you run it
Private Declare Function LoadImage Lib "user32" Alias "LoadImageA" (ByVal hInstance As Long, ByVal lpszFile As String, ByVal uType As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal uFlags As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Const LR_LOADFROMFILE As Long = &H10
Private Const IMAGE_BITMAP As Long = 0
Private Sub Form_Click()
Dim hBitmap As Long, hOldBitmap As Long
hBitmap = LoadImage(App.hInstance, "c:\windows\clouds.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)
'This saves the bitmap that was already in the DC, if any
'Selecting an object into a DC replaces an object of the same type that's already in it. That object's handle is returned
hOldBitmap = SelectObject(Me.hDC, hBitmap)
Me.Refresh
'after you're done, restore the old bitmap, and delete your created one
DeleteObject SelectObject(Me.hDC, hOldBitmap)
End Sub
I'm baaaack...
VB5 Professional Edition, VC++ 6
Using a 1 gHz Thunderbird, 256 mb RAM, 40 gb HD system with Win98se
I feel special because I finally figured out how to loop midis: Post link
I'm a fanatic too 
-
Jun 19th, 2001, 03:39 PM
#17
Good Ol' Platypus
On non-8 bit pictures
This is a little tip for you guys 
You can access this byte array the same way you use GetLockedArray. This means that you can use different indexes for the bits. 16 bit colour involves bit shifts and I wont get into that now, but you can refrence the R G and B properties like this:
VB Code:
Function RetLongArray(ByRef LongArray() As Long, ByRef ByteArray() As Byte, X, Y, BITS As Long)
LongArray(X,Y) = RGB(ByteArray(X*(BITS/4),Y), ByteArray(X*(BITS/4)+1,Y), ByteArray(X*(BITS/4)+2,Y))
This works both for 24 and 32 bit pictures .If you notice something wrong then use:
VB Code:
Function RetLongArray(ByRef LongArray() As Long, ByRef ByteArray() As Byte, X, Y, BITS As Long)
LongArray(X,Y) = RGB(ByteArray(X*(BITS/4)+2,Y), ByteArray(X*(BITS/4)+1,Y), ByteArray(X*(BITS/4),Y))
End Function
You could then use this with an aforementioned piece of code. (Illuminator's)
Last edited by Sastraxi; Jun 19th, 2001 at 03:50 PM.
All contents of the above post that aren't somebody elses are mine, not the property of some media corporation. 
(Just a heads-up)
-
Jun 19th, 2001, 04:23 PM
#18
transcendental analytic
Why not sas? probably because you can't in vb.
Tell me why you need a long array because what youre doing seems like a waste of cpu.
Then I populate the BITMAPFILEHEADER and BITMAPINFO structures and write them to a file in binary mode using fwrite...
... I used the Picture1.Picture=LoadBitmap("blah.bmp") method. This is on a 500mhz AMD processor and reading from a mapped network drive. Not too shabby. I know I kind of cheesed out and didn't use vb but I was in it for the speed, and i am not so sure if I could have done it this fast in VB.
In fact the part buffering the bitmap on the harddisk is totally unnessesary. Since you've thrown the headers for bitmap together the next step would be to use CreateDIBitmap with a pointer to DATA and a DC you could pass as a parameter from vb.
Use  
writing software in C++ is like driving rivets into steel beam with a toothpick.
writing haskell makes your life easier:
reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.
-
Jun 19th, 2001, 04:40 PM
#19
Good Ol' Platypus
You know what I just noticed that, just thought... ah nm. You could change that long array into just a long and destroy the (X, Y) after it.
All contents of the above post that aren't somebody elses are mine, not the property of some media corporation. 
(Just a heads-up)
-
Jun 19th, 2001, 04:47 PM
#20
transcendental analytic
Alright but i still don't know what you are aiming for
Use  
writing software in C++ is like driving rivets into steel beam with a toothpick.
writing haskell makes your life easier:
reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.
-
Jun 19th, 2001, 04:49 PM
#21
Good Ol' Platypus
Well some people want it easy... 
Although in theory it would be easier to do it the way that they give you.
All contents of the above post that aren't somebody elses are mine, not the property of some media corporation. 
(Just a heads-up)
-
Jun 19th, 2001, 05:39 PM
#22
Lively Member
Here is a bit of code I wrote to load a bitmap byte array from your hard disk, then paints the bits to an HDC
Code:
Public Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Public Declare Function CreateDIBitmap Lib "gdi32" (ByVal hdc As Long, lpInfoHeader As BITMAPINFOHEADER, ByVal dwUsage As Long, lpInitBits As Byte, lpInitInfo As BITMAPINFO, ByVal wUsage As Long) As Long
Public Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Public Const CBM_INIT = &H4
'API calls for fast bitmap functions
Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Public Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Public Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Type MEMORY_BITMAP
info As BITMAPINFO
hdc As Long
byte_array() As Byte
End Type
Sub LoadBitmapFromFile(Filename as string, MyBitmap as MEMORY_BITMAP, Pic as Picturebox)
Open Filename For Binary Access Read As #1
Get #1, 15, MyBitmap.info.bmiHeader
Get #1, , MyBitmap.info.bmiColors
ReDim MyBitmap.byte_array(MyBitmap.info.bmiHeader.biWidth - 1, MyBitmap.info.bmiHeader.biHeight - 1) As Byte
Get #1, 1078, MyBitmap.byte_array()
Close #1
Dim P As Long
P = CreateDIBitmap(MyBitmap.hdc, MyBitmap.info.bmiHeader, CBM_INIT, MyBitmap.byte_array(0, 0), MyBitmap.info, 2)
SelectObject MyBitmap.hdc, P
DeleteObject P
BitBlt Pic.hdc, 0, 0, Picture1.Width, Picture1.Height, MyBitmap.hdc, 0, 0, vbSrcCopy
Pic.Refresh
End Sub
You can easily check MyBitmap.info.bmiHeader.biBitCount which will either be 8, 16, 24, or 32 then use an appropriate byte filler like Sastraxi provided to modify the image pixel colors.
-
Jun 19th, 2001, 11:06 PM
#23
Fanatic Member
I think there may be an easier (but not necessarily better) way to
do that, but I'm not sure. I'd have to mess around with it. I've
been doing this kind of stuff for the past week for the hell of it,
and just finished up messing with some API font things. I get
sidetracked when working on things so easily . I'll play around
little later and see if I can get something working, as I just got
n idea to try on one of the problems I've hit recently.
I'm baaaack...
VB5 Professional Edition, VC++ 6
Using a 1 gHz Thunderbird, 256 mb RAM, 40 gb HD system with Win98se
I feel special because I finally figured out how to loop midis: Post link
I'm a fanatic too 
-
Jun 20th, 2001, 04:02 AM
#24
Frenzied Member
-
Jun 20th, 2001, 06:42 AM
#25
transcendental analytic
Sas, there's no optimizer in vb, no inlining no nothing, so if you want it easy, then why using the freaking api's at all? there's stdpictures and paintpicture for god's sake. Back to reality, a long array would only bring performance pain for the vb-programmer, thats why getlockedarray assigns a byte array pointer.
Illuminator got the code right, if you just plan to have the bitmap, the bitblt is also unnessesary.
Youre missing a big detail Jotaf, what DC's really are.
DC's don't contain any bitmap data but provide access to bitmaps using GDI functions, when you create one, it only contains the context where to draw the bitmap that is, offscreens don't have that either. If you want the bitmap by handle currently attached to a DC, you should use selectobject to attach a null, and selectobject it back, the handle you retrieved the first time is the bitmap handle.
Use  
writing software in C++ is like driving rivets into steel beam with a toothpick.
writing haskell makes your life easier:
reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.
-
Jun 20th, 2001, 03:26 PM
#26
Fanatic Member
The things I was working on involved popping out an hBitmap
from a DC and then saving it to a .bmp file. That's not quite as
easy as it sounds though. I keep getting problems trying to get
all the proper information so I can actually write a .bmp file. I do
know the structures required, but there are other things that
may vary, and I can't decide whether to attempt to allow for them
all, or just pick one and have the function save only a bitmap of
that particular type.
As long as a DC contains a bitmap, sure, you can pop it out
(either the way Kedaman said or by doing something that makes
a new bitmap, and then SelectObject that back into the DC).
When you use SelectObject to put an object into a DC, it will
return to you the object of the same type that was already in it
or 0 I believe if there wasn't any in it, or it had some error).
Last edited by Kaverin; Jun 20th, 2001 at 03:35 PM.
I'm baaaack...
VB5 Professional Edition, VC++ 6
Using a 1 gHz Thunderbird, 256 mb RAM, 40 gb HD system with Win98se
I feel special because I finally figured out how to loop midis: Post link
I'm a fanatic too 
-
Jun 20th, 2001, 03:48 PM
#27
transcendental analytic
who gave you such a crappy explanation jotaf?
btw Kaverin, I might be able to help you, made a similar algoritm in c++.
Use  
writing software in C++ is like driving rivets into steel beam with a toothpick.
writing haskell makes your life easier:
reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.
-
Jun 21st, 2001, 04:02 AM
#28
Frenzied Member
Hum... I think it was when I read the Lander game tutorial here at VB-World
-
Jun 25th, 2001, 03:16 PM
#29
Thread Starter
New Member
The reason I wanted a long array is because I have some filters and transforms (sobel, watershed) for image segmentation that are not written by me. I need direct Pixel access to the image, knowing what R, G, B intensites are at each pixel. what I did was load this image using all the fread stuff in c, then outputted it to a bmp and used the paintpicture method to display it in a picture box. This gave me access to each pixel intensity and also quickly displayed it.
My new dilemma is how to do the same thing with Tiff files. I want pixel level knowlege but I want to display them quicky in a picturebox (or similar) display. I want to pass the pixel data from the loaded tiff file to my routines as well.
Any suggestions? code snippets would be apprecaited too.
Thanks,
-Richard
-
Jun 26th, 2001, 10:02 AM
#30
Frenzied Member
Hum... I saw an excellent DLL that can load lots of different file formats, maybe it has that one. It's at http://www.planet-source-code.com (I think it's one of the winners of the code contest so it should be in the front page, not sure - if it isn't I can e-mail it to you).
-
Jun 26th, 2001, 10:23 AM
#31
Thread Starter
New Member
-
Jun 26th, 2001, 11:15 AM
#32
-
Jun 26th, 2001, 11:22 AM
#33
transcendental analytic
note only for bitmaps, that is bmp's. if you need pixel data for other formats you can use getpixel when attached to a device
Loadpicture takes in gif and jpeg as well and other formats you usually wont need to, you aren't developing a new psp are you?
Use  
writing software in C++ is like driving rivets into steel beam with a toothpick.
writing haskell makes your life easier:
reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|