Go Back  Xtreme Visual Basic Talk > Legacy Visual Basic (VB 4/5/6) > Interface and Graphics > pointer graphics


Reply
 
Thread Tools Display Modes
  #1  
Old 08-23-2005, 01:44 PM
rex64 rex64 is offline
Senior Contributor
 
Join Date: Jul 2003
Posts: 1,171
Default pointer graphics


I attempted to follow the tutorial mentioned here:
http://www.xtremevbtalk.com/t191291.html

I even tried his example, and when you hit the button he is getting the same error as I am getting. Also, on mine, it is not displaying the picture when you first load it, I can not figure out how it is displaying it on his, since it has no form load. Take a look at my project please.

My goal is to make a fast PSET, not necessarily updating an entire BMP at once. I think I will be able to make the modificiations once I figure this out Thanks.
Attached Files
File Type: zip pixle.zip (2.8 KB, 12 views)
Reply With Quote
  #2  
Old 08-23-2005, 07:32 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
Default

Did you read the second post where noi_max fixed the problem.
The code you posted doesn't have that fix in it.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
  #3  
Old 08-23-2005, 09:29 PM
zelg37 zelg37 is offline
Contributor

* Expert *
 
Join Date: Dec 2004
Location: Oregon, USA
Posts: 606
Default Other issues

Quote:
Originally Posted by rex64
Also, on mine, it is not displaying the picture when you first load it, I can not figure out how it is displaying it on his, since it has no form load.
The reason you have no picture is because you did not load one into the picturebox.

In Noi_Max's example he assigned a graphic (of some stairs) to the picturebox by using the picturebox's .Picture property at design time. This is the easy way to get a picture into a picturebox.

However, I noticed you have some File I/O code in you project. Perhaps you were trying to load a picture, but there is nothing that would actually load a picture into a picturebox...code that would look something like this:
Code:
Picture1.Picture = LoadPicture("C:\MyImage.bmp")
Unless there is an image inside the Picture control then this line will not have any picture information to transfer into the bitmap structure "bmp":
Code:
GetObjectAPI Picture1.Picture, Len(bmp), bmp
..and all other DMA code (involving the use of CopyMemory and VarPtr APIs) after that will be invalidated (not work also).

I have attached a code corrected working version of Noi_Max's demo for you to play around with. If you've read through the Lucky's tutorial you know that using Direct Memory Access (in place of PSet) will drastically speed up your pixel plotting...and even though it can be a little tricky, it's definitely worth the extra effort.
Attached Files
File Type: zip PixelPlot_working_demo_with_corrections_made.zip (6.6 KB, 11 views)
Reply With Quote
  #4  
Old 08-24-2005, 09:48 AM
rex64 rex64 is offline
Senior Contributor
 
Join Date: Jul 2003
Posts: 1,171
Default loading picture into picture box

I would like to be able to load a picture into a picture box. I am getting an error "cant assign to array" as you can see in the comments in the code. I would like to be able to load serveral pictures into a picture box one at a time, or if I need to maybe to load into a buffer first. Let me know what you think, and how to fix my problem. I have a feeling I need another data type in here or something. THanks.
Code:
Private Sub loadImage(pictureToDisplay, pic() As Byte) 'Dim pic() As Byte Dim sa As SAFEARRAY2D Dim r As Long, g As Long, b As Long Dim i As Long, j As Long GetObjectAPI pictureToDisplay.picture, Len(bmp), bmp 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(pic), VarPtr(sa), 4 For i = 0 To UBound(pic, 1) For j = 0 To UBound(pic, 2) pic(i, j) = 255 - pic(i, j) Next j Next i CopyMemory ByVal VarPtrArray(pic), 0&, 4 pictureToDisplay.Refresh End Sub Private Sub Command2_Click() Dim pic1() As Byte pic1 = LoadPicture("C:\windows\Soap Bubbles.bmp") 'cant assign to array loadImage pic1 End Sub
Reply With Quote
  #5  
Old 08-24-2005, 08:11 PM
zelg37 zelg37 is offline
Contributor

* Expert *
 
Join Date: Dec 2004
Location: Oregon, USA
Posts: 606
Default Loading Pictures 101

