Reading POINTs from an image, to draw on another.

Just starting out? Need help? Post your questions and find answers here.
matalog
Enthusiast
Enthusiast
Posts: 165
Joined: Tue Sep 05, 2017 10:07 am

Reading POINTs from an image, to draw on another.

Post by matalog »

Is it possible, to say load a previously made image, it does not have to be viewable on screen. Then read POINT colours of that image, and then use that information to draw on another new blank image?

The help file says that POINT will return the colour of a pixel in the current output.

Would it just be a matter of pretending that the source image is the current output (how do you switch to it?) and then reading the POINT, and afterwards switching to the actual output image (again, how do you switch between images?)?

Thanks for any help.
matalog
Enthusiast
Enthusiast
Posts: 165
Joined: Tue Sep 05, 2017 10:07 am

Re: Reading POINTs from an image, to draw on another.

Post by matalog »

I got it, Startdrawing() sets the 'current output'.

Code: Select all

UseJPEGImageDecoder()

OpenWindow(0,0,0,800,560, "ImageCopyCols")
CreateImage(1,800,560)
ImageGadget(0, 0, 0,800, 560, ImageID(1))

LoadImage(0,"F:\PureBasic\502.jpg")
For y=0 To 559
  For x=0 To 799
     StartDrawing(ImageOutput(0))
f=Point(x,y)

StopDrawing()
StartDrawing(ImageOutput(1))
Plot(x,y,f)
StopDrawing()
SetGadgetState(0,ImageID(1))

Next
Next



Repeat
  windowevent=WaitWindowEvent()
  Until windowevent=#PB_Event_CloseWindow
matalog
Enthusiast
Enthusiast
Posts: 165
Joined: Tue Sep 05, 2017 10:07 am

Re: Reading POINTs from an image, to draw on another.

Post by matalog »

So it seems that using Startdrawing() and Stopdrawing() is very slow aswell, not just Setgadgetstate().

If I want to take this a pixel at a time, instead of storing many values in memory, how could I make it faster?

I will eventually be editing the value of f before it is output to image(1).

Code: Select all

UseJPEGImageDecoder()

OpenWindow(0,0,0,800,560, "ImageCopyCols")
CreateImage(1,800,560)
ImageGadget(0, 0, 0,800, 560, ImageID(1))

LoadImage(0,"F:\PureBasic\502.jpg")

For y=0 To 559
  For x=0 To 799
     StartDrawing(ImageOutput(0))
f=Point(x,y)
StopDrawing()

StartDrawing(ImageOutput(1))
Plot(x,y,f)
StopDrawing()

Next
Next

SetGadgetState(0,ImageID(1))

Repeat
  windowevent=WaitWindowEvent()
  Until windowevent=#PB_Event_CloseWindow
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8425
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Reading POINTs from an image, to draw on another.

Post by netmaestro »

For one thing, your StartDrawing() should be done before your For loops to avoid doing it for every pixel. Btw, have you considered GrabImage()?
BERESHEIT
matalog
Enthusiast
Enthusiast
Posts: 165
Joined: Tue Sep 05, 2017 10:07 am

Re: Reading POINTs from an image, to draw on another.

Post by matalog »

netmaestro wrote: Sun Aug 29, 2021 1:49 am For one thing, your StartDrawing() should be done before your For loops to avoid doing it for every pixel. Btw, have you considered GrabImage()?
But, if I want to read each point, then it requires 2 calls of start and stop drawing each loop, one to read each pixel, and one to draw each pixel - assuming that I do not want to use extra memory and store the information as an array.

The use of Start and Stop drawing is very slow here, and I cannot see a way around it, without using an array or some other way of storing to memory.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Reading POINTs from an image, to draw on another.

Post by wilbert »

matalog wrote: Mon Aug 30, 2021 6:31 pmThe use of Start and Stop drawing is very slow here, and I cannot see a way around it, without using an array or some other way of storing to memory.
Is there any reason you don't want to use an array ?
You can free the source image as soon as you have read all pixel colors into an array.
That way it shouldn't use more memory.
Windows (x64)
Raspberry Pi OS (Arm64)
matalog
Enthusiast
Enthusiast
Posts: 165
Joined: Tue Sep 05, 2017 10:07 am

