Page 1 sur 2

PB transparence non voulue

Publié : sam. 22/oct./2016 17:27
par JohnJohnsonSHERMAN
Salut à tous :)

J'ai essayé cet aprém d'imiter l'effet de parasite ou de brouillage qu'il y a sur l'écran de chargement des maps dans les Battlefields (3 et 4)... cet effet se compose d'un décalage vers la droite des composantes bleues d'une image et vers la gauche pour les composantes rouges... C'est comme si on prenait une image, qu'on isole sur des calques les canaux rouge, vert et bleu, et qu'ensuite on fait glisser les calques les uns sur les autres.
En principe ca marche trés bien, et le petit code que j'ai fait aussi... A un détail prés :
  • Ceci est l'image d'origine :Image
    Normalement losqu'on décompose cette image selon 3 canaux (un R, un G et un B), on devrait avoir sur chacun les composantes R,G ou B de chaque pixel, comme ceci :
    Image
    Ici on voit bien que le rouge pur (FFFFFF) n'est présent que sur le calque rouge, normal, il ne contient rien d'autre. Et il est bien rouge (RGB 255,255,255). Il en est de même pour les autres couleurs sur les autres calques. Le rectangle blanc lui est présent sur chacun des calques, avec une intensité maximale. Normal aussi... Mais alors, quand on superpose les 3 calques, le blanc devrait bien être blanc( 255 rouge + 255 vert + 255 bleu)? Et bin...
  • Ceci est l'image lorsque les 3 calques sont superposés dans mon application (une fois sur un fond noir, une autre sur fond blanc):ImageNon... le blanc n'est pas blanc... En fait il reste trop de bleu par rapport au reste et pas assez de couleur en tout. Le fond est même visible a travers.
