Sylloge
A C# helper library
code/Audio/Metadata/ID3/Frames/AttachedPicture.cs
Go to the documentation of this file.
00001 using System;
00002 using System.Collections.Generic;
00003 using System.Linq;
00004 using System.Text;
00005 
00006 namespace Sylloge.Audio.Metadata.ID3.Frames
00007 {
00008     public class AttachedPicture : TextFrame
00009     {
00013         public byte[] ImageData { get; private set; }
00017         public string MimeType { get; private set; }
00021         public Picture Type { get; private set; }
00022 
00023         public AttachedPicture()
00024             : base(ID3.Frame.Keys.AttachedPicture)
00025         {
00026             this.Initialize(0x00, string.Empty, string.Empty, Picture.Other, null);
00027         }
00028 
00029         public AttachedPicture(System.Drawing.Image img)
00030             : base(ID3.Frame.Keys.AttachedPicture)
00031         {
00032             this.Initialize(img, Picture.Other);
00033         }
00034 
00035         public AttachedPicture(System.Drawing.Image img, Picture type)
00036             : base(ID3.Frame.Keys.AttachedPicture)
00037         {
00038             this.Initialize(img, type);
00039         }
00040 
00041         public AttachedPicture(Frame other)
00042             : base(other)
00043         {
00044             if (other.ID != ID3.Frame.Keys.AttachedPicture) { throw new System.InvalidCastException("Frame ID must be equal to copy the data within it."); }
00045             AttachedPicture i = AttachedPicture.Parse(other);
00046             this.Description = i.Description;
00047             this.Encoding = i.Encoding;
00048             this.ImageData = i.ImageData;
00049             this.MimeType = i.MimeType;
00050             this.Type = i.Type;
00051             this.Value = i.Value;
00052         }
00053 
00054         public AttachedPicture(TextFrame other)
00055             : base(other)
00056         {
00057             if (other.ID != ID3.Frame.Keys.AttachedPicture) { throw new System.InvalidCastException("Frame ID must be equal to copy the data within it."); }
00058             this.ImageData = null;
00059             this.MimeType = string.Empty;
00060             this.Type = Picture.Other;
00061         }
00062 
00063         public AttachedPicture(AttachedPicture other)
00064             : base(other)
00065         {
00066             this.MimeType = other.MimeType;
00067             this.Type = other.Type;
00068             this.ImageData = other.ImageData;
00069         }
00070 
00071         private AttachedPicture(byte enc, string mime, byte pic, string desc, byte[] img)
00072             : base(ID3.Frame.Keys.AttachedPicture)
00073         {
00074             this.Initialize(enc, desc, mime, (Picture)pic, img);
00075         }
00076 
00077         private void Initialize(System.Drawing.Image img, Picture type)
00078         {
00079             this.Initialize(0x00, string.Empty, string.Empty);
00080             this.SetImage(img, type);
00081         }
00082 
00083         private void Initialize(byte enc, string desc, string mtype, Picture ptype, byte[] idata)
00084         {
00085             this.Initialize(enc, desc, string.Empty);
00086             this.MimeType = mtype;
00087             this.Type = ptype;
00088             this.ImageData = idata;
00089             this.GenerateTag();
00090         }
00091 
00092         // TODO: need to set the underlying member values for each "Frame" type
00093 
00099         public override byte[] GenerateTag()
00100         {
00101             /* <Header for 'Attached picture', ID: "APIC"> 
00102             Text encoding   $xx (1 byte)
00103             MIME type       <text string> (upto 0x00)
00104             Picture type    $xx (1 byte)
00105             Description     <text string according to encoding> (upto 0x00)
00106             Picture data    <binary data>
00107             */
00108             List<byte> ret = new List<byte>();
00109             System.Text.Encoding enc = ID3.Helper.GetEncoding(this.Encoding);
00110             ret.Add(this.Encoding);
00111             byte[] mt = ID3.Helper.ISO.GetBytes(this.MimeType);
00112             if (mt != null && mt.Length > 0) { ret.AddRange(mt); }
00113             ret.Add(0x00);
00114             ret.Add((byte)this.Type);
00115             mt = enc.GetBytes(this.Description);
00116             if (mt != null && mt.Length > 0) { ret.AddRange(mt); }
00117             ret.Add(0x00);
00118             if (this.ImageData != null) {
00119                 byte[] idata = this.ImageData;
00120                 if (this.Format.IsCompressed) {
00121                     idata = Frame.Compress(idata);
00122                 }
00123                 if (this.Format.IsEncrypted) {
00124                     idata = Frame.Encrypt(idata, this.Format.Encryption);
00125                 }
00126                 if (this.Format.IsUnsynchronised) {
00127                     idata = Frame.SyncData(idata);
00128                     this.Format.DataLengthInicator = this.ImageData.Length;
00129                 }
00130                 ret.AddRange(idata);
00131             }
00132             this.Data = ret.ToArray();
00133             return this.FullFrame;
00134         }
00135 
00140         public void SetImage(System.Drawing.Image img, Picture type)
00141         {
00142             if (img == null) { throw new System.ArgumentNullException("img"); }
00143             this.MimeType = Sylloge.Data.Imaging.GetMimeType(img);
00144             this.ImageData = Sylloge.Data.Imaging.ToByteArray(img, this.MimeType);
00145             this.Type = type;
00146             this.GenerateTag();
00147         }
00148 
00153         public System.Drawing.Image ToImage()
00154         {
00155             if (this.ImageData == null) { return null; }
00156             System.IO.MemoryStream st = new System.IO.MemoryStream(this.ImageData);
00157             System.Drawing.Image ret = null;
00158             try {
00159                 ret = System.Drawing.Image.FromStream(st);
00160             } catch (Exception) {
00161                 // TODO: this should only happen on an improperly parsed
00162                 // image data (i.e. missed a bit flag or didn't uncompress)
00163                 ret = null;
00164             }
00165             return ret;
00166         }
00167 
00172         public override string ToString()
00173         {
00174             return ((string.IsNullOrEmpty(this.Description)) ? this.MimeType : this.Description);
00175         }
00176 
00177         public static ID3.Frames.AttachedPicture Parse(ID3.Frame frame)
00178         {
00179             if (frame.ID != ID3.Frame.Keys.AttachedPicture) { throw new System.InvalidCastException("Frame ID must be equal to copy the data within it."); }
00180             AttachedPicture ret = new AttachedPicture();// (Image)frame;
00181             ret.Data = frame.Data;
00182             ret.Format = frame.Format;
00183             ret.Status = frame.Status;
00184             ret.Value = string.Empty;
00185             /* <Header for 'Attached picture', ID: "APIC"> 
00186             Text encoding   $xx (1 byte)
00187             MIME type       <text string> (upto 0x00)
00188             Picture type    $xx (1 byte)
00189             Description     <text string according to encoding> (upto 0x00, the terminating null char)
00190             Picture data    <binary data>
00191                         TE (        MIME TYPE       )    PT
00192             <header> 00 69 6D 61 67 65 2F 4A 50 47 00 03 00 <image>*/
00193             List<byte> bdata = new List<byte>(ret.Data);
00194             ret.Encoding = bdata[0]; bdata.RemoveAt(0);
00195             System.Text.Encoding enc = ID3.Helper.GetEncoding(ret.Encoding);
00196             ret.MimeType = ID3.Helper.ISO.GetString(bdata.ToArray());
00197             int idx = 0;
00198             for (; idx < ret.MimeType.Length; idx++) {
00199                 if (ret.MimeType[idx] == '\0') { break; }
00200             }
00201             ret.MimeType = ret.MimeType.Substring(0, idx);
00202             bdata.RemoveRange(0, ret.MimeType.Length + 1);
00203             byte ptype = bdata[0]; bdata.RemoveAt(0); // get picture type
00204             if (!ID3.Helper.CheckPictureType(ptype)) { ptype = Frame.EOL; } // eol for pic type is 'Other'
00205             ret.Type = (Picture)ptype;
00206             ret.Description = string.Empty;
00207             if (bdata[0] != Frame.EOL) {
00208                 ret.Description = enc.GetString(bdata.ToArray());
00209                 for (idx = 0; idx < ret.Description.Length; idx++) {
00210                     if (ret.Description[idx] == '\0') { break; }
00211                 }
00212                 ret.Description = ret.Description.Substring(0, idx);
00213                 int len = enc.GetByteCount(ret.Description);
00214                 if ((len + 1) > bdata.Count) {
00215                     bdata.Clear();
00216                 } else {
00217                     bdata.RemoveRange(0, len + 1);
00218                 }
00219                 if (enc.GetByteCount("A") > 1) {
00220                     // for multi-byte encodings
00221                     bdata.RemoveAt(0);
00222                 }
00223             } else {
00224                 bdata.RemoveAt(0);
00225             }
00226             // get the image byte data
00227             if (ret.Format.HasData) {
00228                 byte[] d = null;
00229                 if (ret.Format.IsUnsynchronised) {
00230                     d = Frame.UnsyncData(bdata.ToArray(), ret.Format.DataLengthInicator);
00231                 }
00232                 if (ret.Format.IsEncrypted) {
00233                     d = Frame.Decrypt(d, ret.Format.Encryption);
00234                 }
00235                 if (ret.Format.IsCompressed) {
00236                     d = Frame.Decompress(d);
00237                 }
00238                 ret.ImageData = d;
00239             } else {
00240                 ret.ImageData = bdata.ToArray();
00241             }
00242             // retun the ID3 image
00243             return ret;
00244         }
00245 
00251         public static ID3.Frames.AttachedPicture Parse(byte[] data)
00252         {
00253             /* <Header for 'Attached picture', ID: "APIC"> 
00254             Text encoding   $xx (1 byte)
00255             MIME type       <text string> (upto 0x00)
00256             Picture type    $xx (1 byte)
00257             Description     <text string according to encoding> (upto 0x00, the terminating null char)
00258             Picture data    <binary data>
00259                         TE (        MIME TYPE       )    PT
00260             <header> 00 69 6D 61 67 65 2F 4A 50 47 00 03 00 <image>*/
00261             List<byte> bdata = new List<byte>(data);
00262             byte benc = bdata[0]; bdata.RemoveAt(0);
00263             System.Text.Encoding enc = ID3.Helper.GetEncoding(benc);
00264             string mtype = ID3.Helper.ISO.GetString(bdata.ToArray());
00265             int idx = 0;
00266             for (; idx < mtype.Length; idx++) { 
00267                 if (mtype[idx] == '\0') { break; }
00268             }
00269             mtype = mtype.Substring(0, idx);
00270             bdata.RemoveRange(0, mtype.Length + 1);
00271             byte ptype = bdata[0]; bdata.RemoveAt(0); // get picture type
00272             if (!ID3.Helper.CheckPictureType(ptype)) { ptype = Frame.EOL; } // eol for pic type is 'Other'
00273             string desc = string.Empty;
00274             if (bdata[0] != Frame.EOL) {
00275                 desc = enc.GetString(bdata.ToArray());
00276                 for (idx = 0; idx < desc.Length; idx++) {
00277                     if (desc[idx] == '\0') { break; }
00278                 }
00279                 desc = desc.Substring(0, idx);
00280                 int len = enc.GetByteCount(desc);
00281                 if ((len + 1) > bdata.Count) {
00282                     bdata.Clear();
00283                 } else {
00284                     bdata.RemoveRange(0, len + 1);
00285                 }
00286             }
00287             bdata.RemoveAt(0);
00288             // get the image byte data
00289             byte[] idata = bdata.ToArray();
00290             // retun the ID3 image
00291             return (new ID3.Frames.AttachedPicture(benc, mtype, ptype, desc, idata));
00292         }
00293 
00300         public static bool TryParse(byte[] data, out ID3.Frames.AttachedPicture img)
00301         {
00302             try {
00303                 img = AttachedPicture.Parse(data);
00304             } catch (Exception) {
00305                 img = null;
00306             }
00307             return false;
00308         }
00309     }
00310 }
 All Classes Namespaces Files Functions Variables Enumerations Properties Events