Page 1 of 2

Question about DrawingBuffers (with example)

Posted: Thu Feb 02, 2023 3:35 pm
by Josepho
Hi im trying to create a function that turns a selected color into a transparent using image buffers, i know how to do it with plot

Code: Select all

            For i = 0 To ImageHeight(imageFiles()\imgBackup\i)-1
              For z = 0 To ImageWidth(imageFiles()\imgBackup\i)-1
                
                If Point(z,i) = cKey
                  Plot(z,i,RGBA(0,0,0,0))
                EndIf
    
              Next z
            Next i
but im having issues trying to do the same using image buffers, here is what i have at this moment using the example of the documentation

Code: Select all

      If StartDrawing(ImageOutput(imageFiles()\imgBackup\i))
          cKey = imageFiles()\ckeys()
          cBlank = RGBA(0,0,0,0)

          If cKey >= 0
            
            Buffer = DrawingBuffer()
            Pitch = DrawingBufferPitch()
            PixelFormat = DrawingBufferPixelFormat()
            
            If PixelFormat = #PB_PixelFormat_32Bits_RGB Or PixelFormat = #PB_PixelFormat_32Bits_BGR
              Offset = 4
            Else ; 24-bit
              Offset = 3
            EndIf
            
            For y = 0 To ImageHeight(imageFiles()\imgBackup\i)-1
              
              *Line.Pixel = Buffer+Pitch*y
              
              For x = 0 To ImageWidth(imageFiles()\imgBackup\i)-1
                
                Debug "data colors: "+Str(x)+" "+Str(y)+" "+Str(*Line\Pixel)+" "+Str(cKey)+" "+Str(cBlank)
                
                If *Line\Pixel = cKey
                  *Line\Pixel = cBlank
                EndIf
                
                *Line+Offset
                
              Next x
            Next y
      endif
      stopDrawing()
What im missing?? The debug is showing negative numbers for the *Line\Pixel why is that? The result doesnt change the image at any way

Many thanks for your help!

Re: Noob question about imageBuffer function

Posted: Thu Feb 02, 2023 5:26 pm
by infratec
I'm missing a functional example.

Re: Noob question about imageBuffer function

Posted: Thu Feb 02, 2023 5:39 pm
by Josepho
Here is a working example, the commented plot works but the actual code doesnt

Code: Select all

Structure Pixel
  Pixel.l
EndStructure

