【问题标题】:How to Convert System.Windows.Media.Imaging.BitmapImage to System.Drawing.Image?如何将 System.Windows.Media.Imaging.BitmapImage 转换为 System.Drawing.Image?
【发布时间】:2016-06-09 21:56:45
【问题描述】:

XAML:

<ImageBrush x:Key="Symbol1Brush" ImageSource="Resources\Symbol1.png" Stretch="Uniform" />

代码:

// In some class
_imageProcessor = new ImageProcessor(Resources["Symbol1Image"] as BitmapImage)

public class ImageProcessor
{
    private readonly Bitmap _primaryMarkerSymbol;

    public ImageProcessor(BitmapImage primaryMarkerSymbol)
    {
        if (primaryMarkerSymbol == null)
            throw new ArgumentNullException("primaryMarkerSymbol");

        _primaryMarkerSymbol = new Bitmap(primaryMarkerSymbol.StreamSource);
    }

    public Bitmap ProcessImage()
    {
        Graphics g = Graphics.FromImage(img);
        g.DrawImage(_primaryMarkerSymbol);
        g.Flush();

        return img;
    }
}

_primaryMarkerSymbol = 新位图(primaryMarkerSymbol.StreamSource) 抛出异常:“null”的值对“stream”无效。

我假设如果 BitmapImage 是从 Resource 创建的,则不会填充 StreamSource。

还有哪些选择? 谢谢。

编辑:

重点是使用 XAML ResourceDictionary 中定义的源对象(例如 ImageBrush、BitmapImage)。

【问题讨论】:

标签: c# .net wpf


【解决方案1】:

您可能需要像这样复制位图的像素:

// test image
BitmapImage image = new BitmapImage(new Uri(@"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"));

// copy to byte array
int stride = image.PixelWidth * 4;
byte[] buffer = new byte[stride * image.PixelHeight];
image.CopyPixels(buffer, stride, 0);

// create bitmap
System.Drawing.Bitmap bitmap =
    new System.Drawing.Bitmap(
        image.PixelWidth,
        image.PixelHeight,
        System.Drawing.Imaging.PixelFormat.Format32bppArgb);

// lock bitmap data
System.Drawing.Imaging.BitmapData bitmapData =
    bitmap.LockBits(
        new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
        System.Drawing.Imaging.ImageLockMode.WriteOnly,
        bitmap.PixelFormat);

// copy byte array to bitmap data
System.Runtime.InteropServices.Marshal.Copy(
    buffer, 0, bitmapData.Scan0, buffer.Length);

// unlock
bitmap.UnlockBits(bitmapData);

【讨论】:

  • 感谢您的回复和代码。这是巨大的!尤其是互操作和位处理。我忘了添加使用 XAML 对象作为源(不是硬编码路径)的要求,对此感到抱歉。
  • 代码应该适用于任何 BitmapSource,无论是来自 XAML 还是代码都无关紧要。
【解决方案2】:

这对我使用资源文件设置图像源很有用

var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(MyProject.Properties.Resources.myImage.GetHbitmap(),
                                  IntPtr.Zero,
                                  Int32Rect.Empty,
                                  BitmapSizeOptions.FromEmptyOptions());
MyButton.Background = new ImageBrush(bitmapSource);

【讨论】:

    【解决方案3】:

    在构造函数中,我宁愿使用这个:

    System.Windows.Resources.StreamResourceInfo imageInfo = System.Windows.Application.GetResourceStream(primaryMarkerSymbol.UriSource);
    _primaryMarkerSymbol = Image.FromStream(imageInfo.Stream);
    

    【讨论】:

    • 请解释为什么您更喜欢您的方法而不是其他解决方案?有什么优势?
    【解决方案4】:

    在一个明确的时刻,我想出了一个我可以接受的解决方案。

    我使用 BitmapImage.UriSource 来获取图片的相对路径并加载图片:

    public class ImageProcessor
    {
        private readonly Image _primaryMarkerSymbol;
    
        public ImageProcessor(BitmapImage primaryMarkerSymbol)
        {
            _primaryMarkerSymbol = Image.FromFile(primaryMarkerSymbol.UriSource.ToString());
        }
    
        public Bitmap ProcessImage(string fileName)
        {
            var img = new Bitmap(fileName);
            Graphics g = Graphics.FromImage(img);
            g.DrawImage(_primaryMarkerSymbol);
            g.Flush();
    
            return img;
        }
    }
    

    如果我可以使用对象本身在图形上绘制图像而不是通过路径加载,那就太好了。因此,欢迎您提出更好的想法。

    【讨论】:

    • 好吧,如果UriSource 属性实际设置并且仍然有效,那没关系。然后你也可以写new Bitmap(Image.FromFile(...))
    • 它是在 中设置的,一开始我只是没有意识到。
    • 是的,在您的具体情况下确实如此。但是当 UriSource 和 StreamSource 都没有设置时,您仍然可以复制像素。
    • 感谢克莱门斯的澄清。
    • 对这个答案投了反对票的人可以解释它有什么问题。更好的是,发布您自己的答案。
    猜你喜欢
    • 1970-01-01
    • 2012-02-14
    • 2011-04-14
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    • 2021-09-07
    • 2022-01-24
    相关资源
    最近更新 更多