// // Picture.cs: Provides IPicture and Picture. // // Author: // Aaron Bockover (abockover@novell.com) // Brian Nickel (brian.nickel@gmail.com) // // Original Source: // attachedpictureframe.cpp from TagLib // // Copyright (C) 2006 Novell, Inc. // Copyright (C) 2007 Brian Nickel // Copyright (C) 2004 Scott Wheeler (Original Implementation) // // 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; namespace TagLib { /// /// Specifies the type of content appearing in the picture. /// public enum PictureType { /// /// The picture is of a type other than those specified. /// Other = 0x00, /// /// The picture is a 32x32 PNG image that should be used when /// displaying the file in a browser. /// FileIcon = 0x01, /// /// The picture is of an icon different from . /// OtherFileIcon = 0x02, /// /// The picture is of the front cover of the album. /// FrontCover = 0x03, /// /// The picture is of the back cover of the album. /// BackCover = 0x04, /// /// The picture is of a leaflet page including with the /// album. /// LeafletPage = 0x05, /// /// The picture is of the album or disc itself. /// Media = 0x06, // Image from the album itself /// /// The picture is of the lead artist or soloist. /// LeadArtist = 0x07, /// /// The picture is of the artist or performer. /// Artist = 0x08, /// /// The picture is of the conductor. /// Conductor = 0x09, /// /// The picture is of the band or orchestra. /// Band = 0x0A, /// /// The picture is of the composer. /// Composer = 0x0B, /// /// The picture is of the lyricist or text writer. /// Lyricist = 0x0C, /// /// The picture is of the recording location or studio. /// RecordingLocation = 0x0D, /// /// The picture is one taken during the track's recording. /// DuringRecording = 0x0E, /// /// The picture is one taken during the track's performance. /// DuringPerformance = 0x0F, /// /// The picture is a capture from a movie screen. /// MovieScreenCapture = 0x10, /// /// The picture is of a large, colored fish. /// ColoredFish = 0x11, /// /// The picture is an illustration related to the track. /// Illustration = 0x12, /// /// The picture contains the logo of the band or performer. /// BandLogo = 0x13, /// /// The picture is the logo of the publisher or record /// company. /// PublisherLogo = 0x14, /// /// In fact, this is not a Picture, but another file-type. /// NotAPicture = 0xff } /// /// This interface provides generic information about a picture, /// including its contents, as used by various formats. /// public interface IPicture { /// /// 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. /// string MimeType { get; set; } /// /// 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. /// PictureType Type { get; set; } /// /// Gets and sets a filename of the picture stored in the /// current instance. /// /// /// A object containing the filename, /// with its extension, of the picture stored in the current /// instance. /// string Filename { get; set; } /// /// 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. /// 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. /// ByteVector Data { get; set; } } /// /// This class implements and provides /// mechanisms for loading pictures from files. /// public class Picture : IPicture { #region Constants /// /// Look-Up-Table associating a file-extension to /// a Mime-Type /// static readonly string[] lutExtensionMime = new[] { "aac", "audio/aac", // AAC audio file "abw", "application/x-abiword", // AbiWord document "arc", "application/octet-stream", // Archive document (multiple files embedded) "avi", "video/x-msvideo", // AVI: Audio Video Interleave "azw", "application/vnd.amazon.ebook", // Amazon Kindle eBook format "bin", "application/octet-stream", // Any kind of binary data "bmp", "image/bmp", // BMP image data "bmp", "image/x-windows-bmp", // BMP image data "bm", "image/bmp", // BMP image data "bz", "application/x-bzip", // BZip archive "bz2", "application/x-bzip2", // BZip2 archive "csh", "application/x-csh", // C-Shell script "css", "text/css", // Cascading Style Sheets (CSS) "csv", "text/csv", // Comma-separated values (CSV) "doc", "application/msword", // Microsoft Word "eot", "application/vnd.ms-fontobject", // MS Embedded OpenType fonts "epub", "application/epub+zip", // Electronic publication (EPUB) "gif", "image/gif", // Graphics Interchange Format (GIF) "htm", "text/html", // HyperText Markup Language (HTML)text / html "html", "text/html", // HyperText Markup Language (HTML)text / html "ico", "image/x-icon", // Icon format "ics", "text/calendar", // iCalendar format "jar", "application/java-archive", // Java Archive (JAR) "jpg", "image/jpeg", // JPEG images "jpeg", "image/jpeg", // JPEG images "js", "application/javascript", // JavaScript (ECMAScript) "json", "application/json", // JSON format "mid", "audio/midi", // Musical Instrument Digital Interface (MIDI) "midi", "audio/midi", // Musical Instrument Digital Interface (MIDI) "mp3", "audio/mpeg", "mp1", "audio/mpeg", "mp2", "audio/mpeg", "mpg", "video/mpeg", "mpeg", "video/mpeg", // MPEG Video "m4a", "audio/mp4", "mp4", "video/mp4", "m4v", "video/mp4", "mpkg", "application/vnd.apple.installer+xml", // Apple Installer Package "odp", "application/vnd.oasis.opendocument.presentation", // OpenDocuemnt presentation document "ods", "application/vnd.oasis.opendocument.spreadsheet", // OpenDocuemnt spreadsheet document "odt", "application/vnd.oasis.opendocument.text", // OpenDocument text document "oga", "audio/ogg", // OGG audio "ogg", "audio/ogg", "ogx", "application/ogg", // OGG "ogv", "video/ogg", "otf", "font/otf", // OpenType font "png", "image/png", // Portable Network Graphics "pdf", "application/pdf", // Adobe Portable Document Format (PDF) "ppt", "application/vnd.ms-powerpoint", // Microsoft PowerPoint "rar", "application/x-rar-compressed", // RAR archive "rtf", "application/rtf", // Rich Text Format (RTF) "sh", "application/x-sh", // Bourne shell script "svg", "image/svg+xml", // Scalable Vector Graphics (SVG) "swf", "application/x-shockwave-flash", // Small web format (SWF) or Adobe Flash document "tar", "application/x-tar", // Tape Archive (TAR) "tif", "image/tiff", // Tagged Image File Format(TIFF) "tiff", "image/tiff", // Tagged Image File Format(TIFF) "ts", "video/vnd.dlna.mpeg-tts", // Typescript file "ttf", "font/ttf", // TrueType Font "vsd", "application/vnd.visio", // Microsoft Visio "wav", "audio/x-wav", // Waveform Audio Format "weba", "audio/webm", // WEBM audio "webm", "video/webm", // WEBM video "webp", "image/webp", // WEBP image "woff", "font/woff", // Web Open Font Format (WOFF) "woff2", "font/woff2", // Web Open Font Format (WOFF) "xhtml", "application/xhtml+xml", // XHTML "xls", "application/vnd.ms", // excel application "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // excel 2007 application "xml", "application/xml", // XML "xul", "application/vnd.mozilla.xul+xml", // XUL "zip", "application/zip", // ZIP archive "3gp", "video/3gpp", // 3GPP audio/video container "3g2", "video/3gpp2", // 3GPP2 audio/video container "7z", "application/x-7z-compressed", // 7-zip archive }; #endregion #region Constructors /// /// Constructs and initializes a new instance of with no data or values. /// public Picture () { } /// /// Constructs and initializes a new instance of by reading in the contents of a /// specified file. /// /// /// A object containing the path of the /// file to read. /// /// /// is . /// public Picture (string path) { if (path == null) throw new ArgumentNullException (nameof (path)); Data = ByteVector.FromPath (path); Filename = System.IO.Path.GetFileName (path); Description = Filename; MimeType = GetMimeFromExtension (Filename); Type = MimeType.StartsWith ("image/") ? PictureType.FrontCover : PictureType.NotAPicture; } /// /// Constructs and initializes a new instance of by reading in the contents of a /// specified file abstraction. /// /// /// A object containing /// abstraction of the file to read. /// /// /// is . /// public Picture (File.IFileAbstraction abstraction) { if (abstraction == null) throw new ArgumentNullException (nameof (abstraction)); Data = ByteVector.FromFile (abstraction); Filename = abstraction.Name; Description = abstraction.Name; if (!string.IsNullOrEmpty (Filename) && Filename.Contains (".")) { MimeType = GetMimeFromExtension (Filename); Type = MimeType.StartsWith ("image/") ? PictureType.FrontCover : PictureType.NotAPicture; } else { string ext = GetExtensionFromData (Data); MimeType = 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 using the contents of a object. /// /// /// A object containing picture data /// to use. /// /// /// is . /// public Picture (ByteVector data) { if (data == null) throw new ArgumentNullException (nameof (data)); Data = new ByteVector (data); string ext = GetExtensionFromData (data); MimeType = 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 . /// /// /// A object containing picture data /// to convert to an Picture. /// public Picture (IPicture picture) { MimeType = picture.MimeType; Type = picture.Type; Filename = picture.Filename; Description = picture.Description; Data = picture.Data; } #endregion #region Legacy Factory methods /// /// Creates a new , populating it with /// the contents of a file. /// /// /// A object containing the path to a /// file to read the picture from. /// /// /// A new object containing the /// contents of the file and with a mime-type guessed from /// the file's contents. /// [Obsolete ("Use Picture(string filename) constructor instead.")] public static Picture CreateFromPath (string filename) { return new Picture (filename); } /// /// Creates a new , populating it with /// the contents of a file. /// /// /// A object containing /// the file abstraction to read the picture from. /// /// /// A new object containing the /// contents of the file and with a mime-type guessed from /// the file's contents. /// [Obsolete ("Use Picture(File.IFileAbstraction abstraction) constructor instead.")] public static Picture CreateFromFile (File.IFileAbstraction abstraction) { return new Picture (abstraction); } #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; set; } /// /// 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; set; } /// /// 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; set; } /// /// 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; set; } #endregion #region Public static Methods (class functions) /// /// Retrieve a mime type from raw file data by reading /// the first few bytes of the file. /// Less accurate than . /// /// /// file name with extension, or just extension of a file /// /// File-extension as , or null if /// not identified public static string GetExtensionFromData (ByteVector data) { string ext = null; // No picture, unless it is corrupted, can fit in a file of less than 4 bytes if (data.Count >= 4) { if (data[1] == 'P' && data[2] == 'N' && data[3] == 'G') { ext = ".png"; } else if (data[0] == 'G' && data[1] == 'I' && data[2] == 'F') { ext = ".gif"; } else if (data[0] == 'B' && data[1] == 'M') { ext = ".bmp"; } else if (data[0] == 0xFF && data[1] == 0xD8 && data[data.Count - 2] == 0xFF && data[data.Count - 1] == 0xD9) { ext = ".jpg"; } } return ext; } /// /// Gets the file-extension that fits a mime-type. /// More accurate than . /// /// /// Mime-type as . /// /// File-extension as , or null if /// not identified public static string GetExtensionFromMime (string mime) { // Default string ext = null; for (int i = 1; i < lutExtensionMime.Length; i += 2) { if (lutExtensionMime[i] == mime) { ext = lutExtensionMime[i - 1]; break; } } return ext; } /// /// Gets the mime type of from a file-name (it's extensions). /// If the format cannot be identified, it assumed to be a Binary file. /// /// /// file name with extension, or just extension of a file /// /// Mime-type as public static string GetMimeFromExtension (string name) { // Default string mime_type = "application/octet-stream"; // Get extension from Filename if (string.IsNullOrEmpty (name)) return mime_type; var ext = System.IO.Path.GetExtension (name); if (string.IsNullOrEmpty (ext)) ext = name; else ext = ext.Substring (1); ext = ext.ToLower (); for (int i = 0; i < lutExtensionMime.Length; i += 2) { if (lutExtensionMime[i] == ext) { mime_type = lutExtensionMime[i + 1]; break; } } return mime_type; } #endregion } }