2014-10-26 55 views
0

我有一个小图像编辑程序,打开一个图像,并花哨的东西。在这种情况下,我试图调整像素的亮度。这个问题没有得到正确的像素,它为我的滑块在ValueChanged事件中创建了Bitmap/BitmapSources。WPF/C#更新(和处置)ValueChanged事件中的位图/ BitmapSource?

所以基本上用户会点击一个按钮,它会打开一个带有滑块的新窗口。这个新窗口将复制原始位图以备后用。

当滑块的值发生变化时,它将从原始位置创建一个新的位图,并相应增加亮度,从中创建一个新的位图源并更新图像控件的源。即使我正在使用“使用”语句,滑动这么长时间后仍然会出现“内存不足”异常。

任何想法,为什么这是?有没有更好的解决方法可以实现相同的目的?我已经包含下面的代码:

using Imagin.Slideshow; 
using System; 
using System.Collections.Generic; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Shapes; 

namespace Imagin 
{ 
    /// <summary> 
    /// Interaction logic for BrightnessWindow.xaml 
    /// </summary> 
    public partial class BrightnessWindow : Window 
    { 

     public int Increase; 

     private System.Drawing.Bitmap Bitmap; 
     private System.Drawing.Bitmap NewBitmap; 

     private MainWindow ParentWindow; 

     public BrightnessWindow(MainWindow m) 
     { 

      InitializeComponent(); 

      this.ParentWindow = m; 

      this.Bitmap = (System.Drawing.Bitmap)this.ParentWindow.Document.Bitmap.Clone(); 

     } 

     private void slider1_ValueChanged(object sender, RoutedEventArgs e) 
     { 

      using (System.Drawing.Bitmap b = (System.Drawing.Bitmap)this.ParentWindow.Document.Bitmap.Clone(new RectangleF() { Width = (int)this.ParentWindow.Document.Bitmap.Width, Height = (int)this.ParentWindow.Document.Bitmap.Height, X = 0, Y = 0 }, this.ParentWindow.Document.Bitmap.PixelFormat)) 
      { 
       this.ParentWindow.SetPixels(b, AdjustmentTypes.Brightness, Convert.ToInt32(this.slider1.Value)); 
       BitmapSource m = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); 
       this.ParentWindow.image1.Source = m; 
       this.NewBitmap = (System.Drawing.Bitmap)b.Clone(); 
      } 

     } 

     private void applyButton_Click(object sender, RoutedEventArgs e) 
     { 
      if (this.NewBitmap != null) 
      { 
       this.ParentWindow.Document.Bitmap = this.NewBitmap; 
      } 
      this.Close(); 
     } 

     private void cancelButton_Click(object sender, RoutedEventArgs e) 
     { 
      this.ParentWindow.Document.Refresh(); 

      this.Close(); 
     } 
    } 
} 

我想知道的另一件事情是,如果有更好的方法来改变主窗口的控制,而不必把它作为参数传递,或者这是那样的首选方法事情?谢谢!

+0

所以我想通了,没有这条线是造成我们的问题: '如果(!this.NewBitmap = NULL){this.NewBitmap.Dispose(); }' 但是,现在我收到错误“System.Drawing.dll中发生类型'System.Runtime.InteropServices.ExternalException'的异常,但未在用户代码中处理;其他信息:GDI +中发生了一般性错误。从以下行开始: 'BitmapSource m = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b.GetHbitmap(),IntPtr.Zero,Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions());' – 2014-10-26 14:26:17

+0

在将新的BitmapSource或Bitmap设置为任何事情都可以先试试原版。正如我看到你不使用任何BrightnessWindow :: Bitmap字段。 – 2014-10-26 14:26:26

+0

好我是对的。 :) – 2014-10-26 14:33:46

回答

0

http://msdn.microsoft.com/en-us/library/1dz311e4%28v=vs.110%29.aspx

每次使用bitmap.GetHbitmap创建gdibitmap的新实例。根据msdn链接,“您负责调用GDI DeleteObject方法来释放GDI位图对象所使用的内存。有关GDI位图的更多信息,请参阅Windows GDI文档中的Bitmaps。”

我拉那家伙出一个变量,当你用它做调用DeleteObject就可以了,否则你只是创造n gdibitmaps其中n = number of times you move the slider,绝不处置他们。

编辑:突出显示该行:

//Somewhere in the class 
[System.Runtime.InteropServices.DllImport("gdi32.dll")] 
public static extern bool DeleteObject(IntPtr hObject); 

    private void slider1_ValueChanged(object sender, RoutedEventArgs e) 
    { 

     using (System.Drawing.Bitmap b = (System.Drawing.Bitmap)this.ParentWindow.Document.Bitmap.Clone(new RectangleF() { Width = (int)this.ParentWindow.Document.Bitmap.Width, Height = (int)this.ParentWindow.Document.Bitmap.Height, X = 0, Y = 0 }, this.ParentWindow.Document.Bitmap.PixelFormat)) 
     { 
      this.ParentWindow.SetPixels(b, AdjustmentTypes.Brightness, Convert.ToInt32(this.slider1.Value)); 
      IntPtr hbitmap = b.GetHbitmap(); //create variable so we don't orphan the object 
      BitmapSource m = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); //use variable 
      this.ParentWindow.image1.Source = m; 
      this.NewBitmap = (System.Drawing.Bitmap)b.Clone(); 
      DeleteObject(hbitmap); //delete gdi object 
     } 

    } 
+1

在研究你的答案时,我遇到了这个问题:[link](http://stackoverflow.com/questions/1546091/wpf-createbitmapsourcefromhbitmap-memory-leak),它帮助我正确地处理对象。编译器无法识别DeleteObject方法,所以希望这可以帮助遇到同样问题的其他人。谢谢! – 2014-10-27 00:48:15