Actually, I believe this line:
Code:
pic1 = LoadPicture("C:\windows\Soap Bubbles.bmp")
should probably be:
Code:
pic1.picture = LoadPicture("C:\windows\Soap Bubbles.bmp")
Reply With Quote
  #6  
Old 08-24-2005, 08:24 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
Default

If you want to assign the picture to a picturebox, then you should assign it to a picturebox, not try to load it into a byte array, which doesn't make any sense.
What the DMA code will do is size a byte array, and point it at your picture, and you can then manipulate the picture by manipulating the byte array.
So, your command2_Click should just load the picture into a picturebox and pass that picturebox to your loadImage routine (uncomment the local declaration of pic in that routine, and remove the second parameter from the sub definition (the byte array)).
Code:
Private Sub Command2_Click() Picture1 = LoadPicture("D:\windows\Soap Bubbles.bmp") 'cant assign to array loadImage Picture1 End Sub

Now, a complication that you'll see if you run this code (and the same with the original), is that the pic(i,j) = 255-pic(i,j) line is suppose to invert the colors.
Well, it probably would on a 15/16 or 24 or 32 bit bitmap.
But the example code, and Soap Bubbles.bmp are both 8 bit bitmaps, which means they have a palette and the bytes are indices into that palette to select the color to be displayed.
When you invert the bytes in the array, the pixels just turn black because the indicices probably do not have a color defined at that index.
You need to find and load a higher pixel depth picture.
The commented out code expects a 24 bit pixel depth (note the Step 3 in the loop), so try loading a 24-bit color bmp into the picturebox.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
  #7  
Old 08-26-2005, 08:44 AM
rex64 rex64 is offline
Senior Contributor
 
Join Date: Jul 2003
Posts: 1,171
Default

Here is my attempt to copy picToAdd into pictureToDisplay. However, when I run this, nothing happens. Any suggestions?

Also, I do not understand this code:
GetObjectAPI pictureToDisplay.Picture, Len(bmp), bmp

and what is all this bounds stuff:
With sa2
.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
Code:
Private Sub loadImage(pictureToDisplay, picToAdd) Dim pic() As Byte Dim pic2() As Byte Dim sa As SAFEARRAY2D Dim sa2 As SAFEARRAY2D Dim r As Long, g As Long, b As Long Dim i As Long, j As Long GetObjectAPI pictureToDisplay.Picture, Len(bmp), bmp GetObjectAPI picToAdd.Picture, Len(bmp), bmp 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 With sa2 .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(pic), VarPtr(sa), 4 CopyMemory ByVal VarPtrArray(pic2), VarPtr(sa2), 4 For i = 0 To UBound(pic, 1) For j = 0 To UBound(pic, 2) pic(i, j) = pic2(i, j) Next j Next i 'For i = 0 To UBound(pic, 1) ' For j = 0 To UBound(pic, 2) ' pic(i, j) = 255 - pic(i, j) ' Next j 'Next i CopyMemory ByVal VarPtrArray(pic), 0&, 4 CopyMemory ByVal VarPtrArray(pic2), 0&, 4 pictureToDisplay.Refresh picToAdd.Refresh End Sub
Reply With Quote
  #8  
Old 08-26-2005, 08:05 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
Default

You want to get information about a bitmap, so you define a structure to hold the information.
You then call an API function to retrieve the information about the bitmap.
So, after you call
GetObjectAPI pictureToDisplay.Picture, Len(bmp), bmp

bmp will contain information about the bitmap, i.e. the height, the width in bytes, the address of the data (the bits of the bitmap), etc.

You then use that information to plug into the definition of an array.

An array in Visual Basic is a structure with fields that describe the number of dimensions in the array, the lower bounds of each of those dimensions, the number of elements in each dimension and a pointer to where the elements (the data) of the array start.

You are updating the information in the array definition to match the dimensions of your picture, using the information returned by the API call. You are also setting the pointer that points to where the array data should be, to the area where you bitmap data is.
That way when you change an array elements value, you are really changing a pixel (or part of a pixel) in your bitmap since your array points to the same memory.

