Page 1 of 1
Fast Point and Plot?
Posted: Sat Jul 07, 2007 1:30 am
by CopperCircle
Hi, I am new to Purebasic and its command set, wanted to know what would be the fastest way for me to read a pixel colour from one image, process it and then plot a pixel onto another image?
Do I have to change the drawing output back and forward during the loop? or can I specify an image buffer?
Thanks.
Posted: Sat Jul 07, 2007 2:10 am
by Fluid Byte
The fastet way would be to peek the bitmap data directly from memory but that seems redundant as you can simply copy the image.
Posted: Sat Jul 07, 2007 3:51 am
by netmaestro
The very fastest way is to read and write directly to the image's color bits buffer. This buffer is not something PureBasic provides you with for an image, but the GetObject_() API will give you a pointer to it. (assuming you're on Windows, of course) Here's a little demo prog that illustrates the speed gain. Please disable the debugger to run it (Debugger menu in IDE -> Use Debugger = unselected) for best results:
Code: Select all
; Make a good-sized image to read from
CreateImage(1, 1000,720,32)
StartDrawing(ImageOutput(1))
Box(0,0,1000,720,#White)
Ellipse(500,330,450,300,#Red)
StopDrawing()
; An equal-sized image to write to
CreateImage(2, 1000,720,32)
StartDrawing(ImageOutput(2))
Box(0,0,1000,720,GetSysColor_(#COLOR_BTNFACE))
StopDrawing()
; Make an array to use for transferring colors
Dim colors(1000,720)
; Open a window for display test results
OpenWindow(0,0,0,1000,768,"",$CA0001)
CreateGadgetList(WindowID(0))
ImageGadget(1,0,0,0,0,0)
ButtonGadget(2,330,730,80,20,"Plot")
ButtonGadget(3,420,730,80,20,"API")
ButtonGadget(4,510,730,80,20,"Clear")
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
If EventGadget() = 2
StartDrawing(ImageOutput(1))
For h = 0 To 719
For w = 0 To 999
colors(w,h) = Point(w,h)
Next
Next
StopDrawing()
StartDrawing(ImageOutput(2))
For h=0 To 719
For w = 0 To 999
If colors(w,h) = #Red
Plot(w,h,#Green)
EndIf
Next
Next
StopDrawing()
SetGadgetState(1, ImageID(2))
ElseIf EventGadget() = 3
GetObject_(ImageID(1), SizeOf(BITMAP), @bmp1.BITMAP)
width = bmp1\bmWidth
height = bmp1\bmHeight
widthbytes = bmp1\bmWidthbytes
*colorbits1 = bmp1\bmBits
GetObject_(ImageID(2), SizeOf(BITMAP), @bmp2.BITMAP)
*colorbits2 = bmp2\bmBits
*pxin.LONG
*pxout.LONG
For y=0 To height-1
For x=0 To widthbytes-1 Step 4
*pxin = *colorbits1 + widthbytes * y + x
If *pxin\l = RGB(0,0,255)
*pxout = *colorbits2 + widthbytes * y + x
*pxout\l = RGB(255,0,0)
cc+1
EndIf
Next
Next
DeleteObject_(bmp1)
DeleteObject_(bmp2)
SetGadgetState(1, ImageID(2))
ElseIf EventGadget() = 4
SetGadgetState(1,0)
EndIf
EndSelect
Until Event = #WM_CLOSE
This program takes all the red pixels from the first image and duplicates them on the second image as green for the plot method and blue for the read/write buffer method. You should notice a significant delay when you press the Plot button as the image is processed, while the API button will probably give instant results.
Note: This is a very quick-and-dirty version to demonstrate the speed difference, for an actual program you would likely want to use GetDIBits_() for a more professional approach.
Posted: Sat Jul 07, 2007 5:28 am
by Fluid Byte
netmaestro wrote:The very fastest way is to read and write directly to the image's color bits buffer.
This what I already said and I didn't provided code for a reason. Considering his request he doesn't need this technique at all because he can just copy the image, so it's not worth the hassle. Furthermore hes a beginner so the code is rather useless to him because its pretty advanced. Speaking for myself I can tell that it took me a couple of years of knowledge to understand bitmap manipulation like this. So as I said before, if he has the image already loaded there's no need to plot anything from image to another. He can simply copy it.
Posted: Sat Jul 07, 2007 8:59 am
by Kaeru Gaman
Fluid Byte wrote:netmaestro wrote:The very fastest way is to read and write directly to the image's color bits buffer.
This what I already said and I didn't provided code for a reason. Considering his request he doesn't need this technique at all because he can just copy the image, so it's not worth the hassle. Furthermore hes a beginner so the code is rather useless to him because its pretty advanced. Speaking for myself I can tell that it took me a couple of years of knowledge to understand bitmap manipulation like this. So as I said before, if he has the image already loaded there's no need to plot anything from image to another. He can simply copy it.
I think you shouldn't consider your opponent just dumb, asking such a question just to COPY an image.
he asked for a method to transfer Data from one image to another pixelwise.
that he wants to do some manipulation with the data is implemented.
what would be the fastest way for me to read a pixel colour from one image, process it and then plot a pixel onto another image?
nobody would be so dumb to ask for read/process/plot instead of "how can I copy an image" if he just wanted to copy it.
Posted: Sat Jul 07, 2007 1:56 pm
by netmaestro
Indeed and often a newcomer to PureBasic is someone who's forgotten more programming than I'll ever know and he's looking for the best way to exploit the language as opposed to more simple ways. When one of these guys asks a question, it's often something just like this.
Posted: Sat Jul 07, 2007 3:58 pm
by CopperCircle
Thanks netmaestro, thats just what I was looking for. As you stated I am new to Purebasic but not to programming.
This is for a fast edge detection routine, I already have my app running in Blitz and peek/poke the mem to read/write the bitmaps, but did not know how to achive this in Pure.
I am hoping that Pure is faster on large images so that I can move my project over.
Thanks.
Posted: Tue Jul 10, 2007 7:33 pm
by CopperCircle
Hi, could someone show me how to alter this to work with other image bit depths?
Thanks.
Posted: Tue Jul 10, 2007 7:40 pm
by netmaestro
You need to use the GetDIBits_() API for that. It allows you to create a colorbits buffer in your desired depth. There are several examples of implementing this around the forums if you do a search on it. Once you've done that though, you have to put the headers on it to make a complete image for drawing or saving or sending over the network.
Posted: Tue Jul 10, 2007 8:04 pm
by netmaestro
Actually, come to think of it, there's a simple way that should work:
Code: Select all
CreateImage(#final, ImageWidth(0), ImageHeight(0), 32)
StartDrawing(ImageOutput(#final))
DrawImage(ImageID(0),0,0)
StopDrawing()
which should effectively create a 32-bit image #final from Image 0.
Posted: Sat Jul 14, 2007 5:58 pm
by Trond
Kaeru Gaman wrote:Fluid Byte wrote:netmaestro wrote:The very fastest way is to read and write directly to the image's color bits buffer.
This what I already said and I didn't provided code for a reason. Considering his request he doesn't need this technique at all because he can just copy the image, so it's not worth the hassle. Furthermore hes a beginner so the code is rather useless to him because its pretty advanced. Speaking for myself I can tell that it took me a couple of years of knowledge to understand bitmap manipulation like this. So as I said before, if he has the image already loaded there's no need to plot anything from image to another. He can simply copy it.
I think you shouldn't consider your opponent just dumb, asking such a question just to COPY an image.
he asked for a method to transfer Data from one image to another pixelwise.
that he wants to do some manipulation with the data is implemented.
what would be the fastest way for me to read a pixel colour from one image, process it and then plot a pixel onto another image?
nobody would be so dumb to ask for read/process/plot instead of "how can I copy an image" if he just wanted to copy it.
Personally I'd just copy it, then point/process/plot on the copy of the image.