Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How To... Access the memory block of a PictureBox...?

Status
Not open for further replies.

CubeE101

Programmer
Nov 19, 2002
1,492
US
How do you access the block of memory that stores the picture data for a picture box and/or a picture object of a form...

The image information for a PictureBox and Form.Picture is stored somewhere in memory...

How can you access the actual image array for these objects in memory, directly. (with out using the .point(x,y) method?

in QBasic you could use:
DefSeg, VarSeg & VarPtr
to access the Data Segment, Variable's segment, & the Variables Pointer, Respectively...

Does the same apply to VB, or is there a better method of doing this...

Form1.Point(X,Y) and Picture1.Point(X,Y) only work if the Image is Visible... Not to mention... IT IS SLOW...

However, Regardless of the visibility of the image, the data is still in memory. Accessing the data directly via memory calls "Should" dramatically increase the speed AND efficiency of the process.

If anyone has any information on how to do this... I would appriciate the share of knowledge...

I'm sure there is a very simple method for it... I just have not yet ran accross it Yet.

Thanks -n- Advance Sometimes... the BASIC things in life are the best...
cheers.gif

or at least the most fun ;-)
-Josh Stribling
 
.Picture, which is just a wrapper for IPictureDisp/StdPicture, has a property called Handle. This contains a normal GDI handle to the bitmap (what MSDN will refer to as hBmp). So all you need to do is create a memory DC, select the bitmap into it via SelectObject, then grab the basic info you need (a BITMAP) for walking the bitmap by doing a GetObject
 
Thanks for the reply... I got a couple of Q's though...

I haven't used handles very much...
Can you give me a short example (just the highlights) of what you are talking about... (is hWnd a window handle?)

whats a memory DC?

is SelectObject a VB function.. (it is greyed out in the help file)
If NOT... what do you need to reference?

-Thnx- Sometimes... the BASIC things in life are the best...
cheers.gif

or at least the most fun ;-)
-Josh Stribling
 
SelectObject and GetObject are API calls, so you need a function declaration. You can get it from the VB Tools API Text Viewer utility.

Yes, hWnd is a window handle, and hBmp is a bitmap handle.

A DC is a device context. A memory DC is a device context that is held in memory rather than being associated with a particular device (such as, say, the screen)
 
strongm's suggestion is the most convenient method for most tasks. For learning purposes I'm posting code from an old voxel landscape renderer that copies the base address of the bitmap bits to the address of an array so you can access them like pict(x,y) or pict(x) if you use a one dimensional array.

This may not be too friendly at first but the reason I'm mentioning it is that it is much better faster for image processing especially with 24 bit bmps because you usually need to work with RGB values. If you're using a memory DC then you need to convert the long value to its RGB components, do the manipulation, and then conver it back. This is also a faster when working with large chunks of the bitmap because copying is faster. I converted this code to use 24 bit bmps in just a few minutes a couple years back. If you decide to do this you will need to read up on the bitmap format. That's why I said it was for learning purposes :) If you are doing manipulation you would probably be much happier with the speed.




Option Explicit

Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type

Private Type SAFEARRAY1D
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
Bounds(0 To 0) As SAFEARRAYBOUND
End Type

Private Type SAFEARRAY2D
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
Bounds(0 To 1) As SAFEARRAYBOUND
End Type

