public void ReadPicture(Stream s, ReadTagParams readTagParams) { int picturePosition; long initPosition = s.Position; VorbisMetaDataBlockPicture block = ReadMetadataBlockPicture(s); if (block.picType.Equals(PictureInfo.PIC_TYPE.Unsupported)) { addPictureToken(getImplementedTagType(), (byte)block.nativePicCode); picturePosition = takePicturePosition(getImplementedTagType(), (byte)block.nativePicCode); } else { addPictureToken(block.picType); picturePosition = takePicturePosition(block.picType); } if (readTagParams.ReadPictures || readTagParams.PictureStreamHandler != null) { PictureInfo picInfo = new PictureInfo(ImageUtils.GetImageFormatFromMimeType(block.mimeType), block.picType, getImplementedTagType(), block.nativePicCode, picturePosition); picInfo.Description = block.description; picInfo.PictureData = new byte[block.picDataLength]; s.Seek(initPosition + block.picDataOffset, SeekOrigin.Begin); s.Read(picInfo.PictureData, 0, block.picDataLength); tagData.Pictures.Add(picInfo); if (!tagExists) { tagExists = true; } if (readTagParams.PictureStreamHandler != null) { MemoryStream mem = new MemoryStream(picInfo.PictureData); readTagParams.PictureStreamHandler(ref mem, picInfo.PicType, picInfo.NativeFormat, picInfo.TagType, picInfo.NativePicCode, picInfo.Position); mem.Close(); } } }
// Reads large data chunks by streaming private void SetExtendedTagItem(Stream Source, int size, ReadTagParams readTagParams) { const int KEY_BUFFER = 20; string tagId = ""; byte[] stringData = new byte[KEY_BUFFER]; int equalsIndex = -1; while (-1 == equalsIndex) { Source.Read(stringData, 0, KEY_BUFFER); for (int i = 0; i < KEY_BUFFER; i++) { if (stringData[i] == 0x3D) // '=' character { equalsIndex = i; break; } } tagId += Utils.Latin1Encoding.GetString(stringData, 0, (-1 == equalsIndex) ? KEY_BUFFER : equalsIndex); } Source.Seek(-(KEY_BUFFER - equalsIndex - 1), SeekOrigin.Current); if (tagId.Equals(PICTURE_METADATA_ID_NEW)) { size = size - 1 - PICTURE_METADATA_ID_NEW.Length; // Make sure total size is a multiple of 4 size = size - (size % 4); // Read the whole base64-encoded picture header _and_ binary data byte[] encodedData = new byte[size]; Source.Read(encodedData, 0, size); // Gets rid of unwanted zeroes // 0x3D ('=' char) is the padding neutral character that has to replace zero, which is not part of base64 range for (int i = 0; i < encodedData.Length; i++) { if (0 == encodedData[i]) { encodedData[i] = 0x3D; } } using (MemoryStream mem = new MemoryStream(Utils.DecodeFrom64(encodedData))) { mem.Seek(0, SeekOrigin.Begin); ReadPicture(mem, readTagParams); } } else if (tagId.Equals(PICTURE_METADATA_ID_OLD)) // Deprecated picture info { int picturePosition = takePicturePosition(PictureInfo.PIC_TYPE.Generic); PictureInfo picInfo = new PictureInfo(ImageFormat.Undefined, PictureInfo.PIC_TYPE.Generic, getImplementedTagType(), 0, picturePosition); if (readTagParams.ReadPictures || readTagParams.PictureStreamHandler != null) { size = size - 1 - PICTURE_METADATA_ID_OLD.Length; // Make sure total size is a multiple of 4 size = size - (size % 4); byte[] encodedData = new byte[size]; Source.Read(encodedData, 0, size); // Read the whole base64-encoded picture binary data picInfo.PictureData = Utils.DecodeFrom64(encodedData); ImageFormat imgFormat = ImageUtils.GetImageFormatFromPictureHeader(picInfo.PictureData); if (ImageFormat.Unsupported == imgFormat) { imgFormat = ImageFormat.Png; } picInfo.NativeFormat = imgFormat; tagData.Pictures.Add(picInfo); if (readTagParams.PictureStreamHandler != null) { MemoryStream mem = new MemoryStream(picInfo.PictureData); readTagParams.PictureStreamHandler(ref mem, picInfo.PicType, picInfo.NativeFormat, picInfo.TagType, picInfo.NativePicCode, picInfo.Position); mem.Close(); } } } }
public void readTagField(BinaryReader source, string zoneCode, string fieldName, ushort fieldDataType, int fieldDataSize, ReadTagParams readTagParams, bool isExtendedHeader = false, ushort languageIndex = 0, ushort streamNumber = 0) { string fieldValue = ""; bool setMeta = true; addFrameClass(fieldName, fieldDataType); if (0 == fieldDataType) // Unicode string { fieldValue = Utils.StripEndingZeroChars(Encoding.Unicode.GetString(source.ReadBytes(fieldDataSize))); } else if (1 == fieldDataType) // Byte array { if (fieldName.ToUpper().Equals("WM/PICTURE")) { byte picCode = source.ReadByte(); // TODO factorize : abstract PictureTypeDecoder + unsupported / supported decision in MetaDataIO ? PictureInfo.PIC_TYPE picType = ID3v2.DecodeID3v2PictureType(picCode); int picturePosition; if (picType.Equals(PictureInfo.PIC_TYPE.Unsupported)) { addPictureToken(MetaDataIOFactory.TAG_NATIVE, picCode); picturePosition = takePicturePosition(MetaDataIOFactory.TAG_NATIVE, picCode); } else { addPictureToken(picType); picturePosition = takePicturePosition(picType); } if (readTagParams.ReadPictures || readTagParams.PictureStreamHandler != null) { int picSize = source.ReadInt32(); string mimeType = StreamUtils.ReadNullTerminatedString(source, Encoding.Unicode); string description = StreamUtils.ReadNullTerminatedString(source, Encoding.Unicode); PictureInfo picInfo = new PictureInfo(ImageUtils.GetImageFormatFromMimeType(mimeType), picType, getImplementedTagType(), picCode, picturePosition); picInfo.Description = description; picInfo.PictureData = new byte[picSize]; source.BaseStream.Read(picInfo.PictureData, 0, picSize); tagData.Pictures.Add(picInfo); if (readTagParams.PictureStreamHandler != null) { MemoryStream mem = new MemoryStream(picInfo.PictureData); readTagParams.PictureStreamHandler(ref mem, picInfo.PicType, picInfo.NativeFormat, picInfo.TagType, picInfo.NativePicCode, picInfo.Position); mem.Close(); } } setMeta = false; } else { source.BaseStream.Seek(fieldDataSize, SeekOrigin.Current); } } else if (2 == fieldDataType) // 16-bit Boolean (metadata); 32-bit Boolean (extended header) { if (isExtendedHeader) { fieldValue = source.ReadUInt32().ToString(); } else { fieldValue = source.ReadUInt16().ToString(); } } else if (3 == fieldDataType) // 32-bit unsigned integer { uint intValue = source.ReadUInt32(); if (fieldName.Equals("WM/GENRE", StringComparison.OrdinalIgnoreCase)) { intValue++; } fieldValue = intValue.ToString(); } else if (4 == fieldDataType) // 64-bit unsigned integer { fieldValue = source.ReadUInt64().ToString(); } else if (5 == fieldDataType) // 16-bit unsigned integer { fieldValue = source.ReadUInt16().ToString(); } else if (6 == fieldDataType) // 128-bit GUID; unused for now { source.BaseStream.Seek(fieldDataSize, SeekOrigin.Current); } if (setMeta) { SetMetaField(fieldName.Trim(), fieldValue, readTagParams.ReadAllMetaFrames, zoneCode, 0, streamNumber, decodeLanguage(source.BaseStream, languageIndex)); } }