web-dev-qa-db-fra.com

Y at-il un bon moyen de convertir entre BitmapSource et Bitmap?

Autant que je sache, le seul moyen de convertir BitmapSource en bitmap consiste à utiliser du code non sécurisé ... Comme ceci (from Lesters WPF blog ):

myBitmapSource.CopyPixels(bits, stride, 0);

unsafe
{
  fixed (byte* pBits = bits)
  {
      IntPtr ptr = new IntPtr(pBits);

      System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(
        width,
        height,
        stride,
        System.Drawing.Imaging.PixelFormat.Format32bppPArgb,ptr);

      return bitmap;
  }
}

Pour faire l'inverse:

System.Windows.Media.Imaging.BitmapSource bitmapSource =
  System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
    bitmap.GetHbitmap(),
    IntPtr.Zero,
    Int32Rect.Empty,
    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

Y at-il un moyen plus facile dans le cadre? Et quelle est la raison pour laquelle il n'est pas là (si ce n'est pas le cas)? Je pense que c'est assez utilisable.

J'en ai besoin parce que j'utilise AForge pour effectuer certaines opérations sur les images dans une application WPF. WPF veut montrer BitmapSource/ImageSource mais AForge fonctionne sur des bitmaps.

36
JohannesH

Il est possible de se passer de code non sécurisé en utilisant Bitmap.LockBits et de copier les pixels de la BitmapSource directement dans la Bitmap

Bitmap GetBitmap(BitmapSource source) {
  Bitmap bmp = new Bitmap(
    source.PixelWidth,
    source.PixelHeight,
    PixelFormat.Format32bppPArgb);
  BitmapData data = bmp.LockBits(
    new Rectangle(Point.Empty, bmp.Size),
    ImageLockMode.WriteOnly,
    PixelFormat.Format32bppPArgb);
  source.CopyPixels(
    Int32Rect.Empty,
    data.Scan0,
    data.Height * data.Stride,
    data.Stride);
  bmp.UnlockBits(data);
  return bmp;
}
58
josef.axa

Vous pouvez simplement utiliser ces deux méthodes:

public static BitmapSource ConvertBitmap(Bitmap source)
{
    return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                  source.GetHbitmap(),
                  IntPtr.Zero,
                  Int32Rect.Empty,
                  BitmapSizeOptions.FromEmptyOptions());
}

public static Bitmap BitmapFromSource(BitmapSource bitmapsource)
{
    Bitmap bitmap;
    using (var outStream = new MemoryStream())
    {
        BitmapEncoder enc = new BmpBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(bitmapsource));
        enc.Save(outStream);
        bitmap = new Bitmap(outStream);
    }
    return bitmap;
}

Cela fonctionne parfaitement pour moi.

29
melvas

Est-ce ce que vous cherchez?

Bitmap bmp = System.Drawing.Image.FromHbitmap(pBits);
1
caesay

C'est net et plus rapide que la lumière:

  return Imaging.CreateBitmapSourceFromHBitmap( bitmap.GetHbitmap(), IntPtr.Zero,
      Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions() );
1
Mauro Sampietro

Voici un code permettant de définir un fond transparent pour toute ressource bitmap dans un dictionnaire de ressources (et non dans Resources.resx, souvent utilisé dans Windows.Forms). J'appelle cette méthode avant InitializeComponent () - méthode. Les méthodes 'ConvertBitmap (source Bitmap)' et BitmapFromSource (BitmapSource bitmapsource) sont mentionnées dans le message de melvas ci-dessus.

private void SetBitmapResourcesTransparent()
    {
        Image img;
        BitmapSource bmpSource;
        System.Drawing.Bitmap bmp;
        foreach (ResourceDictionary resdict in Application.Current.Resources.MergedDictionaries)
        {
            foreach (DictionaryEntry dictEntry in resdict)
            {
                // search for bitmap resource
                if ((img = dictEntry.Value as Image) is Image 
                    && (bmpSource = img.Source as BitmapSource) is BitmapSource
                    && (bmp = BitmapFromSource(bmpSource)) != null)
                {
                    // make bitmap transparent and assign it back to ressource
                    bmp.MakeTransparent(System.Drawing.Color.Magenta);
                    bmpSource = ConvertBitmap(bmp);
                    img.Source = bmpSource;
                }
            }

        }

    }
1
user3318309

Vous pouvez partager les pixeldata entre les deux espaces de noms. Vous n'êtes pas obligé de convertir.

Utilisez le SharedBitmapSource. https://stackoverflow.com/a/32841840/690656

0
Andreas