Page 1 sur 1
Fenetre d'un format spécial avec alphablending?
Publié : dim. 10/août/2008 15:50
par poshu
Alors que je mettais à jour
iBar, je me suis retrouvé face à un petit problème:
iBar utilise un système de skin qui permet d'utiliser des fenêtres d'une forme "spéciale".

Jusque là, tout va bien, je me suis codé une petite fonction toute bête et très simple qui rempli son office (la voilà, si elle peut servir à quelqu'un, tant mieux ^^):
Code : Tout sélectionner
Procedure SkinWindow(Window,Skin,Transparent_Color = #Magenta)
Region = CreateRectRgn_(0, 0, WindowWidth(Window) + 1, WindowHeight(Window) + 1)
StartDrawing( ImageOutput (Skin))
For x1 = 0 To WindowWidth(Window)-1
For y1 = 0 To WindowHeight(Window)-1
If Point(x1, y1) = Transparent_Color
y2 = y1
While x2 < WindowWidth(Window) And Point(x1, y2 + 1) = Transparent_Color
y2 + 1
Wend
Region_Temp = CreateRectRgn_(x1, y1, x1 + 1, y2 + 1)
CombineRgn_ (Region, Region, Region_Temp, #RGN_DIFF )
y1 = y2
EndIf
Next
Next
StopDrawing()
SetWindowRgn_(WindowID(Window), Region, #True )
brush=CreatePatternBrush_(ImageID(Skin))
SetClassLong_(WindowID(Window),#GCL_HBRBACKGROUND,brush)
InvalidateRect_(WindowID(Window),0,1)
CreateGadgetList(WindowID(Window))
EndProcedure
; Exemple (lancer avec le débuger: on ne peut pas fermer la fenêtre, je suis un flemmard)
If LoadImage(0,OpenFileRequester("Selection du skin","","Bitmap|*.bmp",0))
OpenWindow(0,0,0,ImageWidth(0),ImageHeight(0),"Fenêtre skinée",#PB_Window_ScreenCentered|#PB_Window_BorderLess)
SkinWindow(0,0)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
FreeImage(0)
EndIf
Comme vous pouvez le voir, c'est vraiment simpliste jusque là, mais pour pousser le principe un peu plus loin, j'aimerais utiliser l'alphablending, et là je panne:
Comment faire pour afficher une window skinnée prenant compte de l'alpha blending? Est-ce au moins possible?
Publié : dim. 10/août/2008 17:20
par Thyphoon
C'est cool ! maintenant ça prouve que tu es plus doué que moi ! Vu que tu sais utilisé les API et que moi non a part Beep_()

Publié : dim. 10/août/2008 17:57
par Anonyme2
Tu peux utiliser Gdi+ pour la transparence mais fonctionnera pas sur les OS ou GDI+ n'est pas installé.
Tu peux utiliser l'API alphablend, j'ai donné un exemple ici
http://www.purebasic.fr/french/viewtopic.php?t=5512
Il y a aussi la commande PB DrawAlphaImage()
A+
Denis
Publié : dim. 10/août/2008 18:07
par poshu
Denis > J'avais très peur de devoir en venir à GDI+. J'ai installé ton pack (très beau boulot d'ailleurs) hier, et j'ai beaucoup de mal à assimiler autant d'information d'un coup.
Au moins, ça confirme que c'est possible, merci beaucoup
Typhoon > Et tu sais faire des choses qui m'échappent on a tous nos points faibles. Mais globalement, c'est moi qui pose le plus souvent des questions stupides sur le forum... Et si on arrêtait la gueguerre "c'est toi le meilleur" maintenant?
Publié : dim. 10/août/2008 18:17
par Thyphoon
poshu a écrit :
Typhoon > Et tu sais faire des choses qui m'échappent on a tous nos points faibles. Mais globalement, c'est moi qui pose le plus souvent des questions stupides sur le forum... Et si on arrêtait la gueguerre "c'est toi le meilleur" maintenant?
lollll tu as tout a fait raison, c'était juste un petit clein d'oeil a note dernière conversation.

il est vrai que ce forum possède de véritable talent. ça pourrait être amusant de tous les réunirs pour un petit projet un jour (chaqu'un ayant des occupation diverse ça ne marcherait pas pour un grand projet...). On pourait sans doute faire quelques choses de terrible !!

Publié : dim. 10/août/2008 18:33
par Anonyme2
poshu a écrit :Denis > J'avais très peur de devoir en venir à GDI+. J'ai installé ton pack (très beau boulot d'ailleurs) hier, et j'ai beaucoup de mal à assimiler autant d'information d'un coup.
Au moins, ça confirme que c'est possible, merci beaucoup
J'ai mis plus de 8 mois d'un travail de fou avec des hauts et des bas, alors je sais bien que l'on assimile pas ça d'un coup. Ce qui est intéressant c'est de savoir ce que l'on peut faire, pas de connaître les 600 fonctions; de mémoire il y a des fonctions de mélange de couleurs.
Je pense que l'API Alphablend correspond à ton besoin. Cherche sur le forum, tu trouveras une formule sans API pour créer une image avec transparence (à l'affichage) à partir d'une image.
A+
Denis
Publié : dim. 10/août/2008 19:05
par poshu
Je suis en train de bidouiller sec dans le code là (et j'ai les mains pleines de cambouis), mais j'ai pas l'impression de pouvoir faire ce que je veux avec l'api >.<
J'vais commencer à regarder du coté de GDI (noooooon!)
Publié : dim. 10/août/2008 20:09
par Jacobus
Avec un peu de transparence... (j'ai ajouté le bouton "Fermer") flemmard!
Code : Tout sélectionner
Procedure SkinWindow(Window,Skin,Transparent_Color = #Magenta)
Region = CreateRectRgn_(0, 0, WindowWidth(Window) + 1, WindowHeight(Window) + 1)
StartDrawing( ImageOutput (Skin))
For x1 = 0 To WindowWidth(Window)
For y1 = 0 To WindowHeight(Window)
If Point(x1, y1) = Transparent_Color
y2 = y1
While x2 < WindowWidth(Window) And Point(x1, y2 + 1) = Transparent_Color
y2 + 1
Wend
Region_Temp = CreateRectRgn_(x1, y1, x1 + 1, y2 + 1)
CombineRgn_ (Region, Region, Region_Temp, #RGN_DIFF )
y1 = y2
EndIf
Next
Next
StopDrawing()
SetWindowRgn_(WindowID(Window), Region, #True )
brush=CreatePatternBrush_(ImageID(Skin))
SetClassLong_(WindowID(Window),#GCL_HBRBACKGROUND,brush)
InvalidateRect_(WindowID(Window),0,1)
CreateGadgetList(WindowID(Window))
EndProcedure
; Le niveau de transparence doit être compris entre 1 (transparence totale) et 255 (opaque)
Procedure SetWinTransparency(WinHandle.l, Transparency_Level.l)
SetWindowLong_ (WinHandle, #GWL_EXSTYLE , GetWindowLong_ (WinHandle, #GWL_EXSTYLE ) | $00080000) ; #WS_EX_LAYERED = $00080000
If OpenLibrary (0, "user32.dll" )
CallFunction (0, "SetLayeredWindowAttributes" , WinHandle, 0, Transparency_Level, 2)
CloseLibrary (0)
EndIf
EndProcedure
Global Hwnd
; Exemple (lancer avec le débuger: on ne peut pas fermer la fenêtre, je suis un flemmard)
If LoadImage(0,OpenFileRequester("Selection du skin","","Bitmap|*.bmp",0))
Hwnd = OpenWindow(0,0,0,ImageWidth(0),ImageHeight(0),"Fenêtre skinée",#PB_Window_ScreenCentered|#PB_Window_BorderLess)
SkinWindow(0,0)
ButtonGadget(1,WindowWidth(0)-100,WindowHeight(0)-30,80,20,"Fermer")
SetWinTransparency(Hwnd, 100)
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case 1
quitter = 1
EndSelect
EndSelect
Until quitter = 1
FreeImage(0)
EndIf
End
Publié : dim. 10/août/2008 21:17
par poshu
Ca, je savais le faire (c'est déjà dans la V0.4 d'iBar), mon problème est d'utiliser une transparence différente pour chaque pixel de la fenêtre, et c'est vachement plus dur (ou j'ai juste rien compris, et dans ce cas, j'en suis désolé.)
Publié : lun. 11/août/2008 8:17
par Anonyme2
Voici les explications de Microsoft (en anglais) sur la couche alpha avec les formules.
http://msdn2.microsoft.com/en-us/librar ... S.85).aspx
Essaye cette procedure qui retourne la couleur mélangée, il te suffit de l'appeler pour chaque point de ton image.
Alpha doit être compris en 0 et 255, 0 c'est complètement transparent, donc c'est le fond qui s'affiche et 255 c'est totalement opaque donc c'est la couleur source qui s'affiche.
Code : Tout sélectionner
Procedure.l GetAlphaBlendedColor(CouleurSource.l, CouleurFond.l, Alpha.l)
ProcedureReturn RGB((((Red(CouleurSource) * Alpha / 255) + ((Red(CouleurFond) * (255 - Alpha))) / 255)), (((Green(CouleurSource) * Alpha / 255) + ((Green(CouleurFond) * (255 - Alpha))) / 255)), (((Blue(CouleurSource) * Alpha / 255) + ((Blue(CouleurFond) * (255 - Alpha))) / 255)))
EndProcedure
A+
Denis
Publié : lun. 11/août/2008 13:36
par Backup
Nico avait pondu ça
Code : Tout sélectionner
Procedure AlphaBlend(Image1,Image2); transparence d'image
; Nico
Structure _LTI_BITMAPINFO
bmiHeader.BITMAPINFOHEADER
bmiColors.RGBQUAD[1]
EndStructure
Structure BGRA
Blue.b
Green.b
Red.b
Alpha.b
EndStructure
Structure BGRAL
Blue.l
Green.l
Red.l
Alpha.l
EndStructure
hDC1 = StartDrawing(ImageOutput(Image1))
hDC2=CreateCompatibleDC_(hDC1)
SelectObject_(hDC2,ImageID(Image2))
If hDC1 And hDC2
ImageWidth = ImageWidth(Image1) : ImageHeight = ImageHeight(Image1)
mem1 = GlobalAlloc_(#GMEM_FIXED|#GMEM_ZEROINIT,ImageWidth*ImageHeight*4)
mem2 = GlobalAlloc_(#GMEM_FIXED|#GMEM_ZEROINIT,ImageWidth*ImageHeight*4)
If mem1>0 And mem2>0
bmi._LTI_BITMAPINFO
bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
bmi\bmiHeader\biWidth = ImageWidth
bmi\bmiHeader\biHeight = ImageHeight
bmi\bmiHeader\biPlanes = 1
bmi\bmiHeader\biBitCount = 32
bmi\bmiHeader\biCompression = #BI_RGB
GetDIBits_(hDC1,ImageID(Image1),0,ImageHeight,mem1,bmi,#DIB_RGB_COLORS)
GetDIBits_(hDC2, ImageID(Image2), 0, ImageHeight, mem2, bmi, #DIB_RGB_COLORS)
*color1.BGRA = mem1
*color2.BGRA = mem2
color1Long.BGRAL
color2Long.BGRAL
color1Long\Blue = *color1\Blue & $FF
color1Long\Green = *color1\Green & $FF
color1Long\Red = *color1\Red & $FF
color1Long\Alpha = *color1\Alpha & $FF
color2Long\Blue = *color2\Blue & $FF
color2Long\Green = *color2\Green & $FF
color2Long\Red = *color2\Red & $FF
color2Long\Alpha = *color2\Alpha & $FF
For a = 0 To (ImageWidth*ImageHeight)-1
ColorBlue.b = color1Long\Blue * color1Long\Alpha / 255 + color2Long\Blue * (255 - color1Long\Alpha) / 255
ColorGreen.b = color1Long\Green * color1Long\Alpha / 255 + color2Long\Green * (255 - color1Long\Alpha) / 255
ColorRed.b = color1Long\Red * color1Long\Alpha / 255 + color2Long\Red * (255 - color1Long\Alpha) / 255
*color1\Blue = ColorBlue
*color1\Green = ColorGreen
*color1\Red = ColorRed
*color1 + 4
*color2 + 4
color1Long\Blue = *color1\Blue & $FF
color1Long\Green = *color1\Green & $FF
color1Long\Red = *color1\Red & $FF
color1Long\Alpha = *color1\Alpha & $FF
color2Long\Blue = *color2\Blue & $FF
color2Long\Green = *color2\Green & $FF
color2Long\Red = *color2\Red & $FF
color2Long\Alpha = *color2\Alpha & $FF
Next a
If SetDIBits_(hdcdest, ImageID(1),0,ImageHeight,mem,bmi,#DIB_RGB_COLORS) <> 0
Result = ImageID(1)
EndIf
EndIf
If mem1
GlobalFree_(mem1)
EndIf
If mem1
GlobalFree_(mem2)
EndIf
EndIf
StopDrawing()
DeleteDC_(hDC2)
ProcedureReturn Result
EndProcedure