Reading POINTs from an image, to draw on another.
Reading POINTs from an image, to draw on another.
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.
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.
Re: Reading POINTs from an image, to draw on another.
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
Re: Reading POINTs from an image, to draw on another.
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).
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
- netmaestro
- PureBasic Bullfrog
- Posts: 8433
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Re: Reading POINTs from an image, to draw on another.
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
Re: Reading POINTs from an image, to draw on another.
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.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()?
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.
Re: Reading POINTs from an image, to draw on another.
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)
Raspberry Pi OS (Arm64)
Re: Reading POINTs from an image, to draw on another.
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.
- FourthStone
- User
- Posts: 26
- Joined: Mon Dec 11, 2017 8:44 am
- Location: Australia
Re: Reading POINTs from an image, to draw on another.
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.
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.
Re: Reading POINTs from an image, to draw on another.
Well, by definition alone, 12800x8000x 4 bytes(32bit compiler integer array) or 8 bytes (64 compiler integer array)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.
= 12800x8000x4=409,600,000 bytes.
Or 12800x8000x8=819,200,000 bytes.
I had defined an integer array in 64 bit PB.
Re: Reading POINTs from an image, to draw on another.
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.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.
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.
- FourthStone
- User
- Posts: 26
- Joined: Mon Dec 11, 2017 8:44 am
- Location: Australia
Re: Reading POINTs from an image, to draw on another.
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.
You could use GrabImage to grab a region and copy it to another working image to process or display.
-
- Addict
- Posts: 1309
- Joined: Fri Aug 28, 2015 6:10 pm
- Location: Portugal
Re: Reading POINTs from an image, to draw on another.
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:-
I have not completed the draw image line as I do not know what you want.
StartDrawing/Stopdrawing only called twice
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
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.
-
- Addict
- Posts: 1309
- Joined: Fri Aug 28, 2015 6:10 pm
- Location: Portugal
Re: Reading POINTs from an image, to draw on another.
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()
ImageID(0) being the original Image
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)
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.
Re: Reading POINTs from an image, to draw on another.
Isnt the DrawingBuffer() for images static?
The device context isnt but the buffer should be.
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
Re: Reading POINTs from an image, to draw on another.
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.