Private Declare Function VarPtrArray Lib "msvbvm50.dll" Alias "VarPtr" (Ptr() As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
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 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
Private Const SRCCOPY = &HCC0020 ' (DWORD) dest = source
Private Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long

Private Const SCREEN_WIDTH = 319
Private Const SCREEN_HEIGHT = 239
Private Const MAX_STEPS = 300


Dim x_ray As Double, y_ray As Double, z_ray As Double
Dim vp_x As Double, vp_y As Double, vp_z As Double
Dim vp_ang_x As Double, xr As Double, yr As Double
Dim curr_row As Integer, curr_step As Integer, curr_voxel_scale As Double
Dim dslope As Double, raycast_ang As Integer
Dim column_height As Double, color As Byte

Dim mx As Integer, my As Integer
Dim exitflag As Boolean
Dim dx As Double, dy As Double, dz As Double


Sub DrawFrame()
'***********************************
' Setup the bitmaps so we can
' get to their memory
'***********************************

' these are used to address the pixel using matrices
Dim pict() As Byte
Dim pict2() As Byte
Dim pict3() As Byte


Dim sa As SAFEARRAY2D, bmp As BITMAP
Dim sa2 As SAFEARRAY2D, bmp2 As BITMAP
Dim sa3 As SAFEARRAY2D, bmp3 As BITMAP
Dim r As Integer, c As Integer
' get bitmap info

GetObjectAPI Pic.Picture, Len(bmp), bmp 'picture
GetObjectAPI Pictxt.Picture, Len(bmp2), bmp2 'texture
GetObjectAPI Pichgt.Picture, Len(bmp3), bmp3 'height map

' exit if not a supported bitmap
If bmp.bmBitsPixel <> 8 Then
MsgBox &quot; 8-bit bitmaps only&quot;, vbCritical
Exit Sub
End If

' have the local matrix point to bitmap pixels
With sa
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = bmp.bmHeight
.Bounds(1).lLbound = 0
.Bounds(1).cElements = bmp.bmWidthBytes
.pvData = bmp.bmBits
End With
CopyMemory ByVal VarPtrArray(pict), VarPtr(sa), 4

' have the local matrix point to bitmap pixels
With sa2
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = bmp2.bmHeight
.Bounds(1).lLbound = 0
.Bounds(1).cElements = bmp2.bmWidthBytes
.pvData = bmp2.bmBits
End With
CopyMemory ByVal VarPtrArray(pict2), VarPtr(sa2), 4

' have the local matrix point to bitmap pixels
With sa3
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = bmp3.bmHeight
.Bounds(1).lLbound = 0
.Bounds(1).cElements = bmp3.bmWidthBytes
.pvData = bmp3.bmBits
End With
CopyMemory ByVal VarPtrArray(pict3), VarPtr(sa3), 4

'***********************************
' Here is where we draw a frame
'***********************************
For c = 0 To 319
For r = 0 To 239
pict(c, r) = 0
Next
Next

'**********************************************************
'Thanks to Andre' LaMothe for the C source code this Voxel
'demonstration is based on. David Brebner 24/1/98
'**********************************************************

For c = 0 To SCREEN_WIDTH 'cast a ray for each column of the screen
' seed starting point for cast
x_ray = vp_x
y_ray = vp_y
z_ray = vp_z

' compute deltas to project ray at, note the spherical cancelation factor
dx = Cos((raycast_ang + c) / 360)
dy = Sin((raycast_ang + c) / 360)

' dz is a bit complex, remember dz is the slope of the ray we are casting
' therefore, we need to take into consideration the down angle, or
' x axis angle, the more we are looking down the larger the intial dz
' must be
dz = dslope * -100

' reset current voxel scale
curr_voxel_scale = 0

' reset row
curr_row = 0


For curr_step = 0 To MAX_STEPS ' enter into casting loop
xr = x_ray And 511 'trim
yr = y_ray And 511 'trim
' get current height in height map
' and the added multiplication factor used to scale the mountains
column_height = pict3(xr, yr) '* 2

'test if column height is greater than current voxel height for current step
'from intial projection point
If column_height > z_ray Then
' we know that we have intersected a voxel column, therefore we must
' render it until we have drawn enough pixels on the display such that
' thier projection would be correct for the height of this voxel column
' or until we have reached the top of the screen

' get the color for the voxel
color = pict2(xr, yr)

' draw vertical column voxel
Do
' draw a pixel
pict(c, curr_row) = color

' now we need to push the ray upward on z axis, so increment the slope
dz = dz + dslope

' now translate the current z position of the ray by the current voxel
' scale per unit
z_ray = z_ray + curr_voxel_scale

' test if we are done with column
curr_row = curr_row + 1
If (curr_row >= 239) Then
' force exit of outer steping loop
curr_step = MAX_STEPS
Exit Do
End If

Loop Until z_ray > column_height
End If
' update the position of the ray
x_ray = x_ray + dx
y_ray = y_ray + dy
z_ray = z_ray + dz

' update the current voxel scale, remember each step out means the scale increases
' by the delta scale
curr_voxel_scale = curr_voxel_scale + dslope * 0.5

Next


Next

'***********************************
' Clean up the bitmaps
'***********************************
' clear the temporary array descriptor
' without destroying the local temporary array
CopyMemory ByVal VarPtrArray(pict), 0&, 4
CopyMemory ByVal VarPtrArray(pict2), 0&, 4
CopyMemory ByVal VarPtrArray(pict3), 0&, 4

End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)

Select Case KeyCode
Case vbKeyQ
vp_y = vp_y + 10
Case vbKeyA
vp_y = vp_y - 10
Case vbKeyZ
vp_x = vp_x + 10
Case vbKeyX
vp_x = vp_x - 10
Case vbKeyW
vp_z = vp_z + 10
Case vbKeyS
vp_z = vp_z - 10
Case vbKeyE
dslope = dslope + 0.005
Case vbKeyD
dslope = dslope - 0.005
Case vbKeyC
raycast_ang = raycast_ang + 30
Case vbKeyV
raycast_ang = raycast_ang - 30
End Select
End Sub

