我有一个小型的图像编辑程序,可以打开一个图像并为它做一些奇特的东西。在这种情况下,我试图调整像素的亮度。问题是没有正确的像素,它在我的滑块的ValueChanged事件中处理了Bitmap / BitmapSources。
所以基本上用户会点击一个按钮,它会打开一个带滑块的新窗口。这个新窗口会生成原始位图的副本供以后使用。
当滑块的值发生变化时,它将从原始位图创建一个具有相应亮度增加的新位图,从中创建一个新的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();
}
}
}
我想知道的另一件事是,是否有更好的方法来改变MainWindow的控件而不必将其作为参数传递,或者这是否是这种事情的首选方法?谢谢!
答案 0 :(得分:0)
http://msdn.microsoft.com/en-us/library/1dz311e4%28v=vs.110%29.aspx
每次使用bitmap.GetHbitmap时,都会创建一个gdibitmap的新实例。根据msdn链接,“您负责调用GDI DeleteObject方法来释放GDI位图对象使用的内存。有关GDI位图的更多信息,请参阅Windows GDI文档中的位图。”
我会把那个人拉到变量上并在完成后调用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
}
}