//
// 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
}
}