So, if you look at your code you should see an obvious problem.
You get the information for once picture into bmp by calling the API function, but then you clobber that information by getting the information for the second picture into bmp by calling the API function again.
You then copy information from bmp into both your array descriptions, so both arrays will be pointing to the same, second picture.

You need to get the information from one picture, then update the array you want to point to that picture.
Then get the information from the second picture, and update the array you want to point to that picture.

For some possible example code doing DMA access on a couple of differenet pictures, you might want to look at some of the code from this thread.
Probably starting with the code in Post #19 from zelg37, and variations in Post #23 and #25.
Post 25 has a large bitmap in it so is a bit larger download than you might want to do.
None of the code in the thread are finished products. I think there are still glitches when can cause an occasional crash, but I know that the code in the 3 posts mentioned are doing DMA access on two pictures at the same time, so could be a possible reference to help you along.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 08-26-2005 at 08:28 PM.
Reply With Quote
  #9  
Old 08-31-2005, 09:31 AM
rex64 rex64 is offline
Senior Contributor
 
Join Date: Jul 2003
Posts: 1,171
Default

I got it to work, kinda. It copies the pictures, but the colors are all off. It is like it has to use the pallet from the origional. Any suggestions?
Code:
Private Sub loadImage(pictureToDisplay, picToAdd) Dim pic() As Byte Dim pic2() As Byte Dim sa As SAFEARRAY2D Dim sa2 As SAFEARRAY2D Dim r As Long, g As Long, b As Long Dim i As Long, j As Long GetObjectAPI pictureToDisplay.Picture, Len(bmp), bmp 'GetObjectAPI picToAdd.Picture, Len(bmp), bmp 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 GetObjectAPI picToAdd.Picture, Len(bmp), bmp With sa2 .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(pic), VarPtr(sa), 4 CopyMemory ByVal VarPtrArray(pic2), VarPtr(sa2), 4 For i = 0 To UBound(pic, 1) For j = 0 To UBound(pic, 2) pic(i, j) = pic2(i, j) Next j Next i 'For i = 0 To UBound(pic, 1) ' For j = 0 To UBound(pic, 2) ' pic(i, j) = 255 - pic(i, j) ' Next j 'Next i CopyMemory ByVal VarPtrArray(pic), 0&, 4 CopyMemory ByVal VarPtrArray(pic2), 0&, 4 pictureToDisplay.Refresh picToAdd.Refresh End Sub

Also, can you explain their code here a little bit:
Code:
xd = (x - cx) * 3 'using 24 bit pictures so 3 bytes per pixel yd = tImage.Bounds(0).cElements - cy - y For ys = 0 To tMask.Bounds(0).cElements - 1 For xs = 0 To tMask.Bounds(1).cElements - 1 xp = xd + xs 'Do bounds checking on the array yp = yd + ys If xp >= 0 And xp < tImage.Bounds(1).cElements And _ yp >= 0 And yp < tImage.Bounds(0).cElements Then If bMask(xs, ys) > bImage(xp, yp) Then bImage(xp, yp) = bMask(xs, ys) End If End If Next Next
Reply With Quote
  #10  
Old 09-02-2005, 11:10 AM
rex64 rex64 is offline
Senior Contributor
 
Join Date: Jul 2003
Posts: 1,171
Default

Any ideas on what I should do about the problems with the last post? Please let me know what I should try, or if you have any ideas for code improvement. Thanks.
Reply With Quote
  #11  
Old 09-04-2005, 08:53 PM
rex64 rex64 is offline
Senior Contributor
 
Join Date: Jul 2003
Posts: 1,171
Default *bump*

*bump*
Reply With Quote
  #12  
Old 09-05-2005, 08:54 AM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
Default

Easiest thing to do would be to load a 24-bit bitmap, rather than an 8-bit bitmap.
I didn't respond before because I haven't worked enough with 8-bit bitmaps to know whether you can just create a compatible bit-map and inherit the palette that way, or whether you will have to use API calls to extract the palette from the one bitmap and write it back to the other.
The DMA access itself will only be accessing the pixel data, not the palette data.
If you use a 24-bit bitmap, which is what the code in the example was written for, then you shouldn't have the problems you're having.

