8
votes

Formulaires Windows: faire un casseur bitmap partiellement transparent

Je veux utiliser des images partiellement transparentes dans les opérations de glisser / goutte. Tout cela est mis en place et fonctionne bien, mais la transformation réelle en transparence a un effet secondaire étrange. Pour une raison quelconque, les pixels semblent être mélangés sur un fond noir.

L'image suivante décrit le problème: p>

problème de transparence p> Figure A) est le bitmap d'origine. P>

la figure B) est ce qui est produit après l'exécution de la mélange alpha. Évidemment, cela est beaucoup plus sombre que le filtre alpha de 50% destiné. P>

Figure c) est l'effet souhaité, l'image a) avec une transparence de 50% (ajoutée à la composition avec un programme de dessin). p>

Le code que j'utilise pour produire l'image Trasparent est le suivant: P>

    [DllImport("user32.dll", EntryPoint = "CreateIconIndirect")]
    public static extern IntPtr CreateIconIndirect(ref IconInfo icon);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);


1 commentaires

Merci! Il semble juste vraiment étrange pour moi que même après quinze ans d'opérations de glisser / goutte et de curseurs personnalisés, cette chose ne peut pas être résolue facilement. Je reçois une transparence de sorte que au moins le système indique que cela peut être fait. Après trois jours de taraudage dur sur mon clavier et de mes articles de lecture, j'ai une légère suspicion que l'on pourrait avoir besoin de puiser dans la structure bitmapv5header. Voici un article C ++ susceptible de résoudre le problème: support.microsoft. com / par défaut.aspx? SCID = KB; EN-US; 318876 . Si quelqu'un peut porter cela, je serai heureux de remettre le vote de réponse accepté.


5 Réponses :


0
votes

Essayez de réduire la valeur du bleu à .7 ou .6 et voyez si cela est plus proche de ce que vous voulez.

Voici un bon site qui explique Colormatrix : < / p>


1 commentaires

Négatif. Votre suggestion changerait simplement les couleurs d'origine, puis appliquez l'alpha mélange. Comme mentionné ci-dessus, je crois que cela a quelque chose à voir avec l'alpha de l'image en quelque sorte mélangé sur un fond noir. Dans mon application Alpha 0 donne une image 100% transparente et une alpha complète renvoie l'image d'origine (avec les parties transparentes supérieures et inférieures étant toujours transparentes).



0
votes

Lorsque j'exécute votre code pour modifier une image dans une boîte d'images avec une image de grille de fond, je reçois l'effet que vous avez désiré sans changer votre code. Peut-être que votre image est attirée sur le dessus de quelque chose qui a une couleur sombre ...


1 commentaires

Comme je l'ai dit, ce code est destiné à créer une image semitransparente pour les opérations de glisser / goutte. Ainsi, l'image ne doit pas être dessinée sur rien du tout, mais faire partie d'un curseur. Peut-être que cela arrive pour des raisons telles que les pixels sous-jacents ont des valeurs 0x00000000, mais j'ai essayé de le changer à 0x00FFFFF en vain.



0
votes

Pardonne-moi si ma suggestion est trop simpliste (je suis toujours nouvelle à C #) mais j'ai trouvé cela sur le site MSDN et peut-être Ce pourrait vous pointer dans la bonne direction?

/ mat


1 commentaires

Salut Matt! Merci pour la suggestion, mais le problème est de ne pas créer de bitmap transparent en soi. Le problème est plutôt que lorsque le bitmap est converti en une icône, la partie de transparence semble être superposée noire opaque avant sa rendu. Cela pourrait être un effet secondaire à CreateiconIndrect.



6
votes

GDI + a un certain nombre de problèmes liés à l'alpha mélange lorsqu'ils font interoper avec GDI (et Win32). Dans ce cas, l'appel à BMP.GETHBITMAP () blendra votre image avec un fond noir. Un Article sur CodeProject donne plus de détails sur le problème et une solution utilisée Pour ajouter des images à une liste d'images.

Vous devriez pouvoir utiliser du code similaire pour obtenir le HBITMAP à utiliser pour le masque: P>

[DllImport("kernel32.dll")]
public static extern bool RtlMoveMemory(IntPtr dest, IntPtr source, int dwcount);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateDIBSection(IntPtr hdc, [In, MarshalAs(UnmanagedType.LPStruct)]BITMAPINFO pbmi, uint iUsage, out IntPtr ppvBits, IntPtr hSection, uint dwOffset);

public static IntPtr GetBlendedHBitmap(Bitmap bitmap)
{
    BITMAPINFO bitmapInfo = new BITMAPINFO();
    bitmapInfo.biSize = 40;
    bitmapInfo.biBitCount = 32;
    bitmapInfo.biPlanes = 1;

    bitmapInfo.biWidth = bitmap.Width;
    bitmapInfo.biHeight = -bitmap.Height;

    IntPtr pixelData;
    IntPtr hBitmap = CreateDIBSection(
        IntPtr.Zero, bitmapInfo, 0, out pixelData, IntPtr.Zero, 0);

    Rectangle bounds = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
    BitmapData bitmapData = bitmap.LockBits(
        bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb );
    RtlMoveMemory(
        pixelData, bitmapData.Scan0, bitmap.Height * bitmapData.Stride);

    bitmap.UnlockBits(bitmapData);
    return hBitmap;
}


1 commentaires

J'ai essayé votre code et ça a fonctionné! Merci beaucoup! Cependant, il y a une chose ici qui est partiellement mal. La structure bitmapinfo est vraiment une structure bitmapinfoheader. Le premier contient un bitmapinfoheader comme premier élément de valeur afin que tous les deux dans la pratique fonctionne. Je ne sais pas si l'approche gérée / non gérée par Tarrsier est la meilleure, mais vous avez répondu d'abord et obtenez la réponse acceptée.



3
votes

Il y a quelque temps, j'ai lu ce problème découle d'une exigence de canaux alpha pré-multipliés dans les bitmaps. Je ne sais pas si c'était un problème avec des curseurs Windows ou GDI, et pour la vie de moi, je ne trouve pas de documentation à ce sujet. Donc, alors que cette explication peut être correcte ou non, le code suivant fait en effet ce que vous voulez, à l'aide d'un canal alpha pré-multiplié dans le bitmap de curseur.

public class External
{
  [StructLayout(LayoutKind.Sequential)]
  public struct ICONINFO
  {
    public bool IsIcon;
    public int xHotspot;
    public int yHotspot;
    public IntPtr MaskBitmap;
    public IntPtr ColorBitmap;
  };

  [DllImport("user32.dll")]
  public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);

  [DllImport("user32.dll")]
  public static extern IntPtr CreateIconIndirect([In] ref ICONINFO piconinfo);

  [DllImport("gdi32.dll")]
  public static extern bool DeleteObject(IntPtr hObject);

  [DllImport("gdi32.dll")]
  public static extern IntPtr CreateBitmap(int nWidth, int nHeight, uint cPlanes, uint cBitsPerPel, IntPtr lpvBits);
}


0 commentaires