Fast Point and Plot?

Just starting out? Need help? Post your questions and find answers here.
CopperCircle
User
User
Posts: 11
Joined: Thu Apr 22, 2004 6:42 pm

Fast Point and Plot?

Post 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.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post 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.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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.
BERESHEIT
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post 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.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post 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.
oh... and have a nice day.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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.
BERESHEIT
CopperCircle
User
User
Posts: 11
Joined: Thu Apr 22, 2004 6:42 pm

Post 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.
CopperCircle
User
User
Posts: 11
Joined: Thu Apr 22, 2004 6:42 pm

Post by CopperCircle »

Hi, could someone show me how to alter this to work with other image bit depths?

Thanks.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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.
BERESHEIT
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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.
BERESHEIT
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post 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.
Post Reply