As for the second piece of code, that is from another situation, and despite the names, is really is really trying to create an mask to be used in an Alpha Blended situation.
That is only one piece of the process.
In that situation, each byte of the 3 colors of the pixels( red, green, blue) hold the same value (the pixels are gray scaled). As the smaller bitmap, with a smooth shaded circular area, is moved across a larger bitmap (which was initially a black background) the colors for each pixel are copied from the smaller bitmap to the larger bitmap if the color is brighter (closer to white) than the pixel that is already there.
So as you moved the mouse back and forth, eventually the whole picture would be white. I don't have time to go into more details at the moment, so will check back later.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
  #13  
Old 09-06-2005, 10:00 AM
rex64 rex64 is offline
Senior Contributor
 
Join Date: Jul 2003
Posts: 1,171
Default

I made 3 new functions to try and do the basic image changes. However, I am not sure that any of them are right. I am having trouble testing them and figureing out what is wrong with them.

For example, I am not sure how to apply 3 colors to one var:
theArray(x, y) = red & green & blue '255 - pic(i, j)

Also, the other 2 functions do not seem to be working correctly. The updateImage does not do anything for some reason, and the loadImageToArray comes up with an error on this for some reason (must specify index for object array):
pic(i, j) = picToAdd(i, j)
Code:
Private Sub changePixel(theArray() As Byte, x As Integer, y As Integer, red As Long, green As Long, blue As Long) theArray(x, y) = red & green & blue '255 - pic(i, j) End Sub Private Sub updateImage(pic() As Byte, picctureToDisplay) Dim sa As SAFEARRAY2D GetObjectAPI pictureToDisplay.Picture, Len(bmp), bmp 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(pic), VarPtr(sa), 4 CopyMemory ByVal VarPtrArray(pic), 0&, 4 pictureToDisplay.Refresh End Sub Private Sub loadImageToArray(pic() As Byte, picToAdd) Dim sa As SAFEARRAY2D GetObjectAPI picToAdd.Picture, Len(bmp), bmp 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(pic), VarPtr(sa), 4 For i = 0 To UBound(pic, 1) For j = 0 To UBound(pic, 2) pic(i, j) = picToAdd(i, j) Next j Next i End Sub Private Sub Command2_Click() 'Dim pic1 As Picture 'pic1.Picture = LoadPicture("C:\windows\Soap Bubbles.bmp") 'cant assign to array Dim pic() As Byte loadImage Picture1, Picture2 loadImageToArray pic, Picture1 changePixel pic, 5, 5, 255, 255, 255 updateImage pic, Picture2 End Sub
Reply With Quote
  #14  
Old 09-09-2005, 09:11 AM
rex64 rex64 is offline
Senior Contributor
 
Join Date: Jul 2003
Posts: 1,171
Default

I feel like I am asking dumb questions. Is there an example code that you have that specifically does more like the questions I am asking? The examples I saw did strange things like invert colors and copy an entire image, instead of placing it inside the other image. Anyways, please see the last post and let me know the best way to procede.
Reply With Quote
  #15  
Old 09-09-2005, 10:59 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
Default

I don't know. If you want to provide a faster Pset you might just want to stick with using the API SetPixel function.
A picturebox has essentially three graphical contexts, and all three can be holding different graphical elements which are combined in different situations to present the final image that you see on the screen.

We can consider the three contexts as three layers, although that is a simplification of the true nature, but for this post, we'll go with it.
The top layer is the Screen Context.
If you don't have AutoRedraw set to True on the picturebox, then the normal drawing commands (VB and API functions using the .hDC of the picturebox) draw directly to the screen area "on top of" the picturebox.
These graphics are easily wiped out by dragging another window across the picturebox, since the screen is shared by all windows.

The second layer is the .Image context.
This is where VB and the API draws if the .Autoredraw property is set to True.
The drawing area is actually a buffer in memory and the results of drawing into this buffer have to be refreshed to the screen to be seen.
If you are using VB drawing commands, then VB knows that the screen and the buffer are out of sync, and will refresh the screen from the buffer whenever it is allowed to process events (usually whenever you exit the sub that is doing the drawing).
If you are only using API functions to draw then the buffer is being updated without VB's knowledge so it is up to you to call the .Refresh method of the picturebox when you want the buffer to be flushed to the screen.
An advantage to using AutoRedraw is that since the graphics are in a memory buffer, then when a window is dragged across the picturebox, VB will automatically restore the screen image from the memory buffer so the graphics are not wiped out.