Bon maintenant que le probléme est exposé, voici mon code (sale come d'hab', j'ai pas trop pris de temps de le "propreter" :mrgreen: ) :

Code : Tout sélectionner

File$ = OpenFileRequester("Choisissez une image","","*.*",0)
Path$ = GetPathPart(File$)
If File$ = ""
  End 
EndIf

Debug "Chargement..."

UseJPEGImageDecoder()
UseJPEG2000ImageDecoder()
UsePNGImageDecoder()

Enumeration 
  #Canvas
  #Image_red
  #Image_green
  #Image_blue
  #Image_base
  #Window
  #timer 
  #ImgX=30
  #ImgY=0
  #ImgWdth=400
  #ImgHgth=400
  #MaxDecal = 30
EndEnumeration

Enumeration Channels
  #Red
  #Green
  #Blue
  #Alpha
EndEnumeration

Declare ParasiteRGB()
Declare thRGB(param)
Declare SplitChannels(Image,OutputR,OutputG, OutputB)
Declare thSplitChannel(Channel)

Global progress,channel,total, Width, Height, thRed, thBlue, thGreen, Image, OutputR, OutputG, OutputB

OutputR = #Image_red
OutputG = #Image_green
OutputB = #Image_blue

LoadImage(#Image_base,File$)

Debug "Ok ca commence"

OpenWindow(1,0,0,250,30,"Chargement...",#PB_Window_ScreenCentered)
ProgressBarGadget(1,10,5,230,20,0,1000)
SplitChannels(#Image_base, #Image_red, #Image_green, #Image_blue)
Debug "Threads lancés"

Repeat
  WaitWindowEvent(50)
  SetGadgetState(1,(progress/total)*1000)
  Debug progress
Until Not IsThread(thRed) And Not IsThread(thGreen) And Not IsThread(thBlue)

CloseWindow(1)

;On enregistre le résultat donné pour chaque canal, pour vérifier
SaveImage(#Image_red,Path$ + "tmpR.bmp")
SaveImage(#Image_green,Path$ + "tmpG.bmp")
SaveImage(#Image_blue,Path$ + "tmpB.bmp")
  
OpenWindow(#Window,0,0,800,800,"Analogic display (BF4)",#PB_Window_ScreenCentered| #PB_Window_SystemMenu)
CanvasGadget(#Canvas,0,0,800,800)

AddWindowTimer(#Window,#Timer,1500)

Repeat
  event = WaitWindowEvent()
  If event = #PB_Event_Timer And EventTimer() = #timer
    ParasiteRGB()
  EndIf
  
Until event = #PB_Event_CloseWindow

Procedure ParasiteRGB()
  If Not IsThread(thRGB)
    CreateThread(@thRGB(), 1)
  Else
    Debug "Already running..."
  EndIf
EndProcedure

Procedure thRGB(param)
  Decal = Random(#MaxDecal,2)
  For i= 0 To Decal Step 2
    StartDrawing(CanvasOutput(#Canvas))
    Box(0,0,800,800,0)
    DrawAlphaImage(ImageID(#Image_red),#ImgX+i,#ImgY,(255/3))
    DrawAlphaImage(ImageID(#Image_blue),#ImgX-i,#ImgY,(255/3))
    DrawAlphaImage(ImageID(#Image_green),#ImgX,#ImgY,(255/3))
    StopDrawing()
    Delay(1)
  Next
  For i = Decal To 0 Step -1
    StartDrawing(CanvasOutput(#Canvas))
    Box(0,0,800,800,0)
    DrawAlphaImage(ImageID(#Image_red),#ImgX+i,#ImgY,(255/3))
    DrawAlphaImage(ImageID(#Image_blue),#ImgX-i,#ImgY,(255/3))
    DrawAlphaImage(ImageID(#Image_green),#ImgX,#ImgY,(255/3))
    StopDrawing()
    Delay(1)
  Next
  StartDrawing(CanvasOutput(#Canvas))
  ;DrawImage(ImageID(#Image_base),#imgX,#ImgY) ;Commenter pour voir simplement la superposition foirée
  StopDrawing()
EndProcedure

Procedure SplitChannels(Image,OutputR, OutputG, OutputB)
  Debug ~"Canal rouge\t:"+OutputR+"\nCanal vert\t:"+OutputG+"\nCanal bleu\t:"+OutputB
  StartDrawing(ImageOutput(Image))
  Width = OutputWidth()
  Height = OutputHeight()
  Depth = OutputDepth()
  
  total = 3*(Width * Height)
  CreateImage(OutputR,Width,Height,Depth,0)
  CreateImage(OutputG,Width,Height,Depth,0)
  CreateImage(OutputB,Width,Height,Depth,0)
  
  Global Dim Color(Width,Height)
  channel = 0
  
  For x = 0 To Width-1
    For y = 0 To Height-1
      Color(x,y) = Point(x,y)
    Next
    progress +1
  Next
  StopDrawing()
  
  thRed = CreateThread(@thSplitChannel(),#Red)
  thGreen = CreateThread(@thSplitChannel(), #Green)
  thBlue = CreateThread(@thSplitChannel(), #Blue)
  
EndProcedure

Procedure thSplitChannel(Channel)
  Select Channel
    Case #Red
      channel +1
      StartDrawing(ImageOutput(OutputR))
      For x = 0 To Width-1
        For y = 0 To Height-1
          Plot(x,y,RGB(Red(Color(x,y)),0,0))
        Next
        progress +1
      Next
      StopDrawing()
      
    Case #Green
      channel +1
      StartDrawing(ImageOutput(OutputG))
      For x = 0 To Width-1
        For y = 0 To Height-1
          Plot(x,y,RGB(0,Green(Color(x,y)),0))
        Next
        progress +1
      Next
      StopDrawing()
      
    Case #Blue
      channel +1
      StartDrawing(ImageOutput(OutputB))
      For x = 0 To Width-1
        For y = 0 To Height-1
          Plot(x,y,RGB(0,0,Blue(Color(x,y))))
        Next
        progress +1
      Next
      StopDrawing()
  EndSelect
EndProcedure
je suppose que c'est de la faute de DrawAlphaImage() mais je vois pas bien où se trouve le bug... Surement entre la chaise et le clavier comme d'hab :mrgreen:

Re: PB transparence non voulue

Publié : sam. 22/oct./2016 17:43
par Zorro
j'ai pas testé mais je vois vite fait que tu fait 2 boucles differentes

Code : Tout sélectionner

 For i= 0 To Decal Step 2
puis plus loin

Code : Tout sélectionner

For i = Decal To 0 Step -1
ça reviens pas sur ses pattes , c'est voulu ??

logiquement je m'attendais a trouver

Code : Tout sélectionner

For i = Decal To 0 Step -2 ; <<<< -2 

Re: PB transparence non voulue

Publié : sam. 22/oct./2016 17:50
par JohnJohnsonSHERMAN
Si c'est voulu...C'est ca l'effet recherché : l'image semble se "décomposer" puis revient... Seulement quand elle revient, les couleurs de départ de se reconstituent pas.... :(

Re: PB transparence non voulue

Publié : sam. 22/oct./2016 17:53
par Zorro
oui mais si elle ne reviens pas exactement au meme endroit
il y aura un decalae d'un pixel !

d'un coté tu decal en marchant de 2 point en 2 point
et de l'autre te reviens en reculant d'un point par un point

forcement ça ne reviens pas au meme endroit il me semble
(mais je dis peut etre une betise )

Re: PB transparence non voulue

Publié : sam. 22/oct./2016 18:07
par JohnJohnsonSHERMAN
Mais comme l'image n'est pas modifiée pendant l'animation, ca ne devrait pas affecter les couleurs non?
En fait je créée 3 images : une par canal RGB, et ce au démarrage du programme, puis je ne fait que déplacer ces images dans un canvas, avec de la transparence. D'ailleurs, elles reviennent à leur place, sinon sur ma 3é image (celle des résultats), on verrait des bandes rouges ou bleues sur les cotés des carrés blancs... Le probléme se passe pendant l'animation et concerne la perte d'une partie des couleurs... Ce qu'il faudrait c'est un mode de dessin ou chaque couleur s'aditionne à la précédente au lieu de l'écraser dans le mode par défaut...

Re: PB transparence non voulue

Publié : sam. 22/oct./2016 18:11
par Zorro
oui tu as raison, excuse, moi
je n'avais pas testé ton code :oops:

Re: PB transparence non voulue

Publié : sam. 22/oct./2016 18:13
par JohnJohnsonSHERMAN
Ah ce Dobro ^^

Bon je reviens dessus demain, en espérant que quelqun me tirera de ce gouffre d'incompréhention (Ô grand Fred, n'aurais tu pas moyen d'ajouter le mode #PB_2dDrawing_Add aux modes de la lib 2d Drawing?)

Re: PB transparence non voulue

Publié : sam. 22/oct./2016 18:16
par Zorro
moi demain, je ne serai pas la , donc je ne pourrai pas
refaire ce code ... bon courage

Re: PB transparence non voulue

Publié : sam. 22/oct./2016 19:52
par Ar-S
J'ai pas testé le code mais ce que tu as écris me gène.
Ici on voit bien que le rouge pur (FFFFFF) n'est présent que sur le calque rouge, normal, il ne contient rien d'autre. Et il est bien rouge (RGB 255,255,255)
En PB on est en BGR donc rouge = $0000FF (et pas FFFFFF)
Idem pour rouge (RGB 255,255,255)... Non, rouge = (RGB 255,0,0)

Je me dis que c'est une erreur de syntaxe ou une phrase mal dite mais au cas ou...

Re: PB transparence non voulue

Publié : sam. 22/oct./2016 20:05
par JohnJohnsonSHERMAN
C'est une erreur de ma part uniquement dans le message... Dans le code, j'utilise Red() Green() et Blue()... :oops:
En effet, le rouge c'est FF0000 en RGB... donc RGB(255,0,0) sur pb.

Re: PB transparence non voulue

Publié : sam. 22/oct./2016 23:00
par falsam
Strange ce code. Faudrait voir ne plus abuser de Kouign-amann hein ?^^

Comme ça tu décides de la transparence pour chacun des calques ? ou alors je n'ai pas compris le rendu que tu souhaites et dans ce cas toutes mes excuses pour cette moquerie.

A priori DrawingMode(#PB_2DDrawing_XOr) pourait être la solution.

Voila mon code sans thread et avec une seule image.

Code : Tout sélectionner

EnableExplicit

Enumeration Window
  #mainForm
EndEnumeration

Enumeration Gadget
  #Result
EndEnumeration

Enumeration Timer
  #T0
EndEnumeration

Structure NewPoint
  ;Position x, y, z
  x.i
  y.i
  
  ;Couleur R G B
  r.i
  g.i
  b.i
EndStructure

;Tableau contenant l'image
Global Dim image.NewPoint(0)

;Plan de l'application
Declare Start()
Declare SplitChannels()
Declare RenderImage()
Declare Exit()

Start()

Procedure Start()
  UseJPEGImageDecoder()
  
  OpenWindow(#mainForm, 0, 0, 800, 600, "Kouign-amann effect ^^", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  SplitChannels()  
  CanvasGadget(#Result, 0, 0, 800, 600)
  
  ;Ajout d'un timer à 100 ms
  AddWindowTimer(#mainForm, #T0, 100)
  
  ;Triggers
  BindEvent(#PB_Event_CloseWindow, @Exit())
  BindEvent(#PB_Event_Timer, @RenderImage(), #mainForm, #T0)
    
  Repeat : WaitWindowEvent() : ForEver
EndProcedure

Procedure SplitChannels()
  Protected image = LoadImage(#PB_Any, "image.JPG")
  Protected width = ImageWidth(image)
  Protected height = ImageHeight(image)
  Protected index, x, y, color
  
  ReDim Image(width * height)
  
  StartDrawing(ImageOutput(image))
  For x = 0 To width - 1
    For y = 0 To height - 1
      
      color = Point(x, y)
      image(index)\x = x
      image(index)\y = y      
      image(index)\r = Red(color)
      image(index)\g = Green(color)
      image(index)\b = Blue(color)
      
      index + 1    
    Next
  Next  
  StopDrawing()
EndProcedure

Procedure RenderImage()
  Protected index, r, g, b
  
  ;Décalage à droite ou à gauche des 3 calques R G B
  Static DR, DG, DB  
  
  ;Dans quel sens pour chacun des calques
  Static SR=1, SG=1, SB=1 
  
  ;Génération du décalage
  DR + SR 
  DG + SG  
  DB + SB
  
  If DR > 10 Or DR = 0
    SR * -1
  EndIf
  
  If DG > 20 Or DG = 0
    SG * -1
  EndIf
  
  If DB > 30 Or DB = 0
    SB * -1
  EndIf
  
  ;Résultat
  StartDrawing(CanvasOutput(#Result))
  Box(0, 0, 800, 600, $000000)

  DrawingMode(#PB_2DDrawing_XOr)
  For index = 0 To ArraySize(Image())
    r = image(index)\r
    g = image(index)\g
    b = image(index)\b
    
    Plot(image(index)\x + DR, image(index)\y, RGB(r, 0, 0))
    Plot(image(index)\x + DG, image(index)\y, RGB(0, g, 0))
    Plot(image(index)\x + DB, image(index)\y, RGB(0, 0, b))
  Next
  StopDrawing()
EndProcedure

Procedure Exit()  
  End
EndProcedure
Test réalisé avec l'image test de Sherman que j'ai renommé image.jpg
http://shermanjohnson.weebly.com/upload ... p_orig.jpg

Re: PB transparence non voulue

Publié : dim. 23/oct./2016 1:32
par Demivec
Voici une solution avec filtre personnalisé (sans Debugger):

Code : Tout sélectionner

File$ = OpenFileRequester("Choisissez une image","","*.*",0)
Path$ = GetPathPart(File$)
If File$ = ""
  End 
EndIf

Debug "Chargement..."

UseJPEGImageDecoder()
UseJPEG2000ImageDecoder()
UsePNGImageDecoder()

Enumeration
  #Canvas
  #Image_red
  #Image_green
  #Image_blue
  #Image_base
  #Window
  #timer 
  #ImgX=30
  #ImgY=0
  #ImgWdth=400
  #ImgHgth=400
  #MaxDecal = 30
EndEnumeration

Enumeration Channels
  #Channel_Red
  #Channel_Green
  #Channel_Blue
  #Channel_Alpha
EndEnumeration

Declare ParasiteRGB()
Declare thRGB(param)
Declare SplitChannels(Image,OutputR,OutputG, OutputB)
Declare thSplitChannel(Channel)
Declare DifferenceCustomCallback(x, y, SourceColor, TargetColor)

Global progress,channel,total, Width, Height, thRed, thBlue, thGreen, Image, OutputR, OutputG, OutputB

OutputR = #Image_red
OutputG = #Image_green
OutputB = #Image_blue

LoadImage(#Image_base,File$)

Debug "Ok ca commence"

OpenWindow(1,0,0,250,30,"Chargement...",#PB_Window_ScreenCentered)
ProgressBarGadget(1,10,5,230,20,0,1000)
SplitChannels(#Image_base, #Image_red, #Image_green, #Image_blue)
Debug "Threads lancés"

Repeat
  WaitWindowEvent(50)
  SetGadgetState(1,(progress/total)*1000)
  Debug progress
Until Not IsThread(thRed) And Not IsThread(thGreen) And Not IsThread(thBlue)

CloseWindow(1)

;On enregistre le résultat donné pour chaque canal, pour vérifier
SaveImage(#Image_red,Path$ + "tmpR.bmp")
SaveImage(#Image_green,Path$ + "tmpG.bmp")
SaveImage(#Image_blue,Path$ + "tmpB.bmp")
  
OpenWindow(#Window,0,0,800,800,"Analogic display (BF4)",#PB_Window_ScreenCentered| #PB_Window_SystemMenu)
CanvasGadget(#Canvas,0,0,800,800)

AddWindowTimer(#Window,#Timer,1500)

Repeat
  event = WaitWindowEvent()
  If event = #PB_Event_Timer And EventTimer() = #timer
    ParasiteRGB()
  EndIf
  
Until event = #PB_Event_CloseWindow

Procedure ParasiteRGB()
  If Not IsThread(thRGB)
    CreateThread(@thRGB(), 1)
  Else
    Debug "Already running..."
  EndIf
EndProcedure

Procedure thRGB(param)
  Decal = Random(#MaxDecal,2)
    For i= 0 To Decal Step 2
    StartDrawing(CanvasOutput(#Canvas))
    Box(0,0,800,800,0)
    DrawImage(ImageID(#Image_green),#ImgX,#ImgY)
    DrawingMode(#PB_2DDrawing_CustomFilter)
    CustomFilterCallback(@DifferenceCustomCallback())
    DrawImage(ImageID(#Image_red),#ImgX+i,#ImgY)
    DrawImage(ImageID(#Image_blue),#ImgX-i,#ImgY)
    StopDrawing()
    Delay(1)
  Next
  For i = Decal To 0 Step -1
    StartDrawing(CanvasOutput(#Canvas))
    Box(0,0,800,800,0)
    DrawImage(ImageID(#Image_green),#ImgX,#ImgY)
    DrawingMode(#PB_2DDrawing_CustomFilter)
    CustomFilterCallback(@DifferenceCustomCallback())
    DrawImage(ImageID(#Image_red),#ImgX+i,#ImgY)
    DrawImage(ImageID(#Image_blue),#ImgX-i,#ImgY)
    StopDrawing()
    Delay(1)
  Next
  StartDrawing(CanvasOutput(#Canvas))
  ;DrawImage(ImageID(#Image_base),#imgX,#ImgY) ;Commenter pour voir simplement la superposition foirée
  StopDrawing()
EndProcedure

Procedure SplitChannels(Image,OutputR, OutputG, OutputB)
  Debug ~"Canal rouge\t:"+OutputR+"\nCanal vert\t:"+OutputG+"\nCanal bleu\t:"+OutputB
  StartDrawing(ImageOutput(Image))
  Width = OutputWidth()
  Height = OutputHeight()
  Depth = OutputDepth()
  StopDrawing()
  
  total = 3*(Width * Height)
  CreateImage(OutputR,Width,Height,Depth,0)
  CreateImage(OutputG,Width,Height,Depth,0)
  CreateImage(OutputB,Width,Height,Depth,0)
  
  Global Dim Color(Width,Height)
  channel = 0
  StartDrawing(ImageOutput(Image))
  For x = 0 To Width-1
    For y = 0 To Height-1
      Color(x,y) = Point(x,y)
    Next
    progress +1
  Next
  StopDrawing()
  
  thRed = CreateThread(@thSplitChannel(),#Channel_Red)
  thGreen = CreateThread(@thSplitChannel(), #Channel_Green)
  thBlue = CreateThread(@thSplitChannel(), #Channel_Blue)
  
EndProcedure

Procedure thSplitChannel(Channel)
  Select Channel
    Case #Channel_Red
      channel +1
      StartDrawing(ImageOutput(OutputR))
      For x = 0 To Width-1
        For y = 0 To Height-1
          Plot(x,y,RGB(Red(Color(x,y)),0,0))
        Next
        progress +1
      Next
      StopDrawing()
      
    Case #Channel_Green
      channel +1
      StartDrawing(ImageOutput(OutputG))
      For x = 0 To Width-1
        For y = 0 To Height-1
          Plot(x,y,RGB(0,Green(Color(x,y)),0))
        Next
        progress +1
      Next
      StopDrawing()
      
    Case #Channel_Blue
      channel +1
      StartDrawing(ImageOutput(OutputB))
      For x = 0 To Width-1
        For y = 0 To Height-1
          Plot(x,y,RGB(0,0,Blue(Color(x,y))))
        Next
        progress +1
      Next
      StopDrawing()
  EndSelect
EndProcedure

Procedure DifferenceCustomCallback(x, y, SourceColor, TargetColor)
  Protected red_S, blue_S, green_S, red_T, blue_T, green_T, red_R, blue_R, green_R
  red_S = Red(SourceColor): green_S = Green(SourceColor): blue_S = Blue(SourceColor)
  red_T = Red(TargetColor): green_T = Green(TargetColor): blue_T = Blue(TargetColor)
  
  red_R = red_S - red_T
  If red_R < 0
    red_R = -red_R
  EndIf
  
  green_R = green_S - green_T
  If green_R < 0
    green_R = -green_R
  EndIf
  
  blue_R = blue_S - blue_T
  If blue_R < 0
    blue_R = -blue_R
  EndIf
  ProcedureReturn RGBA(red_R, green_R, blue_R, 255)
EndProcedure
@Edit: j'ai mis a jour ce code

Re: PB transparence non voulue

Publié : dim. 23/oct./2016 2:54
par Micoute
Très bon travail, merci à tous pour le partage.

Re: PB transparence non voulue

Publié : dim. 23/oct./2016 11:03
par falsam
Hello Demivec. Que ce soit avec PB 5.43 ou PB 5.50 le code bugue.
Debug a écrit :[12:02:31] [ERROR] Line: 157
[12:02:31] [ERROR] StartDrawing(): StopDrawing() must be called before calling StartDrawing() again.
J'ai essayé avec l'image de sherman : http://shermanjohnson.weebly.com/upload ... p_orig.jpg

Re: PB transparence non voulue

Publié : dim. 23/oct./2016 11:20
par JohnJohnsonSHERMAN
Magnifiique ! Eh bien que dire sinon que ces deux codes sont trés intéressants... Bien que mon préféré soit celui de Demivec (A compiler en mode threadé, falsam, d'ou ton erreur), et ce pour deux raisons
  • Plus proche de l'effet d'origine, le filtre vert restant fixe
  • Plus proche de mon code aussi
  • Et utilise une Callback custom... ce que j'avais vite fais essayé hier de facon non concluante (Quoi j'ai dit deux raisons? Et si je veux en mettre 3?! :mrgreen: )

    Néanmoins celui de falsam est simple et assez optimisé... ce qui n'est pas forcément le cas du mien ;) Enfin merci à tous les deux pour ces deux codes (Bon je vais faire un benchmark comparatif :) )