// // PictureLazy.cs: // // Author: // Sebastien Mouy // // Copyright (C) 2018 Starwer // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License version // 2.1 as published by the Free Software Foundation. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA // using System; using System.IO; namespace TagLib { /// /// This class implements and provides /// mechanisms for loading pictures from files. /// Contrary to , a reference to a file /// where the picture is located can be given and the picture /// is lazily loaded from the file, meaning that it will be /// read from the file only when needed. This saves time and /// memory if the picture loading is not required. /// public class PictureLazy : IPicture, ILazy { #region Private Fields /// /// Contains the mime-type. /// string mime_type; /// /// Contains the content type. /// PictureType type; /// /// Contains the filename. /// string filename; /// /// Contains the picture data. /// ByteVector data; /// /// Stream where the picture is located /// File.IFileAbstraction file; /// /// Offset from where the picture start in the /// readonly long stream_offset; /// /// Size of the picture in the (-1 = until end of Stream) /// readonly long stream_size = -1; #endregion #region Constructors /// /// Constructs and initializes a new instance of with no data or values. /// public PictureLazy () { } /// /// Constructs and initializes a new instance of from a file. /// The content will be lazily loaded. /// /// /// A object containing the path of the /// file to read. /// /// /// is . /// public PictureLazy (string path) { if (path == null) throw new ArgumentNullException (nameof (path)); file = new File.LocalFileAbstraction (path); filename = Path.GetFileName (path); Description = filename; mime_type = Picture.GetMimeFromExtension (filename); type = mime_type.StartsWith ("image/") ? PictureType.FrontCover : PictureType.NotAPicture; } /// /// Constructs and initializes a new instance of from a file abstraction. /// The content will be lazily loaded. /// /// /// A object containing /// abstraction of the file to read. /// /// /// The position in bytes where the picture is located in the /// . /// /// /// The size in bytes of the picture in the /// (default: read all). /// /// /// is . /// public PictureLazy (File.IFileAbstraction abstraction, long offset = 0, long size = -1) { if (abstraction == null) throw new ArgumentNullException (nameof (abstraction)); file = abstraction; stream_offset = offset; stream_size = size; filename = abstraction.Name; Description = abstraction.Name; if (!string.IsNullOrEmpty (filename) && filename.Contains (".")) { mime_type = Picture.GetMimeFromExtension (filename); type = mime_type.StartsWith ("image/") ? PictureType.FrontCover : PictureType.NotAPicture; } } /// /// Constructs and initializes a new instance of by using the contents of a object. /// The content will not be lazily loaded. /// /// /// A object containing picture data /// to use. /// /// /// is . /// public PictureLazy (ByteVector data) { if (data == null) throw new ArgumentNullException (nameof (data)); Data = new ByteVector (data); string ext = Picture.GetExtensionFromData (data); MimeType = Picture.GetMimeFromExtension (ext); if (ext != null) { type = PictureType.FrontCover; filename = Description = "cover" + ext; } else { type = PictureType.NotAPicture; filename = "UnknownType"; } } /// /// Constructs and initializes a new instance of by doing a shallow copy of . /// The content will not be lazily loaded. /// /// /// A object containing picture data /// to convert to an Picture. /// public PictureLazy (IPicture picture) { mime_type = picture.MimeType; type = picture.Type; filename = picture.Filename; Description = picture.Description; data = picture.Data; } #endregion #region Public Methods /// /// Load the picture data from the file, /// if not done yet. /// public void Load () { // Already loaded ? if (data != null) return; // Load the picture from the stream Stream stream = null; try { if (stream_size == 0) { data = new ByteVector (); } else if (stream_size > 0) { stream = file.ReadStream; stream.Seek (stream_offset, SeekOrigin.Begin); int count = 0, read = 0, needed = (int)stream_size; byte[] buffer = new byte[needed]; do { count = stream.Read (buffer, read, needed); read += count; needed -= count; } while (needed > 0 && count != 0); data = new ByteVector (buffer, read); } else { stream = file.ReadStream; stream.Seek (stream_offset, SeekOrigin.Begin); data = ByteVector.FromStream (stream); } } finally { // Free the resources if (stream != null && file != null) { file.CloseStream (stream); } file = null; } // Retrieve remaining properties from data (if required) if (mime_type == null) { string ext = Picture.GetExtensionFromData (data); MimeType = Picture.GetMimeFromExtension (ext); if (ext != null) { type = PictureType.FrontCover; if (filename == null) filename = Description = "cover" + ext; } else { type = PictureType.NotAPicture; if (filename == null) filename = "UnknownType"; } } } #endregion #region Public Properties /// /// Gets and sets the mime-type of the picture data /// stored in the current instance. /// /// /// A object containing the mime-type /// of the picture data stored in the current instance. /// public string MimeType { get { if (mime_type == null) Load (); return mime_type; } set { mime_type = value; } } /// /// Gets and sets the type of content visible in the picture /// stored in the current instance. /// /// /// A containing the type of /// content visible in the picture stored in the current /// instance. /// public PictureType Type { get { if (type == PictureType.Other && mime_type == null) Load (); return type; } set { type = value; } } /// /// Gets and sets a filename of the picture stored in the /// current instance. /// /// /// A object containing a fielname, with /// extension, of the picture stored in the current instance. /// public string Filename { get { if (filename == null) Load (); return filename; } set { filename = value; } } /// /// Gets and sets a description of the picture stored in the /// current instance. /// /// /// A object containing a description /// of the picture stored in the current instance. /// public string Description { get; set; } /// /// Gets and sets the picture data stored in the current /// instance. /// /// /// A object containing the picture /// data stored in the current instance. /// public ByteVector Data { get { if (data == null) Load (); return data; } set { data = value; } } /// /// Gets an indication whether the picture is loaded. /// public bool IsLoaded { get { return data != null; } } #endregion } }