The third layer is the .Picture context.
The .Picture context's purpose is to be a background.
None of the normal drawing commands can draw on the picture.
When you call the .Cls method of the picturebox (or when you initially load a picture into the picturebox), the picture is converted from whatever format it is in (in the .Picture context, i.e. 8-bit, 15-bit, 24-bit or other) to a screen color depth bitmap and copied to the .Image context (if AutoRedraw is True) or to the Screen (if AutoRedraw is False).
Now there is a lot of different scenarios about when the .Picture background, is converted and copied to the .Image or Screen when the .Refresh method is called.
The DMA method in the code you are referencing, in case you haven't made the connection, is not changing the pixels in the normal drawing areas (at least not directly). It is changing the pixels in the .Picture context (the background image of the picturebox).
If you plan on implementing a fast Pset type function using DMA access, then you need to know that you will need to provide all the drawing functions that you will want, since you are manipulating the background picture, which the normal drawing functions can't reach.
Also, this DMA code depends on using the .Refresh method to copy the graphics from the .Picture context to the other contexts.
If AutoRedraw is set True, then this will only work as long as you have not done any normal drawing (like circle, lines or print) in the picturebox. As soon as you do your first normal drawing command, the .Refresh method will no longer update the display buffers (.Image and Screen contexts) from the .Picture context because that would wipeout your drawing.
The only way to get it working again is to issue the Cls method of the picturebox, which will flush the Picture to the display buffers, and then the .Refresh method will continue to flush the Picture to the display each call (so you can see any manipulations you are doing to the pixels in the bitmap) as long as you don't do any normal drawing commands.
If AutoRedraw is not set to True (and you haven't done any normal drawing while it was set to True), then you don't have the same problem. Any normal drawing you do is only done to the screen, and as soon as the DMA code does a .Refresh your drawing is wiped out (replaced) by the contents of the .Picture context.

Ok, all that said, if you want to modify the colors of pixels in the background picture using the DMA method, then note that for a 24-bit picture, you have three bytes, one for each color gun of the monitor (Red, Green and Blue).
So to change the color of one pixel, you need to calculate the offset of the first byte of the pixel, and then change 3 bytes at that location (in your array, once you've calculated the proper x, then you would change bytes theArray(x, y), theArray(x+1,y) and theArray(x+2,y).
Of course the existing code you have above is nowhere near what you need, so my reference to theArray from your code is for illustration, not a fix.
I don't have time to try to fix, or give an example of something along the lines of what you want.
You did quote part of some code from another post I was involved in, so I guess I could make some minor modifications to a version of that code to at least illustrate changing only one of the 3 bytes at a time, so that you are only setting the Red, Green or Blue portion of the pixel as you drag the mouse. That way, if you are drawing the Green portion of the pixel and you drag across an area already drawn in Red, you should see the pixels change to yellow as you add green to the red.

So, I just downloaded the code from the other thread, and modified the form to add 3 radio buttons to select either Red, Green, or Blue.
Then in the code which updated the big picture's bytes from the smaller picture's bytes by copying byte values from one to the other (if the byte is larger than the value already there), add a check and only update one of the 3 byte in the triplet rather than all the bytes.

The parts that changed
Code:
Dim colorByte As Long 'Holds 0,1 or 2 to identify which byte to modify based on Color Radio Button selection Private Sub optColor_Click(Index As Integer) colorByte = Index 'set colorByte based on which option selected End Sub 'in the MouseMove routine ' If the source byte value is greater than the destination byte value ' Set r to 0,1 or 2 based on which byte we're on (3 bytes per pixel) ' If this byte controls the color of the pixel selected by the radio button then copy the value from the source bitmap to the destination bitmap If bMask(xs, ys) > bImage(xp, yp) Then r = xs Mod 3 If colorByte = r Then bImage(xp, yp) = bMask(xs, ys) End If

The program comes preloaded with a small circular 24-bit grayscaled image (each of the red,green, and blue byte values are the same for a given pixel).
It is also preloaded with a larger 24-bit picture which is all black (all the bytes are 0 to start with).
As you drag the mouse across the larger picture, the rectangle of pixels from the source, is compared to the rectangle of pixels in the destination and if the destination value is less, the source byte is copied to the destination byte.
Bitmaps in memory go from the bottom of the picturebox to the top, so there is some extra calculations going on to adjust for that when yd is calculated.
Attached Files
File Type: zip DMAgraphic2.zip (13.3 KB, 8 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
  #16  
Old 09-10-2005, 01:12 PM
rex64 rex64 is offline
Senior Contributor
 
Join Date: Jul 2003
Posts: 1,171
Default

Let me try and get these things working one function at a time if I need to. I think I am starting to understand.

In the array, each pixle is represented by 3 bytes. So, if you wanted to modify pixle 100,100 would that actually be 300,300, and 301, 300 and 302, 300 in the array?

Would the function look something like this? I dont see why it would be much more complicated than this. I will have a seperate update/refresh function that will upload the array to the picture.
Code:
Private Sub changePixel(theArray() As Byte, x As Integer, y As Integer, red As Long, green As Long, blue As Long) theRealX=x*3 theRealY=y*3 theArray(theRealX, theRealY) = red theArray(theRealX+1, theRealY) = green theArray(theRealX+2, theRealY) = blue End Sub
Reply With Quote
  #17  
Old 09-10-2005, 08:16 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
Default

No, 100,100 wouldn't be 300,300 unless the pixel was represented by 9 bytes (3x3).
It is only 3 bytes.
If you print out the values, or set a breakpoint, you would see that on the 100x100 pixel bitmap (picture2.Picture which is accessed through array bMask) has bp.bmHeight = 100 and bmp.bmWidthBytes = 300.
So the bMask array ends up being dimensioned bMask(0 to 299, 0 to 99) of Byte.
theRealX = x*3 but
theRealY = y
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
  #18  
Old 09-12-2005, 01:07 PM
rex64 rex64 is offline
Senior Contributor
 
Join Date: Jul 2003
Posts: 1,171
Default loadImageToArray

Is this correct? It does not seem to be working. I dont think it is loading anything into pic.
Code:
Private Sub loadImageToArray(pic() As Byte, picToAdd) Dim sa As SAFEARRAY2D GetObjectAPI picToAdd.Picture, Len(bmp), bmp 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(pic), VarPtr(sa), 4 'For i = 0 To UBound(pic, 1) ' For j = 0 To UBound(pic, 2) ' pic(i, j) = picToAdd(i, j) ' Next j 'Next i End Sub
Reply With Quote
  #19  
Old 09-12-2005, 10:27 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
Default

What do you expect the code to do?
What is picToAdd?
What is pic()?

Perhaps you should look into the API function GetBitmapBits to copy the bits from a bitmap into an array. Once you've modify the values in the array you can use SetBitmapBits to copy the array back to the bitmap.

Using DMA access to get to a picture is fairly delicate, and it doesn't take much to blow Visual Basic out of the water when you're using it, so you really shouldn't stray far from the examples given.
When you use DMA access, you are not copying the bitmap data to an array.
You are creating an array descriptor that will access the same amount of memory as an existing picture, and setting the address of the picture data in that descriptor. So the picture you are trying to access with the array must already exist.
Once you create the array descriptor, you copy the address of that descriptor to the address of your dynamic uninitialized array, so now it appears initialized and is pointing to the same memory where your picture is located. Now when VB writes or reads from the array, it is accessing the memory used by your picture.
Before you leave the subroutine, you need to clean up the remove the pointer to the descriptor by resetting the array pointer to 0, otherwise, when you exit the subroutine VB will try to clean up and deallocate the space used by the local array, and you will probably soon crash when VB sticks something else in that memory latter and it is still allocated to your picture (and your code again, if you come back in).
You show pic() being passed in, but that isn't likely to work because the address you are putting into it is local to this routine, and will go away when you exit, so you will have a bad reference in pic() when you leave this routine, leading to more trouble.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
 
 
-->