Equivalent to #PB_2DDrawing_AlphaBlend

Just starting out? Need help? Post your questions and find answers here.
User avatar
[blendman]
Enthusiast
Enthusiast
Posts: 297
Joined: Thu Apr 07, 2011 1:14 pm
Location: 3 arks
Contact:

Equivalent to #PB_2DDrawing_AlphaBlend

Post by [blendman] »

Hi masters of purebasic :)

Do you know what is "the function" equivalent to :

Code: Select all

DrawingMode(#PB_2DDrawing_AlphaBlend)
With a customfilter ?

What I would like to do ? :)
In my application Animatoon, I would like to add some special blendmode for the painting tool (not the blendmode of the layer, but when I paint on the image), to blend the stroke drawing :
- multiply, add, overlay...

Of course, I have tried the functions of blendmode I use for the layers, but unfortunately, it doesn't work.
It works with the layers, but not when I use it for paint. I think, its because, I add a colored box to use properly those blendmode for layers, but I cant add this box when drawing, because it's not the layer which change its blendmode, it's the drawing.

How I have coded the "painting" function :
it's very simple :
It's the same technic as the canvas example from purebasic :

Code: Select all

; first I draw on the sprite (for preview)
If StartDrawing(SpriteOutput(layer(LayerID)\sprite))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  ; if I use a normal mode to paint on the layer
  ; X_result = the position of the point in X, With all parameters (scatter (random), centerX of sprite...).
  ; Y_result = the position of the point in Y, With all parameters (scatter (random), centerY of sprite...).
  ; Alpha = the result for the alpha, with all alpha parameters (pression tablet wacom, random, brush\alpha...)
  DrawAlphaImage(ImageID(#BrushImageCopy), X_result, Y_result, Alpha)
  StopDrawing()
EndIf
; Then I draw on the image (to save it because I need to update the sprite with image sometimes (when I change the blendmode for example, or if the sprite is erased)
If StartDrawing(ImageOutput(layer(LayerID)\Image))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  DrawAlphaImage(ImageID(#BrushImageCopy), X_result, Y_result, Alpha)
  StopDrawing()
EndIf
SO, what I try to do is replace :

Code: Select all

 DrawingMode(#PB_2DDrawing_AlphaBlend)
By a customfilter when I change the blendmode for the tool (like in gimp/krita/photothop...).
Like that :

Code: Select all

; first I draw on the sprite (for preview)
If StartDrawing(SpriteOutput(layer(LayerID)\sprite))
  ; set the blendmode for drawing the stroke
  Select brush\blendmode 
    Case #bm_Normal
      DrawingMode(#PB_2DDrawing_AlphaBlend)
    Case #bm_multiply
      DrawingMode(#PB_2DDrawing_CustomFilter)
      CustomFilterCallback(@Painting_Multiply()) 
    Case #bm_Add
      DrawingMode(#PB_2DDrawing_CustomFilter)
      CustomFilterCallback(@Painting_ADD())
  EndSelect
  ; paint the stroke
  DrawAlphaImage(ImageID(#BrushImageCopy), X_result, Y_result, Alpha)
  StopDrawing()
EndIf
For the layer_blendmode multiply, I use this function (which works fine) :

Code: Select all

Procedure bm_multiply(x, y, SourceColor, TargetColor)
  ProcedureReturn RGBA((Red(SourceColor)*Red(TargetColor))/255,(Green(SourceColor)*Green(TargetColor))/255,(Blue(SourceColor)*Blue(TargetColor))/255, Alpha(SourceColor))
EndProcedure
BUt it doesn't work properly for painting with multiply blendmode.

So, do you an idea for a function to ahve the same result as

Code: Select all

DrawingMode(#PB_2DDrawing_AlphaBlend)
To understand how does work the alphablending in the normal mode, and try to adapt it for some painting blendmode like multiply/add and so.

I have try that :

Code: Select all

; key A to change the painting blendmode

Procedure CallbackFiltre(X, Y, SourceColor, TargetColor)
  If Alpha(SourceColor)=0 Or Alpha(TargetColor)=0
    A=Alpha(SourceColor)+Alpha(TargetColor)
    If A>255
      A=255
    EndIf
    If Alpha(TargetColor) = 0
      color = RGBA(Red(SourceColor),
                   Green(SourceColor),
                   Blue(SourceColor), 
                   A) 
    Else
      color = RGBA((Red(SourceColor)*Red(TargetColor))/255,
                   (Green(SourceColor)*Green(TargetColor))/255,
                   (Blue(SourceColor)*Blue(TargetColor))/255, 
                   A) 
    EndIf
    
  Else
    A=(Alpha(SourceColor)*Alpha(TargetColor))/255
    If A>255
      A=255
    EndIf
    color = RGBA((Red(SourceColor)*Red(TargetColor))/255,
                 (Green(SourceColor)*Green(TargetColor))/255,
                 (Blue(SourceColor)*Blue(TargetColor))/255, 
                 A) 
  EndIf
  ProcedureReturn color
EndProcedure
UseJPEGImageDecoder()
w=600
h=400
If OpenWindow(0, 0, 0, w, h, "Blendmode painting", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CreateImage(0,w,h,32,#PB_Image_Transparent)
  CreateImage(1,50,50,32,#PB_Image_Transparent)
  ; create the brush
  If StartDrawing(ImageOutput(1))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Circle(25, 25, 20, RGBA(205,150,150,255))
    StopDrawing()
  EndIf
  
  AddKeyboardShortcut(0, #PB_Shortcut_A, 0)
  
  CanvasGadget(0, 0, 0, w, h)
  If StartDrawing(CanvasOutput(0))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0,0,OutputWidth(), OutputHeight(),RGBA(200,200,200,255))
    StopDrawing()
  EndIf 
  Repeat
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Menu
      If EventMenu() = 0
        blendmode = 1-blendmode
      EndIf
      
    ElseIf Event = #PB_Event_Gadget And EventGadget() = 0 
      If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
        xx = GetGadgetAttribute(0, #PB_Canvas_MouseX)
        yy = GetGadgetAttribute(0, #PB_Canvas_MouseY)
        
        If StartDrawing(ImageOutput(0))
          If blendmode =0
            DrawingMode(#PB_2DDrawing_AlphaBlend)
          Else
            DrawingMode(#PB_2DDrawing_CustomFilter)
            CustomFilterCallback(@CallbackFiltre())
          EndIf
          ; it work with circle
          ; Circle(Xx, Yy, 10, RGBA(205,150,150,255))
          ; it doesn't works with image
          DrawAlphaImage(ImageID(1),Xx-25, Yy-25)
          StopDrawing()
        EndIf 
        ; update the canvas
        If StartDrawing(CanvasOutput(0))
          DrawingMode(#PB_2DDrawing_AllChannels)
          Box(0,0,OutputWidth(), OutputHeight(),RGBA(200,200,200,255))
          DrawAlphaImage(ImageID(0),0,0)
          StopDrawing()
        EndIf 
      Else
        
      EndIf
    EndIf    
    
  Until Event = #PB_Event_CloseWindow
EndIf
But when I paint with the blendmode (multiply, use the "A" key), it doesn't work properly.
If you have an idea how to fixe that, It will be great ;)

thank you for your answers ;).
User avatar
STARGÅTE
Addict
Addict
Posts: 2084
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: Equivalent to #PB_2DDrawing_AlphaBlend

Post by STARGÅTE »

When the source color is S and the target color is T then the new color is:

Code: Select all

r = Sr*Sa + Tr*(1-Sa)
g = Sg*Sa + Tg*(1-Sa)
b = Sb*Sa + Tb*(1-Sa)
a = Sa + Ta*(1-Sa)
while r, g, b are the colors and a the alpha value, all in the range 0 to 1
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Equivalent to #PB_2DDrawing_AlphaBlend

Post by Keya »

STARGÅTE, that's Occams razor right there - simple and beautiful :)
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: Equivalent to #PB_2DDrawing_AlphaBlend

Post by #NULL »

Here is a test code, with stargates formula added. You can ignore the other test cases with the nonsense I tried. :)

<edit>
fixed formula for alpha

Code: Select all

EnableExplicit
Define ww, wh, style, win, canvas, event, quit

ww=800
wh=600
style | #PB_Window_ScreenCentered
style | #PB_Window_SystemMenu
style | #PB_Window_MinimizeGadget

win = OpenWindow(#PB_Any, 50, 100, ww, wh, "", style)
AddKeyboardShortcut(win, #PB_Shortcut_Escape, 10)
canvas = CanvasGadget(#PB_Any, 0, 0, ww, wh)

Procedure filter(x, y, sourceColor, targetColor)
  Protected resultColor
  Protected.f r, g, b, a
  
  Select 6
    Case 1
      resultColor = sourceColor
    Case 2
      resultColor = targetColor
    Case 3
      r = Red(sourceColor)
;       Debug r
      r = Red(sourceColor) * (255.0 / Alpha(sourceColor))      
;       Debug r
;       Debug ""
      g = Green(sourceColor)
      b = Blue(sourceColor)
      a = Alpha(sourceColor)
      resultColor = RGBA(r, g, b, 50)
    Case 4
      r =   Red(sourceColor) * (Alpha(sourceColor) / 255.0)
      g = Green(sourceColor) * (Alpha(sourceColor) / 255.0)
      b =  Blue(sourceColor) * (Alpha(sourceColor) / 255.0)
      a = (Alpha(sourceColor) + Alpha(targetColor)) / 2.0
      resultColor = RGBA(r, g, b, 50)
    Case 5
      r = (  Red(sourceColor) * (Alpha(sourceColor) / 255.0) +   Red(targetColor) * (Alpha(targetColor) / 255.0)) / 2.0
      g = (Green(sourceColor) * (Alpha(sourceColor) / 255.0) + Green(targetColor) * (Alpha(targetColor) / 255.0)) / 2.0
      b = ( Blue(sourceColor) * (Alpha(sourceColor) / 255.0) +  Blue(targetColor) * (Alpha(targetColor) / 255.0)) / 2.0
      a = (Alpha(sourceColor) + Alpha(targetColor)) / 2.0
      resultColor = RGBA(r, g, b, 255)
    Case 6
      r = (  Red(sourceColor) * (Alpha(sourceColor) / 255.0) +   Red(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
      g = (Green(sourceColor) * (Alpha(sourceColor) / 255.0) + Green(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
      b = ( Blue(sourceColor) * (Alpha(sourceColor) / 255.0) +  Blue(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
      a = Alpha(sourceColor) + Alpha(targetColor) * (1.0 - Alpha(sourceColor)/255.0)
      resultColor = RGBA(r, g, b, a)
  EndSelect
  
  ProcedureReturn resultColor
EndProcedure

StartDrawing(CanvasOutput(canvas))
  DrawingMode(#PB_2DDrawing_AllChannels)
  Box(0, 0, OutputWidth(), OutputHeight(), $00fffffff)
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  Circle(50, 50, 30, $880000ff)
  Circle(90, 50, 30, $8800ff00)
  Circle(70, 70, 30, $88ff0000)
  DrawingMode(#PB_2DDrawing_CustomFilter)
  CustomFilterCallback(@filter())
  Circle(250, 50, 30, $880000ff)
  Circle(290, 50, 30, $8800ff00)
  Circle(270, 70, 30, $88ff0000)  
StopDrawing()

Repeat
  event = WaitWindowEvent(10)
  Select event
    Case #PB_Event_CloseWindow
      quit = #True
    Case #PB_Event_Menu
      Select EventMenu()
        Case 10
          quit = #True
      EndSelect
  EndSelect
Until quit
Last edited by #NULL on Thu Jun 17, 2021 11:10 am, edited 1 time in total.
User avatar
[blendman]
Enthusiast
Enthusiast
Posts: 297
Joined: Thu Apr 07, 2011 1:14 pm
Location: 3 arks
Contact:

Re: Equivalent to #PB_2DDrawing_AlphaBlend

Post by [blendman] »

HI

Thanks a lot for your answer ;).

@Stargate and #Null : I have tried your method, but it doesn't work properly.

I have modified your code example to see the "bug" :

Code: Select all

EnableExplicit
Define ww, wh, style, win, canvas, event, quit

ww=800
wh=600
style | #PB_Window_ScreenCentered
style | #PB_Window_SystemMenu
style | #PB_Window_MinimizeGadget

win = OpenWindow(#PB_Any, 50, 100, ww, wh, "", style)
AddKeyboardShortcut(win, #PB_Shortcut_Escape, 10)
canvas = CanvasGadget(#PB_Any, 0, 0, ww, wh)

Procedure filter(x, y, sourceColor, targetColor)
  Protected resultColor
  Protected.f r, g, b, a
  
      r = (  Red(sourceColor) * (Alpha(sourceColor) / 255.0) +   Red(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
      g = (Green(sourceColor) * (Alpha(sourceColor) / 255.0) + Green(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
      b = ( Blue(sourceColor) * (Alpha(sourceColor) / 255.0) +  Blue(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
      a = (Alpha(sourceColor) + Alpha(targetColor)) * (1.0 - Alpha(sourceColor))
      resultColor = RGBA(r, g, b, a)
   
  ProcedureReturn resultColor
EndProcedure

; Create 3 image of circle (because I use brush image ;)) (so, those 3 images are 3 brush with different colors for example)
Define i =0, c=0,w=60
For i=0 To 2
  CreateImage(i,w,w,32,#PB_Image_Transparent)
  If StartDrawing(ImageOutput(i))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Select i 
      Case 0
        c = RGBA(255,0,0,255)
      Case 1
        c = RGBA(0,255,0,255)
      Case 2
        c = RGBA(0,0,255,255)
    EndSelect
    Circle(w/2, w/2, w/2-1, c)
    StopDrawing()
  EndIf
Next

; draw on image 4 (the image 4 is the layer)
CreateImage(4,ww,wh,32,#PB_Image_Transparent)
If StartDrawing(ImageOutput(4))
  DrawingMode(#PB_2DDrawing_AlphaBlend)
  For i = 0 To 3
    DrawAlphaImage(ImageID(0),50,50)
    DrawAlphaImage(ImageID(1),90,50)
    DrawAlphaImage(ImageID(2),70,70)
  Next
  DrawingMode(#PB_2DDrawing_CustomFilter)
  CustomFilterCallback(@filter())
  For i =0 To 3
    DrawAlphaImage(ImageID(0),250,50)
    DrawAlphaImage(ImageID(1),290,50)
    DrawAlphaImage(ImageID(2),270,70)
  Next
  StopDrawing()
EndIf

; and draw the result (the layer) on the canvas
StartDrawing(CanvasOutput(canvas))
DrawingMode(#PB_2DDrawing_AllChannels)
Box(0, 0, OutputWidth(), OutputHeight(), RGBA(200,200,200,255))
DrawAlphaImage(ImageID(4),0,0)
StopDrawing()

Repeat
  event = WaitWindowEvent(10)
  Select event
    Case #PB_Event_CloseWindow
      quit = #True
    Case #PB_Event_Menu
      Select EventMenu()
        Case 10
          quit = #True
      EndSelect
  EndSelect
Until quit

THe result in image :
Image




And here is my code with your procedure adapted :

Code: Select all

Enumeration
  #BM_PaintingNormal
  #BM_PaintingNormalBorder
  #BM_PaintingMultiply
EndEnumeration

Procedure PaintingBMNormalBorder(X, Y, SourceColor, TargetColor)
   Protected resultColor
  Protected.f r, g, b, a
  r = (  Red(sourceColor) * (Alpha(sourceColor) / 255.0) +   Red(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  g = (Green(sourceColor) * (Alpha(sourceColor) / 255.0) + Green(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  b = ( Blue(sourceColor) * (Alpha(sourceColor) / 255.0) +  Blue(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  a = (Alpha(sourceColor) + Alpha(targetColor)) * (1.0 - Alpha(sourceColor))
  resultColor = RGBA(r, g, b, a)
  
  ProcedureReturn resultColor
EndProcedure

Procedure PaintingBMMultiply(X,Y,SourceColor, TargetColor)
  If Alpha(SourceColor)=0 Or Alpha(TargetColor)=0
    A=(Alpha(SourceColor)+Alpha(TargetColor))
    If A>255
      A=255
    EndIf
    If Alpha(TargetColor) = 0
      color = RGBA(Red(SourceColor),
                   Green(SourceColor),
                   Blue(SourceColor), 
                   A) 
    Else
      color = RGBA((Red(SourceColor)*Red(TargetColor))/255,
                   (Green(SourceColor)*Green(TargetColor))/255,
                   (Blue(SourceColor)*Blue(TargetColor))/255, 
                   A) 
    EndIf
    
  Else
    A=(Alpha(SourceColor)*Alpha(TargetColor))/255
    If A>255
      A=255
    EndIf
    color = RGBA((Red(SourceColor)*Red(TargetColor))/255,
                 (Green(SourceColor)*Green(TargetColor))/255,
                 (Blue(SourceColor)*Blue(TargetColor))/255, 
                 A) 
  EndIf
  ProcedureReturn color
EndProcedure

UseJPEGImageDecoder()
w=600
h=400

If OpenWindow(0, 0, 0, w, h, "Blendmode painting. A key to change the painting blendmode", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CreateImage(0,w,h,32,#PB_Image_Transparent)
  CreateImage(1,50,50,32,#PB_Image_Transparent)
  ; create the brush
  If StartDrawing(ImageOutput(1))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Circle(25, 25, 20, RGBA(205,150,150,255))
    StopDrawing()
  EndIf
  
  AddKeyboardShortcut(0, #PB_Shortcut_A, 0)
  
  CanvasGadget(0, 0, 0, w, h)
  If StartDrawing(CanvasOutput(0))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0,0,OutputWidth(), OutputHeight(),RGBA(200,200,200,255))
    StopDrawing()
  EndIf 
  Repeat
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Menu
      If EventMenu() = 0
        blendmode +1
        If blendmode> #BM_PaintingMultiply
          blendmode = 0
        EndIf
      EndIf
      
    ElseIf Event = #PB_Event_Gadget And EventGadget() = 0 
      If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
        xx = GetGadgetAttribute(0, #PB_Canvas_MouseX)
        yy = GetGadgetAttribute(0, #PB_Canvas_MouseY)
        
        If StartDrawing(ImageOutput(0))
          Select blendmode 
            Case #BM_paintingNormal ; bm painting normal
              DrawingMode(#PB_2DDrawing_AlphaBlend)
            Case #BM_PaintingNormalBorder ; bm painting normal by with
              DrawingMode(#PB_2DDrawing_CustomFilter)
              CustomFilterCallback(@PaintingBMNormalBorder())
            Case #BM_PaintingMultiply
              DrawingMode(#PB_2DDrawing_CustomFilter)
              CustomFilterCallback(@PaintingBMMultiply())
          EndSelect
          ; it work with circle
          ; Circle(Xx, Yy, 10, RGBA(205,150,150,255))
          ; it doesn't works with image
          DrawAlphaImage(ImageID(1),Xx-25, Yy-25)
          StopDrawing()
        EndIf 
        ; update the canvas
        If StartDrawing(CanvasOutput(0))
          DrawingMode(#PB_2DDrawing_AllChannels)
          Box(0,0,OutputWidth(), OutputHeight(),RGBA(200,200,200,255))
          DrawingMode(#PB_2DDrawing_AlphaBlend)
          DrawAlphaImage(ImageID(0),0,0)
          StopDrawing()
        EndIf 
      Else
        
      EndIf
    EndIf    
    
  Until Event = #PB_Event_CloseWindow
EndIf

THe result in image :

With DrawingMode(#PB_2DDrawing_AlphaBlend)
Image

With THe stargate function :
Image

It's an interesting result ;) (I will keep this function as a tool option :)), but it's not what we are looking for (the same result as DrawingMode(#PB_2DDrawing_AlphaBlend))

If you have an idea how to fixe that
thanks ;)

EDIT : I try to fixe the code, but it doesnt work as I would to use it on my "multiply" function :(

Work ok if the brush has alpha =255, but not if the brush with alpha <255

Code: Select all

Procedure filter(x, y, sourceColor, targetColor)
 Protected resultColor
  Protected.f r, g, b, a
  r = (  Red(sourceColor) * (Alpha(sourceColor) / 255.0) +   Red(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  g = (Green(sourceColor) * (Alpha(sourceColor) / 255.0) + Green(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  b = ( Blue(sourceColor) * (Alpha(sourceColor) / 255.0) +  Blue(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  If Alpha(sourceColor)=255
    a = Alpha(sourceColor)
  Else
    a = (Alpha(sourceColor) + Alpha(targetColor)) * (1.0 - Alpha(sourceColor))
  EndIf
  
  resultColor = RGBA(r, g, b, a)
  
  ProcedureReturn resultColor
Endprocedure
When I paint with a brush with alpha <255, we can see another problem :

With drawingmode(#PB_2DDrawing_AlphaBlend) :
Image

With the stargate function (modified) :
Image

My last code, to test the bug :

Code: Select all

Enumeration
  #BM_PaintingNormal
  #BM_PaintingNormalBorder
  #BM_PaintingMultiply
EndEnumeration

Procedure PaintingBMNormalBorder(X, Y, SourceColor, TargetColor)
   Protected resultColor
  Protected.f r, g, b, a
  r = (  Red(sourceColor) * (Alpha(sourceColor) / 255.0) +   Red(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  g = (Green(sourceColor) * (Alpha(sourceColor) / 255.0) + Green(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  b = ( Blue(sourceColor) * (Alpha(sourceColor) / 255.0) +  Blue(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  If Alpha(sourceColor)=255
   a = Alpha(sourceColor)
  Else
    a = (Alpha(sourceColor) + Alpha(targetColor)) * (1.0 - Alpha(sourceColor))
  EndIf
  
  resultColor = RGBA(r, g, b, a)
  
  ProcedureReturn resultColor
EndProcedure

Procedure PaintingBMMultiply(X,Y,SourceColor, TargetColor)
;   If Alpha(SourceColor)=0 Or Alpha(TargetColor)=0
;     A=(Alpha(SourceColor)+Alpha(TargetColor))
;     If A>255
;       A=255
;     EndIf
;     If Alpha(TargetColor) = 0
;       color = RGBA(Red(SourceColor),
;                    Green(SourceColor),
;                    Blue(SourceColor), 
;                    A) 
;     Else
;       color = RGBA((Red(SourceColor)*Red(TargetColor))/255,
;                    (Green(SourceColor)*Green(TargetColor))/255,
;                    (Blue(SourceColor)*Blue(TargetColor))/255, 
;                    A) 
;     EndIf
;     
;   Else
;     A=(Alpha(SourceColor)*Alpha(TargetColor))/255
;     If A>255
;       A=255
;     EndIf
;     color = RGBA((Red(SourceColor)*Red(TargetColor))/255,
;                  (Green(SourceColor)*Green(TargetColor))/255,
;                  (Blue(SourceColor)*Blue(TargetColor))/255, 
;                  A) 
;   EndIf
;    ProcedureReturn Color
  Protected resultColor
  Protected.f r, g, b, a
;   r = (  Red(sourceColor) * (Alpha(sourceColor) / 255.0) *   Red(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
;   g = (Green(sourceColor) * (Alpha(sourceColor) / 255.0) * Green(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
;   b = ( Blue(sourceColor) * (Alpha(sourceColor) / 255.0) *  Blue(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
;   
  If Alpha(TargetColor) = 0
   r = Red(SourceColor)
   g = Green(SourceColor)
   b = Blue(SourceColor)
  Else
    r = (  Red(sourceColor) *  Red(targetColor)   )/ 255.0
    g = (Green(sourceColor) *  Green(targetColor) )/ 255.0
    b = ( Blue(sourceColor) *  Blue(targetColor)  )/ 255.0
  EndIf
  
  If Alpha(sourceColor)=255
    a = Alpha(sourceColor)
  Else
    a = (Alpha(sourceColor) + Alpha(targetColor)) * (1.0 - Alpha(sourceColor))
  EndIf
  resultColor = RGBA(r, g, b, a)
  ProcedureReturn resultColor
EndProcedure

UseJPEGImageDecoder()
w=600
h=400

If OpenWindow(0, 0, 0, w, h, "Blendmode painting. A key to change the painting blendmode", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CreateImage(0,w,h,32,#PB_Image_Transparent)
  CreateImage(1,50,50,32,#PB_Image_Transparent)
  ; create the brush
  If StartDrawing(ImageOutput(1))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Circle(25, 25, 20, RGBA(205,150,150,255))
    StopDrawing()
  EndIf
  
  AddKeyboardShortcut(0, #PB_Shortcut_A, 0)
  
  CanvasGadget(0, 0, 0, w, h)
  If StartDrawing(CanvasOutput(0))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0,0,OutputWidth(), OutputHeight(),RGBA(200,200,200,255))
    StopDrawing()
  EndIf 
  Repeat
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Menu
      If EventMenu() = 0
        blendmode +1
        If blendmode> #BM_PaintingMultiply
          blendmode = 0
        EndIf
      EndIf
      
    ElseIf Event = #PB_Event_Gadget And EventGadget() = 0 
      If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
        xx = GetGadgetAttribute(0, #PB_Canvas_MouseX)
        yy = GetGadgetAttribute(0, #PB_Canvas_MouseY)
        
        ; draw on the layer with a brush image
        If StartDrawing(ImageOutput(0))
          Select blendmode 
            Case #BM_paintingNormal ; bm painting normal
              DrawingMode(#PB_2DDrawing_AlphaBlend)
            Case #BM_PaintingNormalBorder 
              DrawingMode(#PB_2DDrawing_CustomFilter)
              CustomFilterCallback(@PaintingBMNormalBorder())
            Case #BM_PaintingMultiply
              DrawingMode(#PB_2DDrawing_CustomFilter)
              CustomFilterCallback(@PaintingBMMultiply())
          EndSelect
          ; it work with circle
          ; Circle(Xx, Yy, 10, RGBA(205,150,150,255))
          ; it doesn't works with image
          DrawAlphaImage(ImageID(1),Xx-25, Yy-25, 40)
          StopDrawing()
        EndIf 
        
        ; update the canvas
        If StartDrawing(CanvasOutput(0))
          DrawingMode(#PB_2DDrawing_AllChannels)
          Box(0,0,OutputWidth(), OutputHeight(),RGBA(200,200,200,255))
          ; draw the layers
          DrawingMode(#PB_2DDrawing_AlphaBlend)
          DrawAlphaImage(ImageID(0),0,0)
          StopDrawing()
        EndIf 
      Else
        
      EndIf
    EndIf    
    
  Until Event = #PB_Event_CloseWindow
EndIf

If you have an idea how to fixe that ;)
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4659
Joined: Sun Apr 12, 2009 6:27 am

Re: Equivalent to #PB_2DDrawing_AlphaBlend

Post by RASHAD »

Hi
It may help somehow

Code: Select all

Enumeration
  #BM_PaintingNormal
  #BM_PaintingNormalBorder
  #BM_PaintingMultiply
EndEnumeration

UseJPEGImageDecoder()
w=600
h=400

If OpenWindow(0, 0, 0, w, h, "Blendmode painting. A key to change the painting blendmode", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CreateImage(0,w,h,32,#PB_Image_Transparent)
  CreateImage(1,26,26,32,#PB_Image_Transparent)
  ; create the brush
  If StartDrawing(ImageOutput(1))
    DrawingMode(#PB_2DDrawing_AllChannels)    
    Box(0,0,26,26,$01000000)
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    Circle(13,13,10, RGBA(205,150,150,255))
    StopDrawing()
  EndIf  
  
  AddKeyboardShortcut(0, #PB_Shortcut_A, 0)
  
  CanvasGadget(0, 0, 0, w, h)
  If StartDrawing(CanvasOutput(0))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0,0,OutputWidth(), OutputHeight(),RGBA(200,200,200,255))
    StopDrawing()
  EndIf 
  Repeat
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Menu
      If EventMenu() = 0
        Run ! 1
        If Run = 1
          color = RGBA(235, 175, 160, 255)
        Else
          color = RGBA(205,150,150,255)
        EndIf
        StartDrawing(ImageOutput(1))
        DrawingMode(#PB_2DDrawing_AllChannels)    
        Box(0,0,26,26,$01000000)
        DrawingMode(#PB_2DDrawing_AlphaBlend)
        Circle(13,13,10, color)
        StopDrawing()
      EndIf
      
    ElseIf Event = #PB_Event_Gadget And EventGadget() = 0 
      If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
        xx = GetGadgetAttribute(0, #PB_Canvas_MouseX)
        yy = GetGadgetAttribute(0, #PB_Canvas_MouseY)
        
        If StartDrawing(ImageOutput(0))
          DrawAlphaImage(ImageID(1),Xx-25, Yy-25)
          StopDrawing()
        EndIf 
        ; update the canvas
        If StartDrawing(CanvasOutput(0))
          DrawingMode(#PB_2DDrawing_AllChannels)
          Box(0,0,OutputWidth(), OutputHeight(),RGBA(200,200,200,255))
          DrawingMode(#PB_2DDrawing_AlphaBlend)
          DrawAlphaImage(ImageID(0),0,0)                   
          StopDrawing()
        EndIf 
      Else
        
      EndIf
    EndIf    
    
  Until Event = #PB_Event_CloseWindow
EndIf


Egypt my love
User avatar
STARGÅTE
Addict
Addict
Posts: 2084
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: Equivalent to #PB_2DDrawing_AlphaBlend

Post by STARGÅTE »

My alpha calculation was incorrect in your code.
Use:

Code: Select all

      r = (  Red(sourceColor) * (Alpha(sourceColor) / 255.0) +   Red(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
      g = (Green(sourceColor) * (Alpha(sourceColor) / 255.0) + Green(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
      b = ( Blue(sourceColor) * (Alpha(sourceColor) / 255.0) +  Blue(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
      a = Alpha(sourceColor) + Alpha(targetColor) * (1.0 - Alpha(sourceColor)/255.0)
      resultColor = RGBA(r, g, b, a)
 
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: Equivalent to #PB_2DDrawing_AlphaBlend

Post by #NULL »

Sorry, my fault. I fixed it in my code above.
User avatar
[blendman]
Enthusiast
Enthusiast
Posts: 297
Joined: Thu Apr 07, 2011 1:14 pm
Location: 3 arks
Contact:

Re: Equivalent to #PB_2DDrawing_AlphaBlend

Post by [blendman] »

STARGÅTE wrote: Thu Jun 17, 2021 8:22 am My alpha calculation was incorrect in your code.
HI thank you a lot

Thanks to your calculation, I have fixed my code, and it works fine now :).
I have adapted your calculation for some paintint blendmode (multiply, add, screen...), like in gimp/photoshop :)).
That's "painting blendmode", not "layer blendmode", it's not exactly the same, even if layer blendmode create same effect, but layers ^^.
With "painting blendmode", the brush image is drawn on the layer with the selected blendmode.
With layer blendmode (canvas/image), it's a superposition of layers with blendmode which produce the effect (add, multiply, burn...).

Here is the final code :

Code: Select all

; blendmode for brush paint, by blendman, help by stargate, #NULL
Enumeration
  ; painting blendmode
  #BM_PaintingDefault
  #BM_PaintingNormal
  #BM_PaintingNormalBorder
  #BM_PaintingMultiply
  #BM_PaintingADD
  #BM_PaintingScreen
  #BM_PaintingLast
  ; gadgets
  #Canvas = 0
  #G_BrushBlendmode
  #G_brushSize
  #G_brushAlpha
  #G_brushPas
  ; images
  #Img_brush = 0
  #Img_Layer 
EndEnumeration

;{ structures
Structure Canvas
  LeftButtonDown.i
  RightButtonDown.i
EndStructure
Global This.Canvas

Structure VPoint
  x.f
  y.f
EndStructure
Global PreviousPoint.VPoint
Global CurrentPoint.VPoint, LastPoint.VPoint

Structure sBrush
  size.w
  alpha.a
  blendmode.a
  Pas.w ; space betwen two dot
EndStructure
Global Brush.sBrush
Brush\alpha = 140
Brush\blendmode = 0
Brush\pas = 20
Brush\Size = 50
;}

Global draw

;{ procedures
; the blendmode for painting (not for the layer ;))
Procedure PaintingBMNormalBorder(X, Y, SourceColor, TargetColor)
  ; be carefull with this mode, it can give some weird result ^^
  Protected resultColor
  Protected r, g, b
  Protected a
  r = (  Red(sourceColor) * (Alpha(sourceColor) / 255.0) +   Red(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  g = (Green(sourceColor) * (Alpha(sourceColor) / 255.0) + Green(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  b = ( Blue(sourceColor) * (Alpha(sourceColor) / 255.0) +  Blue(targetColor) * (1 - (Alpha(sourceColor) / 255.0)))
  If Alpha(sourceColor)=255
    a = Alpha(sourceColor)
  Else
    a = (Alpha(sourceColor) + Alpha(targetColor)) * (1.0 - Alpha(sourceColor))
  EndIf
  
  resultColor = RGBA(r, g, b, a)
  ProcedureReturn resultColor
  
EndProcedure  
Procedure PaintingBMNormal(X, Y, SourceColor, TargetColor)
  
  ; This mode is a few better than the default #pb_2Ddrawing_alphablend, with brtush\alpha<40
  Protected resultColor
  Protected r, g, b
  Protected a
  
  u.d =255.0
  If Alpha(targetColor)<=2
    r = Red(sourceColor) 
    g = Green(sourceColor) 
    b = Blue(sourceColor) 
  Else
    r = (  Red(sourceColor) * (Alpha(sourceColor) / u) +   Red(targetColor) * (1 - (Alpha(sourceColor) / u)))
    g = (Green(sourceColor) * (Alpha(sourceColor) / u) + Green(targetColor) * (1 - (Alpha(sourceColor) / u)))
    b = ( Blue(sourceColor) * (Alpha(sourceColor) / u) +  Blue(targetColor) * (1 - (Alpha(sourceColor) / u)))
  EndIf
  a = Alpha(sourceColor) + Alpha(targetColor) * (1.0 - Alpha(sourceColor)/u)
  resultColor = RGBA(r, g, b, a)
  ProcedureReturn resultColor
EndProcedure
Procedure PaintingBMMultiply(X,Y,SourceColor, TargetColor)
  
  Protected resultColor
  Protected.f r, g, b, a
  u.d =255
  c.d = (brush\alpha)/255

  If Alpha(TargetColor) <5 ; And Alpha(sourceColor)<>0
    r = Red(SourceColor)
    g = Green(SourceColor)
    b = Blue(SourceColor)
  Else
    r = (  Red(sourceColor) * Red(targetColor)  )/ u
    If r>255
      r=255
    EndIf
    g = (Green(sourceColor) * Green(targetColor) )/ u
    If g>255
      g=255
    EndIf
    b = ( Blue(sourceColor) * Blue(targetColor)  )/ u
    If b>255
      b= 255
    EndIf
  EndIf
  
  If Alpha(targetColor)=0
    a = Alpha(sourceColor)
  Else
    a =( Alpha(sourceColor) + Alpha(targetColor) * (1.0 - Alpha(sourceColor)/255.0))
  EndIf
  If a>255
    a=255
  EndIf
  
  resultColor = RGBA(r, g, b, a)
  ProcedureReturn resultColor
EndProcedure
Procedure PaintingBMAdd(X,Y,SourceColor, TargetColor)
  
  Protected resultColor
  Protected.f r, g, b, a
  u.d = (0.1*brush\alpha)/255
  If Alpha(TargetColor) <5 ;And Alpha(sourceColor)<>0
    r = Red(SourceColor)
    g = Green(SourceColor)
    b = Blue(SourceColor)
  Else
    r = (  Red(sourceColor)*u + Red(targetColor)  )
    If r>255
      r=255
    EndIf
    g = (Green(sourceColor)*u + Green(targetColor))
    If g>255
      g=255
    EndIf
    b = ( Blue(sourceColor)*u + Blue(targetColor))
    If b>255
      b=255
    EndIf
  EndIf
  
  If Alpha(targetColor)=0
    a = Alpha(sourceColor)
  Else
    a =( Alpha(sourceColor) + Alpha(targetColor)  * (1.0 - Alpha(sourceColor)/255.0))
  EndIf
  If a>255
    a=255
  EndIf
  
  resultColor = RGBA(r, g, b, a)
  ProcedureReturn resultColor
EndProcedure
Procedure PaintingBMScreen(X,Y,SourceColor,TargetColor)
  
  Protected resultColor
  Protected.f r, g, b, a
  u.d =(0.1*brush\alpha)/255
  If Alpha(TargetColor) <5 ;And Alpha(sourceColor)<>0
    r = Red(SourceColor)
    g = Green(SourceColor)
    b = Blue(SourceColor)
  Else
    r = 255 -((255-Red(SourceColor)*u)*(255-Red(TargetColor)))/255
    g = 255 -((255-Green(SourceColor)*u)*(255-Green(TargetColor)))/255
    b = 255 -((255-Blue(SourceColor)*u)*(255-Blue(TargetColor)))/255   
  EndIf

  If Alpha(targetColor)=0
    a = Alpha(sourceColor)
  Else
    a =( Alpha(sourceColor) + Alpha(targetColor)  * (1.0 - Alpha(sourceColor)/255.0))
  EndIf
  If a>255
    a=255
  EndIf
  
  resultColor = RGBA(r, g, b, a)
  ProcedureReturn resultColor
EndProcedure

; for drawing
Macro distance(x1,y1,x2,y2)   
  Int(Sqr((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)) )       
EndMacro
Macro direction(x1,y1,x2,y2) ; get angle
  ATan2((y2- y1),(x2- x1))
EndMacro
Procedure EventDraw()
  ; help by falsam
  Protected Distance, first
  Protected CountPoint, N
  
  Protected x = GetGadgetAttribute(#Canvas, #PB_Canvas_MouseX)
  Protected y = GetGadgetAttribute(#Canvas, #PB_Canvas_MouseY)
  
  Protected NextPointX.f, NextPointY.f
  Protected DeltaX.f, DeltaY.f
  
  Define direction.d, interval.d, pas.d, distBetween2dot.d, thesize.w
  Define x1.d, y1.d, x2.f, y2.f, X3.f, y3.f, nextDot.i, color.q
  
  ; define the alpha of the brush
  Thealpha = Brush\Alpha
  
  With This
    
    Select EventType()
        
      Case #PB_EventType_LeftButtonDown
        \LeftButtonDown = #True
        PreviousPoint\x = x
        PreviousPoint\Y = y
        If first = 0
          First = 1
          Draw = #True
        EndIf
        
      Case #PB_EventType_LeftButtonUp
        \LeftButtonDown = #False
        CurrentPoint\x = x
        CurrentPoint\Y = y
        Draw = #False
        First = 0
        
      Case #PB_EventType_MouseMove   
        Draw = #False
        If \LeftButtonDown 
          If Thealpha >0  And Thealpha <=255
            Draw = #True
          EndIf
          CurrentPoint\x = x
          CurrentPoint\Y = y
        EndIf
    EndSelect
    
    ; Drawing
    If Draw
      
      ; pas = to calculate the distance between two dots 100/100 => distance=TheSize
      Pas = Brush\pas/100
      
      ; calcul the size
      Thesize = Brush\size
      
      If thesize >=1 And Thealpha > 0 And thealpha <=255
        x1 = PreviousPoint\x
        y1 = PreviousPoint\y   
        x2 = CurrentPoint\x
        y2 = CurrentPoint\y
        
        ; the distancebetween Two dots
        distBetween2dot = Thesize*Pas
        
        ;distance between two vectors
        Distance = Distance(x1,y1, x2,y2)
        
        ; number of dots to draw
        CountPoint = Distance/(Pas*Thesize)
        
        ; Draw !
        If StartDrawing(ImageOutput(#Img_layer))
          
          Select Brush\blendmode 
            Case #BM_paintingNormal ; bm painting normal
              DrawingMode(#PB_2DDrawing_AlphaBlend)
            Case #BM_PaintingNormalBorder ; bm normal with a strange behavior ^^
              DrawingMode(#PB_2DDrawing_CustomFilter)
              CustomFilterCallback(@PaintingBMNormalBorder())
            Case #BM_PaintingNormal ; bm normal, but a few better with alpha <50 :)
              DrawingMode(#PB_2DDrawing_CustomFilter)
              CustomFilterCallback(@PaintingBMNormal())
            Case #BM_PaintingMultiply
              DrawingMode(#PB_2DDrawing_CustomFilter)
              CustomFilterCallback(@PaintingBMMultiply())
            Case #BM_PaintingScreen
              DrawingMode(#PB_2DDrawing_CustomFilter)
              CustomFilterCallback(@PaintingBMScreen())
            Case #BM_PaintingADD
              DrawingMode(#PB_2DDrawing_CustomFilter)
              CustomFilterCallback(@PaintingBMAdd())
          EndSelect
          
          If distBetween2dot <= distance And CountPoint > 0 And first = 0
            
            direction = direction(x1, y1, x2, y2)
            For N = 1 To CountPoint
              ; then draw the dots
              x3 = x1 + n * distBetween2dot * Sin(direction)
              y3 = y1 + n * distBetween2dot * Cos(direction)
              DrawAlphaImage(ImageID(#Img_brush), x3-Thesize/2, y3-Thesize/2, Thealpha)
            Next
            PreviousPoint\x = x3
            PreviousPoint\y = y3
          Else
            If first = 1
              DrawAlphaImage(ImageID(#Img_brush), x1-Thesize/2, y1-Thesize/2) ; , Thealpha)
            EndIf
          EndIf
          StopDrawing()
        EndIf
      EndIf
    EndIf
  EndWith
EndProcedure

Procedure UpdateBrush(create=0)
  
  s = brush\size
  
  ; we have to recreate the brush if needed
  If create = 1
    If IsImage(#Img_brush)
      FreeImage(#Img_brush)
    EndIf
    If CreateImage(#Img_brush,s,s,32,#PB_Image_Transparent)
    EndIf
  EndIf
  
  ; Draw the brush
  If StartDrawing(ImageOutput(#Img_brush))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Select brush\blendmode
      Case #BM_PaintingMultiply
        Box(0,0,s,s,RGBA(255,255,255,255-brush\alpha))
        DrawingMode(#PB_2DDrawing_AlphaBlend)
      Case #BM_PaintingADD, #BM_PaintingScreen
        Box(0,0,s,s,RGBA(0,0,0,0))
      Default
        Box(0,0,s,s,RGBA(0,0,0,0))
    EndSelect
    Circle(s/2, s/2, s/2-2, RGBA(200,150,150,brush\alpha))
    StopDrawing()
  EndIf
  
EndProcedure
Procedure UpdateCanvas(clear=0)
  If StartDrawing(CanvasOutput(#canvas))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0,0,OutputWidth(), OutputHeight(),RGBA(200,200,200,255))
    ; draw the layers
    If clear=0
      DrawingMode(#PB_2DDrawing_AlphaBlend)
      DrawAlphaImage(ImageID(#Img_Layer),0,0)
    EndIf
    StopDrawing()
  EndIf 
EndProcedure
Procedure Addtrackbar(gadget,x,y,w,h,min,max,tip$,state)
  TrackBarGadget(gadget,x,y,w,h,min,max)
  SetGadgetState(gadget,state)
  GadgetToolTip(gadget,tip$)
EndProcedure
;}


w=800
h=400
If OpenWindow(0, 0, 0, w, h, "Blendmode painting.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  CreateImage(#Img_Layer,w-200,h,32,#PB_Image_Transparent)
  updateBrush(1)
  
  blendmode$="default,normal,normalBorder,multiply,add,screen,"
  nb = CountString(blendmode$, ",")-1
  ; gadget
  Addtrackbar(#G_brushSize,10,10,150,20,1,150,"Brush size",brush\size)
  Addtrackbar(#G_brushAlpha,10,40,150,20,0,255,"Brush Alpha",brush\alpha)
  Addtrackbar(#G_brushPas,10,70,150,20,1,500,"Brush Pas (space between dots)",brush\pas)
  ComboBoxGadget(#G_BrushBlendmode,10,100,150,20)
  For i=0 To nb
    AddGadgetItem(#G_BrushBlendmode,i,StringField(blendmode$,i+1,","))
  Next
  SetGadgetState(#G_BrushBlendmode,0)
  GadgetToolTip(#G_BrushBlendmode, "painting blendmode")
  
  CanvasGadget(#canvas,200,0,w-200,h)
  updatecanvas()
  
  Repeat
    
    Event = WaitWindowEvent()
    EventGadget =EventGadget() 
    
    If Event = #PB_Event_Gadget 
      Select EventGadget 
        Case #canvas
          If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
            ; draw on the layer with a brush image
            Eventdraw()
            ; update the canvas
            updatecanvas()
          EndIf
        Case #G_brushSize
          brush\size= GetGadgetState(EventGadget)
          UpdateBrush(1)
        Case #G_brushAlpha
          brush\alpha= GetGadgetState(EventGadget)
          UpdateBrush()
        Case #G_brushPas
          brush\Pas = GetGadgetState(EventGadget)
        Case #G_BrushBlendmode
          brush\blendmode = GetGadgetState(EventGadget)
          UpdateBrush()
      EndSelect
      
    EndIf    
    
  Until Event = #PB_Event_CloseWindow
EndIf
The result :
Image

Thank you a lot for all contributors ;)

I have to add that in my animatoon 2D painting software :).

Cheers !
Post Reply