Re: Reading POINTs from an image, to draw on another.

Post by matalog »

wilbert wrote: Mon Aug 30, 2021 7:15 pm
matalog wrote: Mon Aug 30, 2021 6:31 pmThe use of Start and Stop drawing is very slow here, and I cannot see a way around it, without using an array or some other way of storing to memory.
Is there any reason you don't want to use an array ?
You can free the source image as soon as you have read all pixel colors into an array.
That way it shouldn't use more memory.
Well, the source image is 12800x8000 and it seems to use a gigabyte of memory within the program as an array, whereas it is 788kb as a jpg.

If I was able to work at a decent speed from the image itself, instead of an array, I would be saving a gigabyte of memory.
User avatar
FourthStone
User
User
Posts: 26
Joined: Mon Dec 11, 2017 8:44 am
Location: Australia

Re: Reading POINTs from an image, to draw on another.

Post by FourthStone »

I can't imagine loading an image would take up 1gb, counting too many 000's?

The way I read points from images is to load them into memory and directly read the RGB values.

Reading data to an array and processing before outputting to another image is magnitudes faster than trying to read an image pixel by pixel.

Let me know if you want an example.
matalog
Enthusiast
Enthusiast
Posts: 165
Joined: Tue Sep 05, 2017 10:07 am

Re: Reading POINTs from an image, to draw on another.

Post by matalog »

FourthStone wrote: Mon Aug 30, 2021 11:25 pm I can't imagine loading an image would take up 1gb, counting too many 000's?

The way I read points from images is to load them into memory and directly read the RGB values.

Reading data to an array and processing before outputting to another image is magnitudes faster than trying to read an image pixel by pixel.

Let me know if you want an example.
Well, by definition alone, 12800x8000x 4 bytes(32bit compiler integer array) or 8 bytes (64 compiler integer array)

= 12800x8000x4=409,600,000 bytes.
Or 12800x8000x8=819,200,000 bytes.

I had defined an integer array in 64 bit PB.
User avatar
Demivec
Addict
Addict
Posts: 4086
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Reading POINTs from an image, to draw on another.

Post by Demivec »

matalog wrote: Mon Aug 30, 2021 10:07 pmWell, the source image is 12800x8000 and it seems to use a gigabyte of memory within the program as an array, whereas it is 788kb as a jpg.

If I was able to work at a decent speed from the image itself, instead of an array, I would be saving a gigabyte of memory.
Don't mistake the space required to store the compressed image on disk with the memory requirements to view it or operate on it in memory once it's loaded.

I calculate that your image would take at a minimum 12800 x 8000 x 4 bytes [i.e. 32-bits] = 409600000 bytes = 390.625 mb of storage in memory. That doesn't included additional spacing on each line that may be used to pad and align things for faster memory access.

If speed is important and memory is freely available create an array copy of the source image. If speed is not important and memory is scarce then do things pixel by pixel. I would think even if memory was limited you would be better off to create an array big enough to hold the pixel data for one line and just switch back and forth once for each line to be read and plotted. That should speed up things up to 12800 times and would only require 12800 x 4 bytes = 52200 bytes = 50 kb.

Based on the obscurity of your goals it is hard to suggest much more. There may be ways of improving things in other ways outside of the individual read point, plot point cycle.
User avatar
FourthStone
User
User
Posts: 26
Joined: Mon Dec 11, 2017 8:44 am
Location: Australia

Re: Reading POINTs from an image, to draw on another.

Post by FourthStone »

Ah I see the image size has an extra 0 on the end making it rather large.

You could use GrabImage to grab a region and copy it to another working image to process or display.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Reading POINTs from an image, to draw on another.

Post by collectordave »

If I understand correctly you want to read one image, process the individual pixels and write them to a second image.

I would break it down to two steps.

First process the source image colours

Second write the source image to the second image.

Maybe code like this:-

Code: Select all

UseJPEGImageDecoder()

OpenWindow(0,0,0,800,560, "ImageCopyCols")
CreateImage(1,800,560)
ImageGadget(0, 0, 0,800, 560, ImageID(1))

LoadImage(0,"F:\PureBasic\502.jpg")
StartDrawing(ImageOutput(0))
For y=0 To 559
  For x=0 To 799
     f=Point(x,y)
     
     ;Process F here
     
     Plot(x,y,f)
   Next y
 Next x
   
 StopDrawing()

 
