Bernhard's profileBernhard Grojer - BlogPhotosBlogLists Tools Help

Blog


    May 13

    .net Framework 3.5 - Beta1


    Ihr dachtet die stressigen Tage sind vorbei? .net 3.5 Release und es wird ruhiger?

    Schwer getäuscht,- .net Framework 3.5 SP1 Beta1 ist hier mit vielen Änderungen ...

    Scott Guthrie (wer auch sonst) hat die wichtigsten Information zusammengestellt.

    May 05

    Bitmaps in WPF (Transparenz-Angabe)


    Nehmen wir mal an, wir haben ein Bitmap das wir in unserer Anwendung darstellen wollen.

    Kein Problem in WPF:

    <Image Source="img.bmp" />

    TransparentWpfShoot2 

    Doch der Magenta-Hintergrund ist nicht unbedingt das Ergebnis das wir erwartet haben. Transparenz muss also her.
    Eine Möglichkeit wäre zu PNG oder dem GIF Format zu greifen. Alternativ hatten wir in WinForms die Option TransparentColor zu verwenden.

    In WPF wird die Sache leider etwas mühsamer.

    Wir können uns einen eigenen Converter für die Problemstellung schreiben:
    public class BitmapTransparentConverter : IValueConverter
        {
            #region IValueConverter Members

            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                BitmapDecoder decoder = BitmapDecoder.Create(new Uri(value.ToString(), UriKind.Relative), BitmapCreateOptions.None, BitmapCacheOption.Default);

                BitmapSource sourceImage = decoder.Frames[0] as BitmapSource;
                Color transparentColor = Colors.Magenta; //Alternativ IMultiValueConverter und als Paramter verwenden

                sourceImage = new FormatConvertedBitmap(sourceImage, PixelFormats.Bgra32, null, 0.0);
                int step = (sourceImage.PixelWidth * sourceImage.Format.BitsPerPixel) / 8;
                byte[] pix = new byte[sourceImage.PixelHeight * step];
                sourceImage.CopyPixels(pix, step, 0);
                byte r = transparentColor.R;
                byte g = transparentColor.G;
                byte b = transparentColor.B;

                for (int i = 0; i < sourceImage.PixelHeight * step; i += (sourceImage.Format.BitsPerPixel / 8))
                {
                    if (pix[i] == b && pix[i + 1] == g && pix[i + 2] == r)
                        pix[i + 3] = 0;
                }
                return BitmapSource.Create(sourceImage.PixelWidth, sourceImage.PixelHeight,
                                    sourceImage.DpiX, sourceImage.DpiY, PixelFormats.Bgra32, sourceImage.Palette, pix, step);
            }

            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }

            #endregion
        }

    Danach noch einbinden in die Resourcen:

    <Window.Resources>
            <local:BitmapTransparentConverter x:Key="BitmapConverter">           
            </local:BitmapTransparentConverter>
    </Window.Resources>

    und nun konsumieren:

    <Image>
                <Image.Source>
                    <Binding Converter="{StaticResource BitmapConverter}" Source="img.bmp" />
                </Image.Source>           
    </Image>

    TransparentWpfShoot1 

    Aber Achtung. Performance ist nicht unbedingt optimal, wenn wir jedes mal (unnötig) konvertieren müssen um das Bild darzustellen.
    Die KonverterKlasse kann dafür natürlich beliebig ausgebaut werden (Caching, ...)

    Code zum Download