[GDI+] problème d'icones transparents...

psy4meuh Messages postés 23 Date d'inscription jeudi 5 juin 2003 Statut Membre Dernière intervention 23 août 2006 - 12 oct. 2005 à 08:44
jpthomasset Messages postés 95 Date d'inscription samedi 19 juin 2004 Statut Membre Dernière intervention 20 avril 2010 - 14 oct. 2005 à 10:13
Bonjour à tous,





je suis en train de basculer un de mes anciens programes d'affichage d'icones en GDI+, et je suis face à un problème bizare :
Les parties complettement transparentes des icones sont OK, mais les transparences 'partielles' s'affichent en noir... alors que dans l'ancienne vesion (BitBlt...) tout était OK...
Pour mieux comprendre, une petite image vaut mieux qu'un grand discours :

Quelqu'un a une idée?

12 réponses

jpthomasset Messages postés 95 Date d'inscription samedi 19 juin 2004 Statut Membre Dernière intervention 20 avril 2010
12 oct. 2005 à 13:47
Salut,



C'est pas facile de répondre comme ca : est-ce que tu aurais un bout de
code ? Tu utilise Graphics::DrawImage ? Quel est le format de tes
icones ?



Pour info, perso j'utilise des PNG et je n'ai eu aucun problème avec la composante alpha.

A+,



JP.

PS: l'image ne s'affiche pas...
0
psy4meuh Messages postés 23 Date d'inscription jeudi 5 juin 2003 Statut Membre Dernière intervention 23 août 2006
12 oct. 2005 à 14:32
Voilà mon code pour la version en GDI+.... rien de spécial... cet icône est en 24bpp + alpha

hdc = BeginPaint(_hWnd, &ps);
Graphics graphics(hdc);
Bitmap bmp2(hIcon);
graphics.DrawImage(&bmp2,256,0);
0
jpthomasset Messages postés 95 Date d'inscription samedi 19 juin 2004 Statut Membre Dernière intervention 20 avril 2010
12 oct. 2005 à 15:45
Salut, d'après ce message : http://groups.google.com/group/microsoft.public.dotnet.framework.drawing/browse_thread/thread/500d874bee13670c/ea581edaf88044e7
Il semble qu'il y ai un bug dans la fonction FromHICON. Le message contient un correctif en C#, mais ce n'est pas trop dur de le porter.

Honnetement, je me demance si cela ne viendrais pas du fait que en GDI classique, pour utiliser l'alpha blending, il fallait prémultiplier les couleurs par l'alpha, alors qu'en GDI+ ce n'est pas le cas.

Une idée à creuser, est peut-etre de charger les icones directement depuis le fichier de resource dans GDI+ avec la fonction Image::FromStream, il est possible que dans ce cas tes icones soient extraites normalement : Perso j'utilise cette technique pour mes images, mais ce sont des PNG.

A+,
JP.
0
psy4meuh Messages postés 23 Date d'inscription jeudi 5 juin 2003 Statut Membre Dernière intervention 23 août 2006
12 oct. 2005 à 16:42
Peut être pas un bug, mais à mon avis le GDI+ ne gère pas le "24bppARGB",je vais essayer de transformer les icones en "32bppARGB"après lecture, mais il faut que je les lisent dirrectement... genre avec le hbmColor de ICONINFO...., j'vais essayer...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
jpthomasset Messages postés 95 Date d'inscription samedi 19 juin 2004 Statut Membre Dernière intervention 20 avril 2010
12 oct. 2005 à 17:28
Ben, en fait les icones en 24bits plus un layer alpha sont équivalentes
à des images en 32bppARGB. La différence est (il me semble) dans
l'organisation des données (je crois que les icones ont un bitmap qui
contient uniquement les valeurs alpha et un autre pour les couleurs
24bits).

Normalement, GDI+ devrait donc créer un bitmap en 32bpp à partir de ton icone, mais il y a sans doute un bug...



A+,

