// Copyright 2014-2018 Dirk Lemstra (https://github.com/dlemstra/MagickViewer) // // Licensed under the ImageMagick License (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // // https://www.imagemagick.org/script/license.php // // Unless required by applicable law or agreed to in writing, software distributed under the // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either // express or implied. See the License for the specific language governing permissions and // limitations under the License. using System; using System.IO; using System.Threading; using System.Threading.Tasks; using ImageMagick; namespace Orbit.Module.ViewModel { class ImageManager : IDisposable { private static readonly object Semaphore = new object(); private readonly ImageIterator _imageIterator; private int _index; private MagickImageCollection _images; public event EventHandler Loaded; public event EventHandler Loading; public ImageManager() { _imageIterator = new ImageIterator(); } public string FileInfo { get { if (_imageIterator.Current == null) return null; string fileInfo = _imageIterator.Current.FullName; if (_images != null) { if (_images.Count > 1) fileInfo += " (" + (_index + 1) + " of " + _images.Count + ")"; if (Image != null) fileInfo += "\n" + Image.Format.ToString().ToUpperInvariant() + "\n" + Image.Width + "x" + Image.Height; } return fileInfo; } } public IMagickImage Image { get { if (_images.Count == 0) return null; return _images[_index]; } } public void Dispose() { DisposeImages(); } public async Task Load(string fileName) { await Load(new FileInfo(fileName)); } public async Task Next() { FileInfo file = _imageIterator.Next(); if (file != null) await Load(file); } public void NextFrame() { if (_images.Count < 2) return; if (++_index == _images.Count) _index = 0; Loaded?.Invoke(this, null); } public async Task Previous() { FileInfo file = _imageIterator.Previous(); if (file != null) await Load(file); } public void PreviousFrame() { if (_images.Count < 2) return; if (--_index == -1) _index = _images.Count - 1; Loaded?.Invoke(this, null); } private void ConstructImages() { DisposeImages(); _images = new MagickImageCollection(); _index = 0; } private void DisposeImages() { if (_images == null) return; _images.Dispose(); _images = null; } private async Task Load(FileInfo file) { Monitor.Enter(Semaphore); Loading?.Invoke(this, null); _imageIterator.Current = file; var ex = await Task.Run(() => ReadImage(file)); Loaded?.Invoke(this, ex); Monitor.Exit(Semaphore); } private Exception ReadImage(FileInfo file) { ConstructImages(); MagickErrorException exception = null; try { MagickReadSettings settings = new MagickReadSettings(); _images.Read(file, settings); foreach (var img in _images) { img.AutoOrient(); } } catch (MagickErrorException ex) { exception = ex; } return exception; } } }