据我所知,从BitmapSource转换为Bitmap的唯一方法是通过不安全的代码...像这样(来自Lesters WPF博客):
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;
  }
}
做反过来:
System.Windows.Media.Imaging.BitmapSource bitmapSource =
  System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
    bitmap.GetHbitmap(),
    IntPtr.Zero,
    Int32Rect.Empty,
    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
框架中有更简单的方法吗?它不在那里的原因是什么(如果不是)?我认为它相当实用.
我需要它的原因是因为我使用AForge在WPF应用程序中执行某些图像操作.WPF希望显示BitmapSource/ImageSource,但AForge可以在Bitmaps上运行.
在WPF中,该System.Windows.Clipboard.getImage()函数返回一个BitmapSource对象.作为一个来自WinForms背景的WPF新手,我不清楚如何将这个图像保存到文件中.我必须采取哪些步骤?
我需要解析Clipboard.GetImage()(a BitmapSource)的内容到a BitmapImage.有谁知道怎么做?
我需要Image在30Hz处在组件上绘制图像.我用这个代码:
public MainWindow()
    {
        InitializeComponent();
        Messenger.Default.Register<Bitmap>(this, (bmp) =>
        {
            ImageTarget.Dispatcher.BeginInvoke((Action)(() =>
            {
                var hBitmap = bmp.GetHbitmap();
                var drawable = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                  hBitmap,
                  IntPtr.Zero,
                  Int32Rect.Empty,
                  BitmapSizeOptions.FromEmptyOptions());
                DeleteObject(hBitmap);
                ImageTarget.Source = drawable;
            }));
        });
    }
问题是,使用此代码,我的CPU使用率约为80%,如果没有转换,则大约为6%.
那么为什么转换位图这么久呢?
是否有更快的方法(使用不安全的代码)?
系统:Windows XP SP3,.NET 3.5,4GB RAM,双1.6gHz
我有一个WPF应用程序加载和转换(使用Storyboard动画)非常大的PNG.这些PNG的分辨率为8190x1080.当应用程序运行时,它似乎缓存图像,系统内存缓慢爬升.最终它会阻塞系统并抛出OutOfMemoryException.
以下是我目前正在尝试解决此问题的步骤:
1)我从应用程序中删除BitmapSource对象
2)我在加载BitmapSource时将BitmapSource BitmapCacheOption设置为None
3)我在加载后冻结BitmapSource.
4)我将删除对使用源的Image的所有引用以及对源本身的任何引用.
5)完成上述步骤后,手动调用GC.Collect().
希望找出为什么WPF挂在这些映像的内存上,以及确保用于加载它们的内存得到正确恢复的可能解决方案.
我想在WPF中创建一个On/Off按钮,我想让它在用户点击它时改变它的外观(如果它是关闭,如果它关掉,则切换到打开)使用图像.我将要使用的图像添加到资源中:
 <Window.Resources>
    <Image x:Key="Off1" Source="/WPFApplication;component/Images/off_button.png" Height="30" Width="70" />
    <Image x:Key="On1" Source="/WPFApplication;component/Images/on_button.png" Height="30" Width="70"/>
 </Window.Resources>
而事件代码是,"flag"是一个布尔局部变量,初始化为true:
 private void OnOff1Btn_Click(object sender, RoutedEventArgs e)
    {
        if (flag)
        {
            OnOff1Btn.Content = FindResource("Off1");
            flag = false;     
        }
        else
        {
            OnOff1Btn.Content = FindResource("On1");
            flag  = true;
        }
    }
现在我需要创建2个开/关按钮,它们的行为相同.当我尝试为第二个按钮使用相同的资源时,我得到了一个例外:
 Specified element is already the logical child of another element. Disconnect it first.
