Page 1 of 2
drawing
Posted: Sun Mar 13, 2022 7:21 pm
by ZX80
Hello, all.
I'm looking for a way to copy the raw data memory buffer into the context StartDrawing(ImageOutput(ImageNr)). Is it possible? Something like BitBlt_
Before copying, I also wanted to clarify two points. Can I change the size of the StartDrawing(ImageOutput(ImageNr)) context buffer? Is it possible to select the buffer area/address where to copy the raw-data?
added:
I understand that the buffer size can be changed with
Code: Select all
hImage = CreateImage(ImageNr, Width, Height)
By resizing the canvas, you are changing the size of the buffer. Okay.
With
you get the address of the buffer. Okay.
But how can I copy a piece of my raw-data to an arbitrary place there?
Re: drawing
Posted: Sun Mar 13, 2022 8:07 pm
by STARGÅTE
The context buffer can be received with
DrawingBuffer().
You can read and write in it.
Additional commands like
DrawingBufferPitch() or
DrawingBufferPixelFormat() give you more informations about the buffer, like the buffer pitch and the pixel format.
Re: drawing
Posted: Sun Mar 13, 2022 8:20 pm
by ZX80
Good time, STARGÅTE.
Oh, while I completed my first post, you already answered. Thank you.
Yes, I know about these commands, thanks.
I'm guessing, I need to describe my task in more detail. I will try...
added:
I have to show it in code. I'm sorry, but I need to think. Although I have the base. Can we leave it until tomorrow? Now I have midnight (and another 30 minutes). Thank you.
Re: drawing
Posted: Sun Mar 13, 2022 8:28 pm
by STARGÅTE
ZX80 wrote: Sun Mar 13, 2022 7:21 pm
But how can I copy a piece of my raw-data to an arbitrary place there?
If the pixel format and the pitch matches, you can use CopyMemory(*RawData, DrawingBuffer() + Offset, Size), while *RawData is you buffer, Offset is an arbitrary offset in the drawing buffer and Size the length of the copied data.
If the pixel format or the pitch do not match, the result is just nonsense.
Re: drawing
Posted: Sun Mar 13, 2022 8:36 pm
by ZX80
STARGÅTE,
thanks again for your help. This is useful. I'll try tomorrow and write a report here. I have updated my previous post. Again, I'm sorry I can't continue now. Didn't expect such a quick response.
Re: drawing
Posted: Mon Mar 14, 2022 9:19 am
by ZX80
Hello, all.
STARGÅTE, are you still here?
This is the first approximation. Hastily and dirty (not clean). But this example shows what I need. There is something wrong with my math. Could you take a look? I am attaching a
screenshot of the problem.
That's what it's about:
Code: Select all
#max_number_of_frames = 5
Global.i FrameSize, *mem
Procedure MakeDesktopScreenshot(ImageNr, x, y, Width, Height, SnapshotNr)
Protected hImage, hDC, hWnd, DeskDC
Protected *Buffer, *mem_ptr, Pitch
hImage = CreateImage(ImageNr, Width, Height)
If hImage
hDC = StartDrawing(ImageOutput(ImageNr))
If hDC
hWnd=GetDesktopWindow_()
DeskDC = GetDC_(hWnd)
BitBlt_(hDC, 0, 0, Width, Height, DeskDC, x, y, #SRCCOPY)
*Buffer = DrawingBuffer()
If SnapshotNr = 1
Pitch = DrawingBufferPitch()
FrameSize = Pitch * Height ;ImageHeight(ImageNr)
*mem = AllocateMemory(FrameSize * #max_number_of_frames)
EndIf
If *mem = 0
hImage = 0
Else
*mem_ptr = *mem + (FrameSize * (#max_number_of_frames - SnapshotNr))
CopyMemory(*Buffer, *mem_ptr, FrameSize)
EndIf
StopDrawing()
ReleaseDC_(hWnd, DeskDC)
Else
FreeImage(ImageNr)
hImage = 0
EndIf
EndIf
ProcedureReturn hImage
EndProcedure
Procedure CreateFinalizeSnapshot(ImageNr, Width, Height, SnapshotNr)
Protected *mem_ptr, hImage, hDC
hImage = CreateImage(ImageNr, Width, Height * SnapshotNr)
If hImage
hDC = StartDrawing(ImageOutput(ImageNr))
If hDC
*mem_ptr = *mem + (FrameSize * (#max_number_of_frames - SnapshotNr))
CopyMemory(*mem_ptr, DrawingBuffer(), FrameSize * SnapshotNr)
StopDrawing()
Else
FreeImage(ImageNr)
hImage = 0
EndIf
EndIf
ProcedureReturn hImage
EndProcedure
#const_x = 264
#const_y = 183
#const_w = 1322
#const_h = 655
UsePNGImageEncoder()
Sleep_(1500)
If MakeDesktopScreenshot(0, #const_x, #const_y, #const_w, #const_h, 1)
Beep_(2000, 400)
Sleep_(5000) ;time to change screen
If MakeDesktopScreenshot(0, #const_x, #const_y, #const_w, #const_h, 2)
If CreateFinalizeSnapshot(0, #const_w, #const_h, 2)
SaveImage(0, "c:\-\-\test.png", #PB_ImagePlugin_PNG)
EndIf
EndIf
EndIf
If *mem
FreeMemory(*mem)
EndIf
P.S. This is not my ultimate goal. This is just the first step. I need more time to think about how to take the next step. I understand what needs to be done, but I don't know how. But first I need to fix my math. Please, HELP!
Thank you in advance.
P.S.2. Lines 33 and 34 in the picture are the border where the two frames "meet". It does not depend on me. There was enough time to scroll through the text.
Re: drawing
Posted: Tue Mar 15, 2022 6:49 pm
by ZX80
Hello, all.
If someone has time, please take a look at the code. What's wrong here? I almost always get 'Addr' equal to zero. Why?
Only if I scroll the text a few lines do I get the address. But now I have almost 33 lines in the frame. And if you scroll the text by 30 lines, it no longer works.
Is my math really wrong? I just don't see where?
Code: Select all
#max_number_of_frames = 5
#overlap_lines = 3
Global.i FrameSize, *mem
Global.i SearchPatternSize, *SearchPattern
Procedure FindOverlap(*buff)
Protected i, n, result
n = FrameSize - SearchPatternSize
For i = 0 To n
If CompareMemory(*buff+i, *SearchPattern, SearchPatternSize)
result = *buff+i
Break
EndIf
Next i
ProcedureReturn result
EndProcedure
Procedure MakeDesktopScreenshot(ImageNr, x, y, Width, Height, SnapshotNr)
Protected hImage, hDC, hWnd, DeskDC, Addr
Protected *Buffer, *mem_ptr, Pitch
hImage = CreateImage(ImageNr, Width, Height)
If hImage
hDC = StartDrawing(ImageOutput(ImageNr))
If hDC
hWnd=GetDesktopWindow_()
DeskDC = GetDC_(hWnd)
BitBlt_(hDC, 0, 0, Width, Height, DeskDC, x, y, #SRCCOPY)
*Buffer = DrawingBuffer()
If SnapshotNr = 1
Pitch = DrawingBufferPitch()
FrameSize = Pitch * Height ;ImageHeight(ImageNr)
*mem = AllocateMemory(FrameSize * #max_number_of_frames)
SearchPatternSize = Pitch * #overlap_lines
*SearchPattern = AllocateMemory(SearchPatternSize)
EndIf
If *mem = 0 Or *SearchPattern = 0
hImage = 0
Else
If SnapshotNr = 1
*mem_ptr = *mem + (FrameSize * (#max_number_of_frames - SnapshotNr))
CopyMemory(*Buffer, *mem_ptr, FrameSize)
CopyMemory(*mem_ptr + FrameSize - SearchPatternSize, *SearchPattern, SearchPatternSize)
Else
Addr = FindOverlap(*Buffer)
Debug Addr
EndIf
EndIf
StopDrawing()
ReleaseDC_(hWnd, DeskDC)
Else
FreeImage(ImageNr)
hImage = 0
EndIf
EndIf
ProcedureReturn hImage
EndProcedure
#const_x = 264
#const_y = 183
#const_w = 1322
#const_h = 655
Sleep_(1500)
If MakeDesktopScreenshot(0, #const_x, #const_y, #const_w, #const_h, 1)
Beep_(2000, 400)
Sleep_(5000) ;time to change frame
If MakeDesktopScreenshot(0, #const_x, #const_y, #const_w, #const_h, 2)
; to do
EndIf
EndIf
If *mem
FreeMemory(*mem)
EndIf
If *SearchPattern
FreeMemory(*SearchPattern)
EndIf
Re: drawing
Posted: Tue Mar 15, 2022 7:26 pm
by STARGÅTE
I don't understand, what you want to try.
If you just want to draw multiple images into a larger one, just create multiple images (screenshots) and then use DrawImage() to draw them all into the larger one.
Using the DrawingBuffer can make a lot of trouble, if the buffer is Y-flipped (#PB_PixelFormat_ReversedY) or the pitches do not match.
Re: drawing
Posted: Tue Mar 15, 2022 7:49 pm
by ZX80
Good time,
STARGÅTE.
If you just want to draw multiple images into a larger one, just create multiple images (screenshots) and then use DrawImage() to draw them all into the larger one.
This is not exactly what I need. I'm trying to merge two frames into one. To do this, I have to figure out where the border is. The second frame is taken with a small allowance. That is, the beginning of the second frame must contain a part from the end of the first frame. Overlay / overlap. I decided that three lines would be enough to reliably determine the boundary (no mistake). As a result, I try to glue or stitch two frames. No seams. This is something like a panorama, only vertical. This idea came to me from the 'HyperSnap' program.
Using the DrawingBuffer can make a lot of trouble, if the buffer is Y-flipped (#PB_PixelFormat_ReversedY) or the pitches do not match.
Do not worry. It's all right here. All frames will be of the same specified size and format. I just have problems with memory lookup, but I don't understand why?
added:
I don't want to save two separate files to disk before gluing them together to then once again save the resulting snapshot to disk. I prefer to work with raw data.
Re: drawing
Posted: Tue Mar 15, 2022 9:49 pm
by JHPJHP
Hi ZX80,
It seems like you may already have a viable solution, but I'll post this anyways...
Stitch Images: SIFT.
NOTE: The free version may not fit your preference of working with raw data.
The free download includes both DLL and EXE examples that accomplish the same result, stitching images together.
In order to have a near seamless stitch, a Laplacian blending algorithm is applied during the stitch process.
While the free version cannot be modified from a horizontal stitch, it should be easy enough to first rotate the two images, stitch them together, then rotate the newly created stitched image to vertical.
Again, just a thought

Re: drawing
Posted: Wed Mar 16, 2022 8:53 am
by ZX80
Hello, dear JHPJHP.
Thanks for your reply. I really appreciate it.
Okay. Yes, it requires more work and external additional files. However, I checked your version but couldn't get it to work. I downloaded the free version from your site. Every time after running your code I get the same message: "icon file not found". And no matter what "StitchImages_DLL.pb", what "StitchImages_EXE.pb".
In fact, the task is simple: find given pattern in the buffer. And it works well with text('FindOverlap' procedure), I tested it. Why there are problems with snapshot, I do not understand. Only in this case, the pattern is not text, but a set of pixels. But if we are looking for pixels or text, what does it matter? In the end, it's just a part of memory.
As I said earlier, these are two pictures not from different places. This is just a screenshot of the same screen, but shifted one frame down. There is no need of complicated calculations, but simple memory search. Actually, it's absolutely clear even without any complex calculations. Therefore, I think your approach in this case is redundant and unnecessarily complicated. Sorry.
Thanks again for your answer.
Re: drawing
Posted: Wed Mar 16, 2022 11:32 am
by Demivec
ZX80 wrote: Tue Mar 15, 2022 6:49 pm
Hello, all.
If someone has time, please take a look at the code. What's wrong here? I almost always get 'Addr' equal to zero. Why?
Only if I scroll the text a few lines do I get the address. But now I have almost 33 lines in the frame. And if you scroll the text by 30 lines, it no longer works.
Is my math really wrong? I just don't see where?
In examining but not testing your code I see several potential problems. In looking at the FindOverlap() procedure, I've made comments in the procedure of some concerns:
Code: Select all
Procedure FindOverlap(*buff)
Protected i, n, result
n = FrameSize - SearchPatternSize
;Why advance the the search point byte by byte instead of line by line?
For i = 0 To n
:The search pattern size includes possible padding
:bytes (as part of the Pitch) which are undefined and
;never guaranteed to match even though the pixel
;data portions do.
;SearchPatternSize = Pitch * #overlap_lines
If CompareMemory(*buff+i, *SearchPattern, SearchPatternSize)
result = *buff+i
Break
EndIf
Next i
ProcedureReturn
EndProcedure
You are comparing image buffer data from two different images without any attempt to normalize them. For instance you don't take into account any information for them by using DrawingBufferPixelFormat(). You may be fortunate and the images may always be in the same format but then again it [could be a Wednesday] (insert your favorite joke here in place of the bracketed one).
MakeDesktopScreenshot() also contains at least a few issues. For one it reserves memory for #max_number_of_frames (based on the assumption that all frames have the same Pitch) but doesn't contain logic to handle more than 2. This is because it seems to compare every image after the first one to the first one to see if they overlap. If stitching is to occur I would think you would compare each image to the one immediately preceding it. I'm guessing you are always using it with two images.
In your debugging I recommend that you test your procedures separately. First the screen captures (save them to disk) then test the stitching of them by using the disk images. After that works eliminate the storage and loading from disk of the intermediate images.
Re: drawing
Posted: Wed Mar 16, 2022 12:53 pm
by ZX80
Good day,
Demivec.
Thanks for your reply.
I did a bit more research on this issue and came to the conclusion: raw data = BMP-file without header. Header size of BMP-file = 54 Bytes. But this is not the most important thing. What matters is how the raw data is written (BitMap Array). It turns out they are written from left to right and from bottom to top. I think this is the reason of the fatal error. So... start of the raw data is the end of the frame. Am I wrong again?
...doesn't contain logic to handle more than 2.
Please... This is just a sketch. And if I understand how to glue at least two of them, then no problems to continue.
If stitching is to occur I would think you would compare each image to the one immediately preceding it.
This is true. But at this stage, it doesn't matter. It will be in the future when I can glue at least two frames.
First the screen captures (save them to disk) then test the stitching of them by using the disk images.
Without using
ImageGadget? Then you definitely need to know the structure of file for the selected image format (png, jpg). This will be required to manually edit the file header (when you change raw-content).
Why advance the the search point byte by byte instead of line by line?
Otherwise, the fish will pass through the seine. I think so...
Re: drawing
Posted: Wed Mar 16, 2022 2:56 pm
by JHPJHP
Hi ZX80,
ZX80 wrote:Every time after running your code I get the same message: "icon file not found".
Sorry, in the examples compiler options I had an icon set; download fixed, or just deselect the checkbox.
ZX80 wrote:I think your approach in this case is redundant and unnecessarily complicated.
I agree, but if you wanted to post a couple test images... no worries otherwise.
Re: drawing
Posted: Wed Mar 16, 2022 4:37 pm
by ZX80
@
JHPJHP
I unchecked the checkbox in compiler options, but now another problem. I see this message:
Code: Select all
title$ = "PureBasic_Compilation1.exe - System error"
text$ = "The program cannot start because MSVCP140.dll is missing" + #CRLF$ + "from the computer. Try reinstalling the program."
MessageRequester(title$, text$, #PB_MessageRequester_Error)
In any case, thanks for your point of view on this question.
Unfortunately, I can not find suitable shots that would have a large angle between themselves. Thank you!