drawing

Just starting out? Need help? Post your questions and find answers here.
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: drawing

Post by ZX80 »

@STARGÅTE

I'm sorry I didn't listen to you or didn't listen closely enough. :oops:
A thousand apologies, you were right all along.

The 'DrawingBufferPixelFormat'-function telling me that I'm dealing with "24bit BGR with inverted Y coordinate".

Code: Select all

DrawingBufferPixelFormat() = #PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY
Using the DrawingBuffer can make a lot of trouble, if the buffer is Y-flipped (#PB_PixelFormat_ReversedY) or the pitches do not match.
This is my case :(

added:
But I do not despair, because now I have very significant information. And information is power.
I will solve this issue, in any case. It doesn't matter how. At least now I understand what needs to be done. I will return to this question later when I get time. I'm on the right track and everything will be fine. I know.
Also I pay sincere tribute to all involved. I would rather say merely... Thank you, gentlemen.
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: drawing

Post by ZX80 »

A few days later...

Today I tried again, but without success. I have simplified this as much as possible. Can anyone tell me what is wrong here again? Right now I'm looking for a match on only one line. In fact, the height of one line of text is 20 lines. And I would like to compare such a minimum volume, and not one line as it is now. I want to see the address of the buffer where the match occurs. More precisely, the address of the line in the buffer that follows the desired fragment. Now I read the buffer as it should, but it does not help. Why?

Code: Select all

Global.i SearchPatternSize, *SearchPattern

Procedure MakeDesktopScreenshot(ImageNr, ImageX, ImageY, ImageWidth, ImageHeight, SnapshotNr)
  Protected hImage, hDC, hWnd, DeskDC, Addr
  Protected Pitch, iFormat, iBytes, LastY, Y
  Protected *Buffer
  
  hImage = CreateImage(ImageNr, ImageWidth, ImageHeight)
  If hImage
    hDC = StartDrawing(ImageOutput(ImageNr))
    If hDC
      hWnd=GetDesktopWindow_()
      DeskDC = GetDC_(hWnd) 
      BitBlt_(hDC, 0, 0, ImageWidth, ImageHeight, DeskDC, ImageX, ImageY, #SRCCOPY) 
      
      *Buffer = DrawingBuffer()
      Pitch   = DrawingBufferPitch()
      iFormat = DrawingBufferPixelFormat()

      LastY   = ImageHeight - 1
      
      If SnapshotNr = 1
        If iFormat & #PB_PixelFormat_24Bits_BGR
          iBytes = 3
        EndIf
        SearchPatternSize = ImageWidth * iBytes
        *SearchPattern = AllocateMemory(SearchPatternSize)
        If *SearchPattern
          If iFormat & #PB_PixelFormat_ReversedY
            CopyMemory(*Buffer + Pitch * LastY, *SearchPattern, SearchPatternSize)
          EndIf
        Else
          hImage = 0
        EndIf
        
      Else
        If iFormat & #PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY
          For Y = LastY To 0 Step -1
            If CompareMemory(*Buffer + Pitch * Y, *SearchPattern, SearchPatternSize)
              Debug "found"
              Break
            EndIf
          Next
        EndIf
      EndIf

      StopDrawing()
      ReleaseDC_(hWnd, DeskDC)
    Else
      FreeImage(ImageNr)
      hImage = 0
    EndIf
  EndIf
  
  ProcedureReturn hImage
EndProcedure


#const_x = 3
#const_y = 122
#const_w = 1656
#const_h = 675

Sleep_(2000)
If MakeDesktopScreenshot(0, #const_x, #const_y, #const_w, #const_h, 1)
  Beep_(2000, 400)
  Sleep_(5000) ;time to scroll screen
  If MakeDesktopScreenshot(0, #const_x, #const_y, #const_w, #const_h, 2)
    ; to do
  EndIf
EndIf
If *SearchPattern
  FreeMemory(*SearchPattern)
EndIf
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: drawing

Post by breeze4me »

Here are two examples. Both work well on my PC.

Code: Select all

Global.i SearchPatternSize, *SearchPattern
Global *FirstImage, *LastPartialImage, LastPartialImageHeight

Procedure MakeDesktopScreenshot(ImageNr, ImageX, ImageY, ImageWidth, ImageHeight, SnapshotNr)
  Protected hImage, hDC, hWnd, DeskDC, Addr
  Protected Pitch, iFormat, iBytes, LastY, Y
  Protected *Buffer
  Protected ScanLinesToCompare
  
  hImage = CreateImage(ImageNr, ImageWidth, ImageHeight)
  If hImage
    hDC = StartDrawing(ImageOutput(ImageNr))
    If hDC
      hWnd=GetDesktopWindow_()
      DeskDC = GetDC_(hWnd) 
      BitBlt_(hDC, 0, 0, ImageWidth, ImageHeight, DeskDC, ImageX, ImageY, #SRCCOPY) 
      
      *Buffer = DrawingBuffer()
      Pitch   = DrawingBufferPitch()
      iFormat = DrawingBufferPixelFormat()
      
      LastY   = ImageHeight - 1
      If (iFormat & (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)) = (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)
        
        ;ScanLinesToCompare = 10
        ;ScanLinesToCompare = 3
        ScanLinesToCompare = 1
        
        If SnapshotNr = 1
          SearchPatternSize = ScanLinesToCompare * Pitch
          *SearchPattern = AllocateMemory(SearchPatternSize)
          If *SearchPattern
            CopyMemory(*Buffer, *SearchPattern, SearchPatternSize)
          Else
            hImage = 0
          EndIf
          
          *FirstImage = AllocateMemory(Pitch * ImageHeight)
          If *FirstImage
            CopyMemory(*Buffer, *FirstImage, Pitch * ImageHeight)
          Else
            hImage = 0
          EndIf
          
        Else
          
          LastY - ScanLinesToCompare
          
          For Y = LastY To 0 Step -1
            
            If CompareMemory(*Buffer + Pitch * Y, *SearchPattern, SearchPatternSize)
              
              If y * Pitch > 0
                *LastPartialImage = AllocateMemory(y * Pitch)
                If *LastPartialImage
                  CopyMemory(*Buffer, *LastPartialImage, y * Pitch)
                  LastPartialImageHeight = y
                  
                  Debug "Image height to be added at the end of the first image: " + LastPartialImageHeight
                EndIf
              EndIf
              
              Break
            EndIf
          Next
          
        EndIf
      EndIf
      
      StopDrawing()
      ReleaseDC_(hWnd, DeskDC)
      
      ; image for verification
      CompilerIf #PB_Compiler_Debugger
        Protected Image
        
        If *LastPartialImage
          Image = CreateImage(#PB_Any, ImageWidth, y + ImageHeight)
          If Image
            Debug "Image  #" + Str(Image) + "  =  #2 "
            
            If StartDrawing(ImageOutput(Image))
              *Buffer = DrawingBuffer()
              
              If (DrawingBufferPixelFormat() & (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)) = (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)
                CopyMemory(*LastPartialImage, *Buffer, y * Pitch)
                
                If *FirstImage
                  CopyMemory(*FirstImage, *Buffer + y * Pitch, MemorySize(*FirstImage))
                EndIf
              EndIf
              StopDrawing()
            EndIf
          EndIf
        EndIf
      CompilerEndIf
      
    Else
      FreeImage(ImageNr)
      hImage = 0
    EndIf
  EndIf
  
  ProcedureReturn hImage
EndProcedure

Procedure CreateFinalizeSnapshot(ImageNr, Width, Height) ;, SnapshotNr)
  Protected hImage
  
  If *LastPartialImage And *FirstImage
    hImage = CreateImage(ImageNr, Width, Height + LastPartialImageHeight)
    If hImage
      If StartDrawing(ImageOutput(ImageNr))
        *BufferTemp = DrawingBuffer()
        LastPartialImageSize = MemorySize(*LastPartialImage)
        
        If (DrawingBufferPixelFormat() & (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)) = (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)
          CopyMemory(*LastPartialImage, *BufferTemp, LastPartialImageSize)
          CopyMemory(*FirstImage, *BufferTemp + LastPartialImageSize, MemorySize(*FirstImage))
        EndIf
        StopDrawing()
      EndIf
    EndIf
  EndIf
  
  If *FirstImage       : FreeMemory(*FirstImage)       : *FirstImage = 0       : EndIf
  If *LastPartialImage : FreeMemory(*LastPartialImage) : *LastPartialImage = 0 : EndIf
  
  ProcedureReturn hImage
EndProcedure


#const_x = 3
#const_y = 122
#const_w = 1656
#const_h = 675

Sleep_(2000)
If MakeDesktopScreenshot(0, #const_x, #const_y, #const_w, #const_h, 1)
  Beep_(2000, 400)
  Sleep_(5000) ;time to scroll screen
  If MakeDesktopScreenshot(1, #const_x, #const_y, #const_w, #const_h, 2)
    ; to do
    
    If CreateFinalizeSnapshot(2, #const_w, #const_h) ;;, 2)
      
      ShowLibraryViewer("image")
      CallDebugger
    EndIf
    
  EndIf
EndIf
If *SearchPattern
  FreeMemory(*SearchPattern)
EndIf

Code: Select all

Global.i SearchPatternSize, *SearchPattern
Global LastPartialImage

Procedure MakeDesktopScreenshot(ImageNr, ImageX, ImageY, ImageWidth, ImageHeight, SnapshotNr)
  Protected hImage, hDC, hWnd, DeskDC, Addr
  Protected Pitch, iFormat, iBytes, LastY, Y
  Protected *Buffer
  Protected ScanLinesToCompare, LastPartialImageHeight
  
  hImage = CreateImage(ImageNr, ImageWidth, ImageHeight)
  If hImage
    hDC = StartDrawing(ImageOutput(ImageNr))
    If hDC
      hWnd=GetDesktopWindow_()
      DeskDC = GetDC_(hWnd) 
      BitBlt_(hDC, 0, 0, ImageWidth, ImageHeight, DeskDC, ImageX, ImageY, #SRCCOPY) 
      
      *Buffer = DrawingBuffer()
      Pitch   = DrawingBufferPitch()
      iFormat = DrawingBufferPixelFormat()
      
      LastY   = ImageHeight - 1
      If (iFormat & (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)) = (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)
        
        ;ScanLinesToCompare = 3
        ;ScanLinesToCompare = 10
        ScanLinesToCompare = 1
        
        If SnapshotNr = 1
          SearchPatternSize = ScanLinesToCompare * Pitch
          *SearchPattern = AllocateMemory(SearchPatternSize)
          If *SearchPattern
            CopyMemory(*Buffer, *SearchPattern, SearchPatternSize)
          Else
            hImage = 0
          EndIf
          
        Else
          LastY - ScanLinesToCompare
          
          For Y = LastY To 0 Step -1
            If CompareMemory(*Buffer + Pitch * Y, *SearchPattern, SearchPatternSize)
              
              LastPartialImageHeight = 0
              
              If Y * Pitch > 0
                LastPartialImageHeight = y
                Debug "Image height to be added at the end of the first image: " + LastPartialImageHeight
              EndIf
              
              Break
            EndIf
          Next
          
        EndIf
      EndIf
      
      StopDrawing()
      ReleaseDC_(hWnd, DeskDC)
      
      If LastPartialImageHeight > 0 And ImageHeight - LastPartialImageHeight > 0
        LastPartialImage = GrabImage(ImageNr, #PB_Any, 0, ImageHeight - LastPartialImageHeight, ImageWidth, LastPartialImageHeight)
      EndIf
      
    Else
      FreeImage(ImageNr)
      hImage = 0
    EndIf
  EndIf
  
  ProcedureReturn hImage
EndProcedure

Procedure CreateFinalizeSnapshot(ImageNr, Width, Height) ;, SnapshotNr)
  Protected hImage, ImgH
  
  If LastPartialImage And IsImage(LastPartialImage)
    ImgH = ImageHeight(LastPartialImage)
  EndIf
  
  hImage = CreateImage(ImageNr, Width, Height + ImgH)
  If hImage
    If StartDrawing(ImageOutput(ImageNr))
      DrawImage(ImageID(0), 0, 0)
      
      If ImgH
        DrawImage(ImageID(LastPartialImage), 0, ImageHeight(0))
        ;DrawImage(ImageID(LastPartialImage), 0, Height)
      EndIf
      
      StopDrawing()
    EndIf
  EndIf
  
  ProcedureReturn hImage
EndProcedure


#const_x = 3
#const_y = 122
#const_w = 1656
#const_h = 675

Sleep_(2000)
If MakeDesktopScreenshot(0, #const_x, #const_y, #const_w, #const_h, 1)
  Beep_(2000, 400)
  Sleep_(5000) ;time to scroll screen
  If MakeDesktopScreenshot(1, #const_x, #const_y, #const_w, #const_h, 2)
    ; to do
    
    If CreateFinalizeSnapshot(2, #const_w, #const_h) ;;, 2)
      ;SaveImage(0, "z:\test.bmp")
      
      ShowLibraryViewer("image")
      CallDebugger
    EndIf
    
  EndIf
EndIf
If *SearchPattern
  FreeMemory(*SearchPattern)
EndIf

Edit:
By the way, I have to point out an issue. Make sure you use the brackets well. :wink:

Code: Select all

PixelFormat = #PB_PixelFormat_24Bits_BGR   ; For example, if the return value of DrawingBufferPixelFormat() is like this.

Debug Bool(PixelFormat & #PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)     ; 1
Debug Bool(PixelFormat & (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY))   ; 1
Debug Bool((PixelFormat & #PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY) = (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)) ; 1
Debug ""

; To compare whether the value of variable #1 contains both values of variable #2 and #3, it should be as follows.
Debug Bool(PixelFormat & (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY) = (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)) ; 0  correct result

Debug "-----------------------"


PixelFormat = #PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY  ; For example, if the return value of DrawingBufferPixelFormat() is like this.

Debug Bool(PixelFormat & #PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)     ; 1
Debug Bool(PixelFormat & ( #PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY))  ; 1
Debug Bool((PixelFormat & #PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY) = (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)) ; 1
Debug ""
Debug Bool(PixelFormat & (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY) = (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)) ; 1  correct result
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: drawing

Post by breeze4me »

This is a new code that improves the second example.

Edit:
BUG: If the DPI resolution factor is not 1.0, it may not work properly depending on the object to be captured. If I find a solution, I will update the code. Sorry. :oops:
Programs that do not support DPI Awareness seem to have such a problem, because of the blurry captured image.

Code: Select all

Global *SearchPattern

Procedure MakeDesktopScreenshot(ImageNr, ImageX, ImageY, ImageWidth, ImageHeight, *LowerPartImageNr.Integer = 0)
  Protected hImage, hDC, hWnd, DeskDC
  Protected Pitch, iFormat, LastY, Y
  Protected *Buffer
  Protected ScanLinesToCompare, PartialImageHeight, SearchPatternSize
  
  hImage = CreateImage(ImageNr, ImageWidth, ImageHeight)
  If hImage
    hDC = StartDrawing(ImageOutput(ImageNr))
    If hDC
      hWnd=GetDesktopWindow_()
      DeskDC = GetDC_(hWnd) 
      BitBlt_(hDC, 0, 0, ImageWidth, ImageHeight, DeskDC, ImageX, ImageY, #SRCCOPY) 
      
      *Buffer = DrawingBuffer()
      Pitch   = DrawingBufferPitch()
      iFormat = DrawingBufferPixelFormat()
      LastY   = ImageHeight - 1
      
      If (iFormat & (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)) = (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_ReversedY)
        
        ;ScanLinesToCompare = 3
        ;ScanLinesToCompare = 10
        ScanLinesToCompare = 1
        
        SearchPatternSize = ScanLinesToCompare * Pitch
        
        ; if there is a previously captured image, start searching from the top of the current image.
        If *SearchPattern
          LastY - ScanLinesToCompare
          
          For Y = LastY To 0 Step -1
            If CompareMemory(*Buffer + Pitch * Y, *SearchPattern, SearchPatternSize)
              
              PartialImageHeight = 0
              
              If Y * Pitch > 0
                PartialImageHeight = y
                ;Debug "Image height to be added at the end of the first image: " + PartialImageHeight
              Else
                hImage = 0
              EndIf
              
              Break
            EndIf
          Next
          
        Else
          *SearchPattern = AllocateMemory(SearchPatternSize)
        EndIf
        
        ; get one or more scanlines from the bottom of the current image.
        If *SearchPattern
          CopyMemory(*Buffer, *SearchPattern, SearchPatternSize)
        Else
          hImage = 0
        EndIf
        
      Else
        hImage = 0
      EndIf
      
      StopDrawing()
      ReleaseDC_(hWnd, DeskDC)
      
      If hImage And *LowerPartImageNr
        If PartialImageHeight > 0 And ImageHeight - PartialImageHeight > 0
          *LowerPartImageNr\i = GrabImage(ImageNr, #PB_Any, 0, ImageHeight - PartialImageHeight, ImageWidth, PartialImageHeight)
        Else
          hImage = 0
        EndIf
      EndIf
      
    Else
      hImage = 0
    EndIf
    
    If hImage = 0
      FreeImage(ImageNr)
    EndIf
  EndIf
  
  ProcedureReturn hImage
EndProcedure

Procedure CreateFinalizeSnapshot(NewImageNr, FirstImageNr, Array Image.i(1))
  Protected i, hImage, TotalHeight, y, Width
  Protected ImageCount = ArraySize(Image())
  Protected Dim Height.i(0)
  
  If IsImage(FirstImageNr)
    If ImageCount >= 0
      ReDim Height(ImageCount + 1)
      
      Width = ImageWidth(FirstImageNr)
      Height(0) = ImageHeight(FirstImageNr)
      TotalHeight + Height(0)
      
      For i = 0 To ImageCount
        If Image(i) And IsImage(Image(i))
          Height(i + 1) = ImageHeight(Image(i))
          TotalHeight + Height(i + 1)
        EndIf
      Next
      
      hImage = CreateImage(NewImageNr, Width, TotalHeight)
      If hImage
        If StartDrawing(ImageOutput(NewImageNr))
          DrawImage(ImageID(FirstImageNr), 0, 0)
          
          For i = 0 To ImageCount
            If Height(i) > 0
              y + Height(i)
              DrawImage(ImageID(Image(i)), 0, y)
            EndIf
          Next
          
          StopDrawing()
        EndIf
      EndIf
      
      For i = 0 To ImageCount
        If Image(i) And IsImage(Image(i))
          FreeImage(Image(i))
        EndIf
      Next
      
    EndIf
  EndIf
  
  If *SearchPattern
    FreeMemory(*SearchPattern)
    *SearchPattern = 0
  EndIf
  
  ProcedureReturn hImage
EndProcedure

Define Dim Image.i(1)

#const_x = 3
#const_y = 122
#const_w = 1656
#const_h = 675

Repeat
  
  Sleep_(2000)
  Beep_(2000, 400)
  If Not MakeDesktopScreenshot(0, #const_x, #const_y, #const_w, #const_h)
    Debug "error 1"
    Break
  EndIf
  
  Sleep_(5000) ;time to scroll screen
  Beep_(2000, 400)
  If Not MakeDesktopScreenshot(1, #const_x, #const_y, #const_w, #const_h, @Image(0))
    Debug "error 2"
    Break
  EndIf
  
  Sleep_(5000) ;time to scroll screen
  Beep_(2000, 400)
  If Not MakeDesktopScreenshot(2, #const_x, #const_y, #const_w, #const_h, @Image(1))
    Debug "error 3"
    Break
  EndIf
  
  If CreateFinalizeSnapshot(3, 0, Image())
    
    ShowLibraryViewer("image")
    CallDebugger
  EndIf
  
  Break
ForEver
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: drawing

Post by ZX80 »

@breeze4me

Thank you so much for your help :!:

I completely forgot that I have zoom set to 125% (personalization -> screen). Unfortunately, when I set it to 100% it doesn't work for me either. I should take a better look at your code. Sorry, but now I can not say more. I'll be sure to comment on how your code works when I learn more about it.

Thanks again for your great work :!:
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: drawing

Post by ZX80 »

Hello everyone again.

I have another non-standard question:
How to make a smooth image density?
So that the image smoothly transitions from visible to invisible (gradient for alpha channel).
Even better, if it can be done only for certain part of the image. For example, at the end of a sheet of text.
Does anyone have any advice or ideas?

Thank you in advance.
User avatar
JHPJHP
Addict
Addict
Posts: 2250
Joined: Sat Oct 09, 2010 3:47 am

Re: drawing

Post by JHPJHP »

Hi ZX80,

If I understood you correctly...

Windows Services & Other Stuff\Other_Stuff\ImageMask\
- filter_1.pb: DrawingBuffer
- filter_2.pb: Point / Plot
- transparent_1.pb: DrawingBuffer
- transparent_2.pb: Point / Plot

NB*: The examples incorporate image mask files, but alternately you could draw your own to fit most requirements.
Last edited by JHPJHP on Wed Mar 30, 2022 6:09 pm, edited 4 times in total.

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: drawing

Post by ZX80 »

Good day, JHPJHP.
If I understood you correctly...
Exactly! This is exactly what I was asking. Blending the image with a semi-transparent mask. Thanks a lot for your example!
Post Reply