我可以在第二个按钮中使用相同的图像资源,还是必须将图像作为具有不同密钥的资源再次添加?
我的应用程序中存在内存泄漏问题,它会加载大量图像.我对C#很陌生,并认为我的内存泄漏问题已经过去了.我无法弄清楚问题 - 也许我正在使用一些我无法正确处理的非托管模块?
为了说明我的问题,我简化了导致问题的核心,并将其转移到一个干净的项目中.请注意,这都是愚蠢的代码,不能反映它来自的原始应用程序.在测试应用程序中,我有2个按钮,触发两个事件.
按钮1 - 创建:将对象设置为datacontext.这将通过将对象设置为DataContext来加载图像并使它们保持活动状态:
var imgPath = @"C:\some_fixed_path\img.jpg";
DataContext = new SillyImageLoader(imgPath);
按钮2 - 清理:我的理解是,如果我放开持有SillyImageLoader再次保存图像的引用,那么这将被删除.我还明确地触发垃圾收集,只是为了在删除引用后立即查看内存量.
DataContext = null; 
System.GC.Collect();
测试时我正在加载一个974KB的jpeg图像.保持30位图表示可以将我的应用程序的内存使用量从大约18MB增加到大约562MB.好.但是当我清理时,内存只下降到~292MB.如果我重复Create + CleanUp,我还剩下另外~250MB的内存.所以显然某人仍然持有一些东西.
这是SillyImageLoader代码:
namespace MemoryLeakTest
{
    using System;
    using System.Drawing;
    using System.Windows;
    using System.Windows.Interop;
    using System.Windows.Media.Imaging;
    public class SillyImageLoader
    {
        private BitmapSource[] _images; 
        public SillyImageLoader(string path)
        {
            DummyLoad(path);
        }
        private void DummyLoad(string path)
        {
            const int numberOfCopies = 30;
            _images = new BitmapSource[numberOfCopies];
            for (int i = 0; i < numberOfCopies; i++)
            {
                _images[i] = LoadImage(path);
            } …在c#中创建空(0x0 px或1x1 px和完全透明)BitmapSource实例的最快(几行代码和低资源使用)方法是什么,当没有任何应该呈现时使用.
我试图将BitmapSource的一部分复制到WritableBitmap.
到目前为止这是我的代码:
var bmp = image.Source as BitmapSource;
var row = new WriteableBitmap(bmp.PixelWidth, bottom - top, bmp.DpiX, bmp.DpiY, bmp.Format, bmp.Palette);
row.Lock();
bmp.CopyPixels(new Int32Rect(top, 0, bmp.PixelWidth, bottom - top), row.BackBuffer, row.PixelHeight * row.BackBufferStride, row.BackBufferStride);
row.AddDirtyRect(new Int32Rect(0, 0, row.PixelWidth, row.PixelHeight));
row.Unlock();
我得到"ArgumentException:值不在预期的范围内." 在线CopyPixels.
我试着换row.PixelHeight * row.BackBufferStride用row.PixelHeight * row.PixelWidth,但后来我得到一个错误说价值太低.
我找不到使用这个重载的单个代码示例CopyPixels,所以我正在寻求帮助.
谢谢!
我试图通过使用Image和BitmapSource从WPF中显示原始数据创建的位图:
Int32[] data = new Int32[RenderHeight * RenderWidth];
for (Int32 i = 0; i < RenderHeight; i++)
{
    for (Int32 j = 0; j < RenderWidth; j++)
    {
        Int32 index = j + (i * RenderHeight);
        if (i + j % 2 == 0)
            data[index] = 0xFF0000;
        else
            data[index] = 0x00FF00;
    }
}
BitmapSource source = BitmapSource.Create(RenderWidth, RenderHeight, 96.0, 96.0, PixelFormats.Bgr32, null, data, 0);
RenderImage.Source = source;
但是,对BitmapSource.Create的调用会抛出ArgumentException,并说"值不在预期范围内".这不是这样做的方法吗?我没有正确地打电话吗?
bitmapsource ×10
wpf ×9
c# ×8
.net ×3
bitmap ×3
memory-leaks ×2
bitmapimage ×1
copy ×1
stride ×1
xaml ×1