If OpenWindow(0, 0, 0, 220, 220, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    CanvasGadget(0, 10, 10, 200, 200)
    UsePNGImageDecoder()

    img.i = LoadImage(#PB_Any,"unitytest2.png")
    
    If StartDrawing(ImageOutput(img))
      DrawingMode(#PB_2DDrawing_AllChannels)
      
      cKey = Point(0,0)
      cBlank = RGBA(0,0,0,0)
      
      Buffer = DrawingBuffer()
      Pitch = DrawingBufferPitch()
      PixelFormat = DrawingBufferPixelFormat()
      
      If PixelFormat = #PB_PixelFormat_32Bits_RGB Or PixelFormat = #PB_PixelFormat_32Bits_BGR
        Offset = 4
      Else ; 24-bit
        Offset = 3
      EndIf
      
      For y = 0 To ImageHeight(img)-1
        
        *Line.Pixel = Buffer+Pitch*y
        
        For x = 0 To ImageWidth(img)-1
          
          
          If *Line\Pixel = cKey
            *Line\Pixel = cBlank
          EndIf
          
          *Line+Offset
          
        Next x
      Next y
      
;       For i = 0 To ImageHeight(img)-1
;         For z = 0 To ImageWidth(img)-1
;           
;           If Point(z,i) = cKey
;             Plot(z,i,RGBA(0,0,0,0))
;           EndIf
;           
;         Next z
;       Next i
      
      StopDrawing()
    EndIf
    
    
    If StartDrawing(CanvasOutput(0))
      DrawingMode(#PB_2DDrawing_AlphaBlend)
      DrawImage(ImageID(img),0,0)
      StopDrawing()
    EndIf
    
    Repeat
      Event = WaitWindowEvent()
             
      
    Until Event = #PB_Event_CloseWindow
  EndIf

Re: Question about DrawingBuffers (with example)

Posted: Thu Feb 02, 2023 5:59 pm
by Mijikai
The problem seems to be the check:

Code: Select all

PixelFormat = #PB_PixelFormat_32Bits_RGB Or PixelFormat = #PB_PixelFormat_32Bits_BGR
DrawingBufferPixelFormat() returns flags so correct would be:

Code: Select all

PixelFormat & #PB_PixelFormat_32Bits_RGB Or PixelFormat & #PB_PixelFormat_32Bits_BGR

Re: Question about DrawingBuffers (with example)

Posted: Thu Feb 02, 2023 6:06 pm
by Josepho
Im afraid that doesnt have any effect Mijikai

Re: Question about DrawingBuffers (with example)

Posted: Thu Feb 02, 2023 6:14 pm
by infratec
Mijikai is right.

You need the & in the compare.

Your next bug is the color order of the pixel.

And your example i still not executable, because we don't own this image.

Re: Question about DrawingBuffers (with example)

Posted: Thu Feb 02, 2023 6:17 pm
by Josepho
This is the image, the target is to remove the green background

Image

Re: Question about DrawingBuffers (with example)

Posted: Thu Feb 02, 2023 6:18 pm
by infratec
A working example:

Code: Select all

Structure imgBackup_Structure
  i.i
EndStructure


Structure imageFile_Structure
  imgBackup.imgBackup_Structure
  List ckeys.i()
EndStructure

Structure Pixel
  Pixel.l
EndStructure



NewList imageFiles.imageFile_Structure()

AddElement(imageFiles())
imageFiles()\imgBackup\i = CreateImage(#PB_Any, 200, 200, 32, RGBA($80, $81, $82, $FF))

If StartDrawing(ImageOutput(imageFiles()\imgBackup\i))
  DrawingMode(#PB_2DDrawing_AllChannels)
  Box(10, 10, 100, 100, RGBA($20, $30, $40, $FF))
  StopDrawing()
EndIf

AddElement(imageFiles()\ckeys())
imageFiles()\ckeys() = RGBA($20, $30, $40, $FF)



Define *Line.Pixel
Define.i iWidth, iHeight

If StartDrawing(ImageOutput(imageFiles()\imgBackup\i))
  
  DrawingMode(#PB_2DDrawing_AllChannels)
  
  cKey = imageFiles()\ckeys()
  cBlank = RGBA(0, 0, 0, 0)
  
  If cKey <> 0
    
    *Buffer = DrawingBuffer()
    Pitch = DrawingBufferPitch()
    PixelFormat = DrawingBufferPixelFormat()
    
    
    If PixelFormat & #PB_PixelFormat_32Bits_RGB Or PixelFormat & #PB_PixelFormat_32Bits_BGR
      If PixelFormat & #PB_PixelFormat_32Bits_RGB
        Debug "RGB"
      Else
        Debug "BGR"
        cKey = RGBA(Blue(ckey), Green(ckey), Red(ckey), Alpha(ckey))
      EndIf
      Offset = 4
    Else ; 24-bit
      Offset = 3
    EndIf
    
    iHeight = ImageHeight(imageFiles()\imgBackup\i) - 1
    iWidth = ImageWidth(imageFiles()\imgBackup\i) - 1
    
    For y = 0 To iHeight
      
      *Line = *Buffer + Pitch * y
      
      For x = 0 To iWidth
        
        ;Debug Str(*Line) + " " + Str(x) + " " + Str(y) + " " + Hex(*Line\Pixel, #PB_Long) + " " + Hex(cKey, #PB_Long) + " " + Hex(cBlank, #PB_Long)
        
        If *Line\Pixel = cKey
          *Line\Pixel = cBlank
        EndIf
        
        *Line + Offset
        
      Next x
    Next y
  EndIf
  StopDrawing()
EndIf


OpenWindow(0, 0, 0, 200, 200, "Test", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
ImageGadget(0, 0, 0, 0, 0, ImageID(imageFiles()\imgBackup\i))


Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Question about DrawingBuffers (with example)

Posted: Thu Feb 02, 2023 6:22 pm
by infratec
And for speed reasons you can also check:

Code: Select all

CustomFilterCallback()

Re: Question about DrawingBuffers (with example)

Posted: Thu Feb 02, 2023 6:22 pm
by Mijikai
The example wasnt runnable for me but i read through it again and found this: cKey correct would be cKey.l otherwise it will fail on x64

Re: Question about DrawingBuffers (with example)

Posted: Thu Feb 02, 2023 6:32 pm
by Josepho
It works! many thanks, i modified the code to make it work with the image and it works, yes also adding the .l was critical

Here is the code in case a future person see this

Code: Select all

Structure imgBackup_Structure
  i.i
EndStructure


Structure imageFile_Structure
  imgBackup.imgBackup_Structure
  List ckeys.i()
EndStructure

Structure Pixel
  Pixel.l
EndStructure



NewList imageFiles.imageFile_Structure()

AddElement(imageFiles())
; imageFiles()\imgBackup\i = CreateImage(#PB_Any, 200, 200, 32, RGBA($80, $81, $82, $FF))
; 
; If StartDrawing(ImageOutput(imageFiles()\imgBackup\i))
;   DrawingMode(#PB_2DDrawing_AllChannels)
;   Box(10, 10, 100, 100, RGBA($20, $30, $40, $FF))
;   StopDrawing()
; EndIf

AddElement(imageFiles()\ckeys())

UsePNGImageDecoder()
imageFiles()\imgBackup\i = LoadImage(#PB_Any,"unitytest2.png")

Define *Line.Pixel

If StartDrawing(ImageOutput(imageFiles()\imgBackup\i))
  
  DrawingMode(#PB_2DDrawing_AllChannels)
  
  imageFiles()\ckeys() = Point(0,0) ;RGBA($20, $30, $40, $FF)
  cKey.l = imageFiles()\ckeys()
  cBlank = RGBA(0, 0, 0, 0)
  
  If cKey <> 0
    
    *Buffer = DrawingBuffer()
    Pitch = DrawingBufferPitch()
    PixelFormat = DrawingBufferPixelFormat()
    
    
    If PixelFormat & #PB_PixelFormat_32Bits_RGB Or PixelFormat & #PB_PixelFormat_32Bits_BGR
      If PixelFormat & #PB_PixelFormat_32Bits_RGB
        Debug "RGB"
      Else
        Debug "BGR"
        cKey = RGBA(Blue(cKey), Green(cKey), Red(cKey), Alpha(cKey))
      EndIf
      Offset = 4
    Else ; 24-bit
      Offset = 3
    EndIf
    
    For y = 0 To ImageHeight(imageFiles()\imgBackup\i) - 1
      
      *Line = *Buffer + Pitch * y
      
      For x = 0 To ImageWidth(imageFiles()\imgBackup\i) - 1
        
        ;Debug Str(*Line) + " " + Str(x) + " " + Str(y) + " " + Hex(*Line\Pixel, #PB_Long) + " " + Hex(cKey, #PB_Long) + " " + Hex(cBlank, #PB_Long)
        
        If *Line\Pixel = cKey
          *Line\Pixel = cBlank
        EndIf
        
        *Line + Offset
        
      Next x
    Next y
  EndIf
  StopDrawing()
EndIf


OpenWindow(0, 0, 0, 200, 200, "Test", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
ImageGadget(0, 0, 0, 0, 0, ImageID(imageFiles()\imgBackup\i))


Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Question about DrawingBuffers (with example)

Posted: Thu Feb 02, 2023 7:36 pm
by infratec
Version with CustomFilterCallback()

Code: Select all

Structure imgBackup_Structure
  i.i
EndStructure


Structure imageFile_Structure
  imgBackup.imgBackup_Structure
  List ckeys.i()
EndStructure



Procedure.i CustomFilter(x.i, y.i, transparentColor.i, sourceColor.i)
  
  Protected.i resultColor
  
  
  If sourceColor = transparentColor
    resultColor = 0
  Else
    resultColor = sourceColor
  EndIf
  
  ;Debug Str(x) + " " + Str(y) + " " + Hex(sourceColor, #PB_Long) + " " + Hex(transparentColor, #PB_Long) + " " + Hex(resultColor, #PB_Long)
  
  ProcedureReturn resultColor
  
EndProcedure


UsePNGImageDecoder()

NewList imageFiles.imageFile_Structure()

AddElement(imageFiles())
; imageFiles()\imgBackup\i = CreateImage(#PB_Any, 200, 200, 32, RGBA($80, $81, $82, $FF))
; If StartDrawing(ImageOutput(imageFiles()\imgBackup\i))
;   DrawingMode(#PB_2DDrawing_AllChannels)
;   Box(10, 10, 50, 50, RGBA(0, 255, 0, 255))
;   StopDrawing()
; EndIf
imageFiles()\imgBackup\i = LoadImage(#PB_Any, "unitytest2.png")
If ImageDepth(imageFiles()\imgBackup\i) <> 32
  Image32 = CreateImage(#PB_Any, ImageWidth(imageFiles()\imgBackup\i), ImageHeight(imageFiles()\imgBackup\i), 32)
  If Image32
    If StartDrawing(ImageOutput(Image32))
      DrawImage(ImageID(imageFiles()\imgBackup\i), 0, 0)
      StopDrawing()
      FreeImage(imageFiles()\imgBackup\i)
      imageFiles()\imgBackup\i = Image32
    EndIf
  EndIf
EndIf


AddElement(imageFiles()\ckeys())
imageFiles()\ckeys() = RGBA(0, 255, 0, 255)

If StartDrawing(ImageOutput(imageFiles()\imgBackup\i))  
  DrawingMode(#PB_2DDrawing_CustomFilter)      
  CustomFilterCallback(@CustomFilter())
  
  Box(0, 0, ImageWidth(imageFiles()\imgBackup\i), ImageHeight(imageFiles()\imgBackup\i), imageFiles()\ckeys())
  
  StopDrawing()
EndIf


OpenWindow(0, 0, 0, 200, 200, "Test", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
ImageGadget(0, 0, 0, 0, 0, ImageID(imageFiles()\imgBackup\i))


Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Question about DrawingBuffers (with example)

Posted: Sat Feb 04, 2023 11:14 am
by Demivec
infratec wrote: Thu Feb 02, 2023 7:36 pm Version with CustomFilterCallback()
I think your Custom filter callback is a little off. The callback should be using black instead of the source color when the source color equals the transparent color, not when the source color equals the target color. Also, the transparent color should be set independent of the callback parameters. The source color would be from the image being drawn and the target color (named transparentColor in your code) is the color already present in the output drawing.

I confess that I did not run your example yet before I posted this. Here is a version that implements the suggested changes, also untested.

Code: Select all

Structure imgBackup_Structure
  i.i
EndStructure


Structure imageFile_Structure
  imgBackup.imgBackup_Structure
  List ckeys.i()
EndStructure


Global transparentColor.i
Procedure.i CustomFilter(x.i, y.i, sourceColor.i, targetColor.i)
  
  Protected.i resultColor
  
  If sourceColor = transparentColor
    resultColor = 0 ; draw black instead of transparent color
    ;resultColor  = targetColor ; leave target color unchanged for actual transparency
  Else
    resultColor = sourceColor
  EndIf
  
  ProcedureReturn resultColor
  
EndProcedure



NewList imageFiles.imageFile_Structure()

AddElement(imageFiles())
imageFiles()\imgBackup\i = CreateImage(#PB_Any, 200, 200, 32, RGBA($80, $81, $82, $FF))

If StartDrawing(ImageOutput(imageFiles()\imgBackup\i))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawImage(10, 10, 100, 100, RGBA($20, $30, $40, $FF))
  StopDrawing()
EndIf

AddElement(imageFiles()\ckeys())
imageFiles()\ckeys() = RGBA($20, $30, $40, $FF)


If StartDrawing(ImageOutput(imageFiles()\imgBackup\i))
  
  DrawingMode(#PB_2DDrawing_CustomFilter)      
  CustomFilterCallback(@CustomFilter())
  
  transparentColor = imageFiles()\ckeys()
  Box(0, 0, ImageWidth(imageFiles()\imgBackup\i), ImageHeight(imageFiles()\imgBackup\i))
  
  StopDrawing()
EndIf


OpenWindow(0, 0, 0, 200, 200, "Test", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
ImageGadget(0, 0, 0, 0, 0, ImageID(imageFiles()\imgBackup\i))


Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Question about DrawingBuffers (with example)

Posted: Sat Feb 04, 2023 2:46 pm
by infratec
No, it's not off :wink:

The target color in my example is the color which should be changed to transparent.
I used the color of the Box() to ensure this.

If the source color is equal to the color which should be transparent, the color value is set to 0.
The color black is meaningless, since it is fully transparent. This is done like in the original code.

Re: Question about DrawingBuffers (with example)

Posted: Sat Feb 04, 2023 2:53 pm
by mestnyi
after running your codes what should happen? :)