Private Sub Form_Load()
'Pic.Picture = LoadPicture(App.Path & &quot;\title.gif&quot;)
'Pictxt.Picture = LoadPicture(App.Path & &quot;\texture.gif&quot;)
Pichgt.Picture = LoadPicture(App.Path & &quot;\height.gif&quot;)

'set up the default starting positions
vp_z = 500: vp_x = 200: vp_y = 200
dslope = 0.05
raycast_ang = 100

End Sub

Private Sub Form_Unload(Cancel As Integer)
exitflag = True
End Sub

Private Sub Pic_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
'get the mouse position so you can fly in the correct direction
mx = X
my = Y
End Sub

Private Sub Timer1_Timer()
'This timer is only designed to go off once when the program
'first starts. After that it is disabled, and the tight
'animation loop begins.

Dim u%
Timer1.Enabled = 0

'start the voxel rendering
Do
'reposition based on mouse
vp_x = vp_x - (mx - (Pic.ScaleWidth / 2)) / 10
vp_y = vp_y - (my - (Pic.ScaleHeight / 2)) / 10
'redraw the frame
DrawFrame
Pic.Refresh
'wait for user input
u% = DoEvents

Loop Until exitflag

End Sub
 
Please... tell me that is an overkill...

Thanks for the post... but... that is alot of information to dig through...

I'm looking for about 10-15 lines of code... not 100-150

What is an example of JUST THE CODE FOR THE ACTUAL PICTURE OBJECT...

given a form (Form1)...

The picture object is Form1.Picture

The handle is Form1.Picture.Handle...

what do you do with this handle to get the picture info... the pixel data, height, width (in pixels)...

...and what is the difference in the same procedure with a picturebox? Sometimes... the BASIC things in life are the best...
cheers.gif

or at least the most fun ;-)
-Josh Stribling
 
Ok...

I am getting tired of scrolling over all of that...
these were your 2 post...
.Picture, which is just a wrapper for IPictureDisp/StdPicture, has a property called Handle. This contains a normal GDI handle to the bitmap (what MSDN will refer to as hBmp). So all you need to do is create a memory DC, select the bitmap into it via SelectObject, then grab the basic info you need (a BITMAP) for walking the bitmap by doing a GetObject

SelectObject and GetObject are API calls, so you need a function declaration. You can get it from the VB Tools API Text Viewer utility.
Yes, hWnd is a window handle, and hBmp is a bitmap handle.
A DC is a device context. A memory DC is a device context that is held in memory rather than being associated with a particular device (such as, say, the screen)


O K... Now then...

Now you said &quot;SelectObject and GetObject are API calls...
...You need a Declaration... get it from VB Tools API Text Viewer Util...&quot;

What is the VB Tools API Text Viewer???

What does the handle actually store... a pointer?

Here are the MSDN sitez I found...
SelectObject
and
GetObject

What do I need to look for on these sites??? Sometimes... the BASIC things in life are the best...
cheers.gif

or at least the most fun ;-)
-Josh Stribling
 
The API text viewer is a app that is normally installed into a group right bellow Microsoft Visual Studio 6.0, called strangely enough Microsoft Visual Studio 6.0 Tools

The thing to understand is you may get a handle to the bitmap but if you don't understand that the bitmap has a few different structures then you'll be stuffed. You have mono,16 color, 256 color (paletted), 16 bit, 24 bit and 32 bit. the headers are the same then if your a paletted bitmap you have a palette and the actual image is bottom to top indexes one byte indexes into the palette for the actual color. For the 16,24,and 32 bit you have to look at RGB sets with 16 bit it is 5, 5, 5 bits with 24 it is 8,8,8 bits and with 32 (bare with me if I'm off but its been a while) its 10,10,10 bits.

Theses are DIB (device independant bit maps) what you see on screen is actually a DDB (device dependant bit map).

VB isn't geared for this type of manipulation. And honestly things have changed a bit from the QBASIC day where your pictures where alot less complicated. Hell I didn't even touch on RLE bitmaps thay you may incounter.

10-15 lines of code may not be possible depending on how flexible your application needs to be.

handles are kind of like pointers but when you want to access information the handle gets locked down so it doesn't get moved by the operating system while you are working with it.

Basically doing anything serious with graphics (unless you go through some 3rd party product) in VB is going to take a good understanding on how Windows deals with graphics (GDI)
this means stuff like
Device Context (DC)
Pen
Brushes
Bitmaps
BITBLT
etc
 
Yes, the handle is a pointer to block of memory containing the bits that define the image
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top