;Now you have your original image all processed
;Draw the whole thing to the next image
 
     
StartDrawing(ImageOutput(1))
;DrawImage(ImageID(0),x,y) ;etc.
StopDrawing()
SetGadgetState(0,ImageID(1))

Repeat
  windowevent=WaitWindowEvent()
  Until windowevent=#PB_Event_CloseWindow
I have not completed the draw image line as I do not know what you want.

StartDrawing/Stopdrawing only called twice
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Reading POINTs from an image, to draw on another.

Post by collectordave »

Just another idea.

If the second image is simply the first image processed then you do not need to draw the processed image onto a second image just display the processed image.

Start/Stop Drawing only called once.

Also if the original Image is to be used again so you do not wish to change the original then use CopyImage()

Code: Select all


Global DisplayImage.i

DisplayImage = CopyImage(ImageID(0),#PB_Any)
ImageID(0) being the original Image
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Reading POINTs from an image, to draw on another.

Post by Mijikai »

Isnt the DrawingBuffer() for images static?
The device context isnt but the buffer should be.

Code: Select all

EnableExplicit
 
Procedure.i ImageBuffer(Image.i)
  Structure IMAGE_BUFFER_STRUCT
    size.POINT
    *bits
    pitch.i
    depth.i
  EndStructure
  Protected *imgbuffer.IMAGE_BUFFER_STRUCT
  *imgbuffer = AllocateMemory(SizeOf(IMAGE_BUFFER_STRUCT),#PB_Memory_NoClear)
  If *imgbuffer
    If StartDrawing(ImageOutput(Image))
      *imgbuffer\size\x = OutputWidth()
      *imgbuffer\size\y = OutputHeight()
      *imgbuffer\bits = DrawingBuffer()
      *imgbuffer\pitch = DrawingBufferPitch()
      *imgbuffer\depth = OutputDepth()
      StopDrawing()
      ProcedureReturn *imgbuffer
    EndIf
    FreeMemory(*imgbuffer)
    ProcedureReturn #Null
  EndIf
EndProcedure

Procedure.i ImageCopyColor(*Dst.IMAGE_BUFFER_STRUCT,*Src.IMAGE_BUFFER_STRUCT,X.i,Y.i)
  Protected depth.i
   depth = *Dst\depth >> 3
  *Dst = *Dst\bits + (Y * *Dst\pitch) + (X * depth)
  *Src = *Src\bits + (Y * *Src\pitch) + (X * depth)
  ProcedureReturn CopyMemory(*Src,*Dst,depth)
EndProcedure

Procedure.i Main()
  Protected img_1.i
  Protected img_2.i
  Protected *img_b1.IMAGE_BUFFER_STRUCT
  Protected *img_b2.IMAGE_BUFFER_STRUCT
  Protected x.i
  Protected y.i
  Protected w.i
  Protected h.i
  Protected color.i
  img_1 = CreateImage(#PB_Any,32,32,24,#Red)
  img_2 = CreateImage(#PB_Any,32,32,24,#Blue)
  *img_b1 = ImageBuffer(img_1)
  *img_b2 = ImageBuffer(img_2)
  w = *img_b1\size\x - 5
  h = *img_b1\size\y - 5
  For y = 4 To h
    For x = 4 To w
      ImageCopyColor(*img_b1,*img_b2,x,y)
    Next
  Next
  SaveImage(img_1,"dummy.bmp")
  ProcedureReturn #Null
EndProcedure

Main()

End
User avatar
Demivec
Addict
Addict
Posts: 4086
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Reading POINTs from an image, to draw on another.

Post by Demivec »

Mijikai wrote: Tue Aug 31, 2021 12:47 pm Isnt the DrawingBuffer() for images static?
The device context isnt but the buffer should be.
Fred's response in the thread Fred does image buffer remain static after StopDrawing()?:
StopDrawing() invalidate all drawing operations including DrawingBuffer(). It's not safe to use it after StopDrawing() (it can work by luck, but it's not supported. I will update the doc to make it clear.
PureBasic help file under DrawingBuffer() wrote:Once StopDrawing() has been called, the buffer is invalidated and can no more be used.
Post Reply