JP.
0
jpthomasset Messages postés 95 Date d'inscription samedi 19 juin 2004 Statut Membre Dernière intervention 20 avril 2010
12 oct. 2005 à 17:42
Petite correction les icones en 32 bits, contiennent en fait un bitmap
de 1bit qui sert de masque et un bitmap de 32 bits (24 pour les
couleurs et 8 pour l'alpha).

Il est probable que GDI+ utilise le bitmask au lieu de l'alpha.



A+,

JP.
0
psy4meuh Messages postés 23 Date d'inscription jeudi 5 juin 2003 Statut Membre Dernière intervention 23 août 2006
13 oct. 2005 à 08:25
Je crois avaoir trouvé, je poste mon code apres vérif...
0
psy4meuh Messages postés 23 Date d'inscription jeudi 5 juin 2003 Statut Membre Dernière intervention 23 août 2006
13 oct. 2005 à 08:55
Ok, ca marche... c bien ce que je pensait, le GDI+ ne gère pas bien le format de l'icone à cause du masque je pense, donc je prends la parie couleur(+alpha) de l'icone par 'GetIconInfo' et je crée un Bitmap GDI+ au format 32bppARGB... voilà mon code :

/**************************************************************************/
//hIcon loadé par un LoadImage ou ExtractIcon
PICONINFO ii = new ICONINFO;
GetIconInfo(hIcon, ii);

Bitmap bmp(ii->hbmColor, NULL);
DeleteObject(ii->hbmColor);
DeleteObject(ii->hbmMask);

BitmapData bmData;
Rect bmBounds(0,0,bmp.GetWidth(),bmp.GetHeight());
bmp.LockBits(&bmBounds, ImageLockModeRead, bmp.GetPixelFormat(), &bmData);
Bitmap dstBitmap(bmData.Width, bmData.Height, bmData.Stride, PixelFormat32bppARGB, (BYTE *)bmData.Scan0);

BOOL IsAlpha = false;
Color c1(0,0,0,0);
for (int y=0; y <= bmp.GetHeight()-1; y++) {
for (int x=0; x <= bmp.GetWidth()-1; x++) {
dstBitmap.GetPixel(x,y,&c1);
if (c1.GetA()>0 & c1.GetA()<255) IsAlpha=true;
}
}
bmp.UnlockBits(&bmData);
if (IsAlpha) {
graphics.DrawImage(&dstBitmap,0,0,Taille,Taille);
}
else {
Bitmap bmp2(hIcon);
graphics.DrawImage(&bmp2,0,0,Taille,Taille);
delete &bmp2;
}
/**************************************************************************/

Je vérifie au passage que l'icone contient bien de la transparence partielle (0<Alpha<255) sinon la transparence totale saute au passage.

Par contre j'aurai besoin d'un complément d'aide sur comment afficher cet icone sur une fenetre complètement transparente... j'ai essayé avec un SetLayeredWindowAttributes, mais on peut spécifier qu'une colorkey, donc encore une fois, la transparence complète est ok, mais pas la partielle... tu peux encore m'aider?
0
jpthomasset Messages postés 95 Date d'inscription samedi 19 juin 2004 Statut Membre Dernière intervention 20 avril 2010
13 oct. 2005 à 10:02
Salut,



Effectivement, cela vient sans doute de la conversion dans GDI+. Dans
tes boucles for, je te conseille de sortir des boucles dès que IsAlpha
est vrai, ca t'evitera de parcourir tout les pixels si tu trouve une
valeur alpha dans les premiers pixels.

Je pense que tu aurais pu t'en sortir en regardant simplement le nombre
de bits par pixel de ii->hbmColor avec GetObject, a mon avis il doit
donner 32 dans le cas d'un image avec une valeur alpha.



Pour ton problème de fenetre transparente, il me semble que
SetLayeredWindowAttributes ne sert que si l'on veut une fenetre avec
des parties completement transparentes (avec une colorkey) ou alors si
on veut appliquer le même alpha à toute la fenetre (la valeur bAlpha).
Si tu veux une fenetre avec des valeurs alpha par pixel, il faut créer
ta fenetre avec les styles WS_EX_LAYERED et WS_EX_TRANSPARENT et
ensuite utiliser la fonction UpdateLayeredWindow qui fonctionne un peu
comme la fonction AlphaBlend. Je pense aussi qu'avec GDI+ on peut aussi
utiliser DrawImage avec une image en 32bppARGB au lieu de la fonction
UpdateLayeredWindow, mais c'est a vérifier.



A+,

JP.
0
psy4meuh Messages postés 23 Date d'inscription jeudi 5 juin 2003 Statut Membre Dernière intervention 23 août 2006
13 oct. 2005 à 15:40
Bon, j'suis carrément perdu dans l'histoire de fenetre avec alpha par pixel... je crée ma fenetre avec WS_EX_LAYERED et WS_EX_TRANSPARENT, par contre je comprends pas comment utiliser la fonction UpdateLayeredWindow... Voilà ce que j'ai fait :

/************************** CODE *********************************/
HDC buf = CreateCompatibleDC(NULL);
Graphics g(buf);
g.Clear(Color(128,128,0,0));

SIZE sz = { 64, 64};
POINT pos = {0};
POINT ptSource = {0};
BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };

UpdateLayeredWindow(hwnd, GetWindowDC(hwnd), NULL, &sz, g.GetHDC(), &ptSource, 0, &bf, ULW_ALPHA);

/**********************************************************/

Mais ca ne me donne rien, j'comprends pas... il faut bien spécifier à 'UpdateLayeredWindow' le HDC qu'on veut afficher dans la fenetre.Pour infos j'ai mis ca dans l'evenement PAINT de ma fenêtre... help me JP!!!!
0
jpthomasset Messages postés 95 Date d'inscription samedi 19 juin 2004 Statut Membre Dernière intervention 20 avril 2010
14 oct. 2005 à 08:28
De mémoire, lorsque l'on utilise WS_EX_LAYERED, le message WM_PAINT
n'est plus envoyé, en fait le mécanisme de rafraichissement de la
fenetre est différent : lorsque tu utilise UpdateLayeredWindow tu donne
une image de la fenetre au système qui se charge de l'afficher, c'est a
toi de décider quand tu doit rafraichir cette image.



A+,

JP.
0
jpthomasset Messages postés 95 Date d'inscription samedi 19 juin 2004 Statut Membre Dernière intervention 20 avril 2010
14 oct. 2005 à 10:13
Une derniere chose, dans la doc MSDN sur UpdateLayeredWindow, il est dit de passer GetDC(NULL) à cette fonction.



A+,

JP.
0
Rejoignez-nous