图像编辑例外

我正在使用MVVM在WPF应用程序中工作。 在imageSlider中加载和编辑图像会给我错误和exception。

加载图像: Insufficient memory to handle编辑图像: Sharing violation

视图模型:

 public class ImageList : INotifyPropertyChanged { #region Fields private ObservableCollection images = new ObservableCollection(); private int selectedIndex; private ImageItem currentImage; #endregion Fields #region Properties public ObservableCollection Images { get { return images; } set { images = value; } } public int SelectedIndex { get { return selectedIndex; } set { if(value  -1) { selectedIndex = value; OnPropertyChanged(); CurrentImage = Images[selectedIndex]; } } } public ImageItem CurrentImage { get { return currentImage; } set { currentImage = value; OnPropertyChanged(); } } #endregion Properties #region Public Methods public void Next() { SelectedIndex ++; } public void Back() { SelectedIndex--; } #endregion Public Methods #region Methods public void AddNewImage() { OpenFileDialog dlg = new OpenFileDialog(); dlg.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.gif, *.png, *.bmp, *.tif) | *.jpg; *.jpeg; *.jpe; *.gif; *.png, *.bmp, *.tif"; dlg.ShowDialog(); if(dlg.FileName != "") { Images.Add(new ImageItem() { URI = new Uri(dlg.FileName) }); SelectedIndex = Images.Count - 1; } } #endregion Methods #region Constructors public ImageList() { _canExecute = true; } #endregion Constructors #region Commands private ICommand _clickCommand; public ICommand ClickCommand { get { return _clickCommand ?? (_clickCommand = new CommandHandler(() => AddNewImage(), _canExecute)); } } private bool _canExecute; private ICommand nextCommand; public ICommand NextCommand { get { if (nextCommand == null) { nextCommand = new CommandHandler(()=> OnNextCommand(), true); } return nextCommand; } set { nextCommand = value; } } private void OnNextCommand() { Next(); } private ICommand backCommand; public ICommand BackCommand { get { if(backCommand == null) { backCommand = new CommandHandler(() => OnBackCommand(), true); } return backCommand; } set { backCommand = value; } } private void OnBackCommand() { Back(); } private ICommand _clickCommand; public ICommand ClickCommand { get { return _clickCommand ?? (_clickCommand = new CommandHandler(() => AddNewImage(), _canExecute)); } } private ICommand _EditImageCommand; public ICommand EditImageCommand { get { return _EditImageCommand ?? (_EditImageCommand = new CommandHandler(obj => EditImage(obj), _canExecute)); } } #endregion Commands public void EditImage(object obj) { string ss = ((ImageItem)obj).URI.AbsolutePath; Process proc = Process.Start(ss); if (proc != null) { proc.EnableRaisingEvents = true; ProcessStartInfo startInfo = new ProcessStartInfo(); //startInfo.Verb = "edit"; startInfo.FileName = ("mspaint.exe"); proc.StartInfo = startInfo; } } #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion INotifyPropertyChanged }` 

模型:

  public class ImageItem { public Uri URI { get; set; } private BitmapSource _Source; public BitmapSource Source { get { try { if (_Source == null) _Source = new BitmapImage(URI);//lazy loading } catch (Exception) { _Source = null; } return _Source; } } public void Save(string filename) { var img = BitmapFrame.Create(Source); var encoder = new JpegBitmapEncoder(); encoder.Frames.Add(img); using (var saveStream = System.IO.File.OpenWrite(filename)) encoder.Save(saveStream); } } 

XAML

              <!---->   

上面的代码适用于imageSlider(Next和Back)。 但是在编辑期间它会在mspaint打开,当我保存它时会抛出我的Sharing violation error 。 厌倦了在SO和这里发布的一些解决方案。 尝试这些时,我可以编辑图像并保存没有任何错误。 但是当使用Slider控件(Next和Back)并且当它加载更重的图像时,经常它会让我Insufficient memory to handleexception。

所以现在我需要消除这两个问题。 请帮助。

对于观看者来说,编辑器需要做一些不同的事情

您的模型需要更新为ViewModel,因为它将会更改(您可以使用该模型来构建ViewModel,但是在这种情况下,模型中的function很少,您也可以使用FIleInfo类作为模型)

 public class ImageEditor: IDisposable,INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private List images = new List(); private FileInfo _ImageFile; public static readonly PropertyChangedEventArgs FilenameProperty = new PropertyChangedEventArgs(nameof(ImageFile)); public FileInfo ImageFile { get { return _ImageFile; } set { _ImageFile = value; Strokes.Clear(); PropertyChanged?.Invoke(this, ImageFrameProperty); } } private int selectedIndex; public static readonly PropertyChangedEventArgs SelectedIndexProperty = new PropertyChangedEventArgs(nameof(SelectedIndex)); public int SelectedIndex { get { return selectedIndex; } private set { if (value < images.Count && value > -1) { selectedIndex = value; PropertyChanged?.Invoke(this, SelectedIndexProperty); ImageFile = images[selectedIndex]; Load(); } } } MemoryStream mem; private BitmapSource _ImageFrame; public static readonly PropertyChangedEventArgs ImageFrameProperty = new PropertyChangedEventArgs(nameof(ImageFrame)); public BitmapSource ImageFrame { get { return _ImageFrame; } set { _ImageFrame = value; PropertyChanged?.Invoke(this, ImageFrameProperty); } } public StrokeCollection Strokes { get; } = new StrokeCollection(); public void Open(FileInfo file) { images.Add(file); SelectedIndex = images.Count - 1; } public void Next() { SelectedIndex++; } public void Back() { SelectedIndex--; } public void Load() { ImageFile.Refresh(); if (ImageFile.Exists) { if (mem != null) { mem.Dispose(); } using (var stream = ImageFile.OpenRead()) { mem = new MemoryStream(); stream.CopyTo(mem); } ImageFrame = BitmapFrame.Create(mem); } } public void Dispose() { if (mem != null) { mem.Dispose(); } ImageFrame = null; } public void Save() { DrawingVisual drawingVisual = new DrawingVisual(); using (DrawingContext drawingContext = drawingVisual.RenderOpen()) { drawingContext.DrawImage(ImageFrame, new Rect(0, 0, ImageFrame.Width, ImageFrame.Height)); foreach (var item in Strokes) { item.Draw(drawingContext); } drawingContext.Close(); Strokes.Clear(); var width = ImageFrame.Width; var height = ImageFrame.Height; var bitmap = new RenderTargetBitmap((int)width, (int)height, 96, 96, PixelFormats.Pbgra32); bitmap.Render(drawingVisual); ImageFrame = bitmap; var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(ImageFrame)); using (var stream = ImageFile.OpenWrite()) { encoder.Save(stream); } } } } 

注意:因为我们正在使用带有using语句的内存流,所以我们最好使用IDisposable接口进行清理

这样做是创建一个内存驻留位图,然后使用它作为一个帧,这将删除使用带有URI的普通位图获得的文件上的openRead锁定

接下来我们有编辑本身

             White Black Yellow Red Cyan SpringGreen                        public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); CommandBindings.Add(new CommandBinding(ApplicationCommands.Save, execSave, hasChanged)); CommandBindings.Add(new CommandBinding(ApplicationCommands.Open, execOpen)); CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, execUndo, hasChanged)); } private void execOpen(object sender, ExecutedRoutedEventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); if(dlg.ShowDialog() ?? false) { editor.Open(new System.IO.FileInfo(dlg.FileName)); } e.Handled = true; } private void hasChanged(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = editor.Strokes.Count > 0; e.Handled = true; } private void execUndo(object sender, ExecutedRoutedEventArgs e) { editor.Strokes.Remove(editor.Strokes.Last()); e.Handled = true; } private void execSave(object sender, ExecutedRoutedEventArgs e) { editor.Save(); e.Handled = true; } private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { editor.Dispose(); } private void Next_Click(object sender, RoutedEventArgs e) { editor.Next(); } private void Back_Click(object sender, RoutedEventArgs e) { editor.Back(); } } 

请注意,如果您在图像上进行任何缩放/拉伸,则需要在渲染之前反转Strokes上的操作,否则编辑将与屏幕相关而不是图像