public static byte[] GetCommandData(this ICommand command) { MemoryStream ms = new MemoryStream(); using (var write = new BigEndianWriter(ms)) { var info = command.GetCommandInfo(); var fields = command.GetFields(); foreach (var field in fields) { if (field.FieldData == null) { continue; } write.Write(field.FieldID); write.Write((Int16)field.FieldData.Length); write.Write(field.FieldData); } if (fields.Any() || info.AlwaysAddEOFField) { write.Write((byte)255); } } var bytes = ms.ToArray(); ms.Dispose(); return(bytes); }
public override void Prepare() { if (Prepared) { return; } Prepared = true; _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); if (FrameCount < 1) { return; } // First frame is [no depends, is depended on, unknown redundancy] ous.Write((byte)0x24); for (int i = 1; i < FrameCount; i++) { // Other frames are [dependent, (reserved), unknown redundancy] --> this is how M$ do it... ous.Write((byte)0x1C); //ous.Write((byte)0x24); } }
/// <summary> /// Create a blank 'trex' for the given track id. /// </summary> /// <param name="TrackId"></param> public trex(int TrackId) : base(0, 0, "trex") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); ous.Write((UInt32)TrackId); // Track ous.Write((UInt32)0); // Default sample description index ous.Write((UInt32)0); // Default sample duration ous.Write((UInt32)0); // Default sample size ous.Write((UInt32)0); // Default sample flags }
public smhd() : base(0, 0, "smhd") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); UInt16 balance = 0x0000; // 8.8 real; 0xFF00 == left, 0x0100 == right. UInt16 reserved = 0; ous.Write(balance); ous.Write(reserved); }
static void WriteBlob(BigEndianWriter writer, byte[] buffer) { writer.Write(buffer.Length); writer.Write(buffer); var zeroPad = buffer.Length % PadLength; if (zeroPad > 0) { var padBytes = new byte[zeroPad]; writer.Write(padBytes); } }
/// <summary> /// Create a new Video media header /// </summary> /// <remarks>The spec says flags should be 1, with no info why.</remarks> public vmhd() : base(0, 0x0001, "vmhd") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); UInt16 graphics_mode = 0; // plain ol' copy. UInt16 op_red = 0; // a bit odd that this is RGB when most video is Y'CrCb... UInt16 op_green = 0; UInt16 op_blue = 0; ous.Write(graphics_mode); ous.Write(op_red); ous.Write(op_green); ous.Write(op_blue); }
public stsd_mp3() : base(0, 0, "stsd") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); ous.Write((UInt32)0); // entry count /* * // This is a WMA block, used to test 'moov' correctness. * byte[] hard_data = new byte[] { * 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, * 0x00, 0x48, 0x6F, 0x77, 0x6D, 0x61, * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, * 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, * 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, * 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, * 0xAC, 0x44, 0x00, 0x00, 0x62, 0x01, * 0x02, 0x00, 0x44, 0xAC, 0x00, 0x00, * 0x45, 0x1F, 0x00, 0x00, 0xCF, 0x05, * 0x10, 0x00, 0x12, 0x00, 0x10, 0x00, * 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, * 0xE0, 0x00, 0x42, 0xC0 * }; * ous.WriteForward(hard_data);*/ }
public mehd() : base(0x01, 0, "mehd") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); ous.Write((UInt64)0); // test value }
/// <summary> /// Creates a stts with no data (empty box) /// </summary> public ctts() : base(0, 0, "ctts") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); ous.Write((UInt32)0); // Entry count }
public stsd_h264() : base(0, 0x0000, "stsd") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); ous.Write((UInt32)0); // entry count /* * // This is a VC-1 block to test 'moov' correctness. * byte[] hard_data = new byte[] { * 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xE5, 0x6F, 0x76, 0x63, * 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, * 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0xD0, 0x00, 0x48, 0x00, 0x00, * 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, * 0x15, 0x56, 0x43, 0x2D, 0x31, 0x20, 0x41, 0x64, 0x76, 0x61, 0x6E, * 0x63, 0x65, 0x64, 0x20, 0x50, 0x72, 0x6F, 0x66, 0x69, 0x6C, 0x65, * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, * 0x05, 0x00, 0x00, 0xD0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, * 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0xD0, 0x02, 0x00, * 0x00, 0xA0, 0x2B, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0x5B, * 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, * 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, * 0x00, 0x00, 0x05, 0x00, 0x00, 0xD0, 0x02, 0x00, 0x00, 0x01, 0x00, * 0x18, 0x00, 0x57, 0x56, 0x43, 0x31, 0x00, 0x30, 0x2A, 0x00, 0x00, * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, * 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x01, 0x0F, 0xD3, 0xBE, * 0x27, 0xF1, 0x67, 0x8A, 0x27, 0xF8, 0x59, 0xE8, 0x04, 0x50, 0x82, * 0x4A, 0x56, 0xDC, 0xEC, 0xC0, 0x00, 0x00, 0x01, 0x0E, 0x5A, 0x67, * 0xF8, 0x40 * }; * ous.WriteForward(hard_data);*/ }
public void FixChannels(string BRSTMPath, int amount) { BinaryReader br = new BinaryReader(File.Open(BRSTMPath, FileMode.Open), Encoding.ASCII); const string Magic = "DATA"; int position = 0; for (int i = 0; i < br.BaseStream.Length; i += 4) { if (new String(br.ReadChars(4)) == Magic) //if we find the magic we can stop and we have our position { position = i + 4; br.Dispose(); br.Close(); break; } } BigEndianReader ber = new BigEndianReader(File.Open(BRSTMPath, FileMode.Open)); ber.BaseStream.Seek(position, SeekOrigin.Begin); uint value = ber.ReadUInt32() + 0x20; ber.Dispose(); ber.Close(); BigEndianWriter bw = new BigEndianWriter(File.Open(BRSTMPath, FileMode.Open)); bw.Seek(position, SeekOrigin.Begin); bw.Write(value); bw.Flush(); bw.Close(); BRSTMPath = '"' + BRSTMPath + '"'; //fix path DecodeBRSTM brstm = new DecodeBRSTM(); brstm.DecodeBRSTMDSP(BRSTMPath, amount); //pass value }
/// <summary> /// Make a defaut header with just track id /// </summary> /// <param name="TrackID"></param> public tfhd(UInt32 TrackID) : base(0x00, /*Flags*/ 0, "tfhd") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); ous.Write(TrackID); }
public static byte[] ToByteArray(this ICommand command) { MemoryStream ms = new MemoryStream(); using (var write = new BigEndianWriter(ms)) { var info = command.GetCommandInfo(); write.Write((byte)1); write.Write(info.Header.ToCharArray()); if (command.GetType().GetInterface(nameof(ICommandSequence)) != null) { write.Write((command as ICommandSequence).CommandSequence); } write.Write(info.CommandID); var data = command.GetCommandData(); write.Write((Int32)data.Length); write.Write(data); write.Write((byte)13); } var bytes = ms.ToArray(); ms.Dispose(); return(bytes); }
/// <summary> /// Create a new header box /// </summary> public mfhd(UInt32 SequenceNumber) : base(0, 0, "mfhd") { // I think this box is a total waste of up to 24 bytes. _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); ous.Write(SequenceNumber); // that's it. Done... }
public override void Prepare() { // build the base '_data' item. // done here to be as late as possible. _data = new MemoryStream(); BigEndianWriter d = new BigEndianWriter(_data); d.Write((UInt32)_frames.Count); // required field // frame positions and sizes foreach (var frame in _frames) { d.Write((UInt32)frame.FrameDuration); // This is in .Net ticks (100ns) d.Write((UInt32)frame.FrameData.Length); //d.Write((UInt32)frame.FramePresentationTime); // This is in .Net ticks (100ns) } }
//////////////// public static void ToStream(string src, Stream destStream) { var zipStream = new GZipStream(destStream, CompressionMode.Compress, true); var destWriter = new BigEndianWriter(zipStream); destWriter.Write(src); zipStream.Close(); }
public void SendPacket(Action <BigEndianWriter> writePacket) { byte[] buffer; using (var memoryStream = new MemoryStream()) using (var writer = new BigEndianWriter(memoryStream)) { writePacket(writer); buffer = memoryStream.ToArray(); } lock (stream) { using (var writer = new BigEndianWriter(stream, true)) { writer.Write(buffer.Length); writer.Write(buffer); } } }
/// <summary> /// Create a new timing box. /// </summary> /// <param name="Offset">Start timecode of this fragment (sum of previous 'FragmentTicks')</param> /// <param name="FragmentTicks">Total number of .Net ticks of the fragment</param> public SmoothFragmentTimer(long Offset, long FragmentTicks):base("uuid") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); // This is the GUID for the timing box. Taken directly from network captures ous.WriteForward(new byte[] { 0x6D, 0x1D, 0x9B, 0x05, 0x42, 0xD5, 0x44, 0xE6, 0x80, 0xE2, 0x14, 0x1D, 0xAF, 0xF7, 0x57, 0xB2 // 16 bytes of 'type' }); // Don't know what this is, but it's always this data when I've seen it. Maybe flags&version? ous.WriteForward(new byte[] { 0x01, 0x00, 0x00, 0x00 }); // This relates to the 't' field of the 'c' element in .ism files. ous.Write((UInt64)Offset); // This is presentation offset. // This relates to the 'd' field of the 'c' element in .ism files. ous.Write((UInt64)FragmentTicks); // This is the fragment duration. }
/// <summary> /// Create a new ftyp box, assuming isom / iso2 compatibiliy /// </summary> public ftyp() : base("ftyp") { // Write out a string of FOURCC values. // There are: // 'Major Brand' = "avc1" // 'minor version' = 0 // 'compatible brands' = {"isom", "iso2"} UInt32 major_brand = Box.FourCC("avc1"); UInt32 minor_version = 0U; UInt32 cb_brand_1 = Box.FourCC("isom"); UInt32 cb_brand_2 = Box.FourCC("iso2"); _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); ous.Write(major_brand); ous.Write(minor_version); ous.Write(cb_brand_1); ous.Write(cb_brand_2); }
public hdlr(int Width, int Height) : base(0, 0, "hdlr") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); ous.Write((UInt32)0); // 'pre_defined', which seems to be the same as 'reserved' UInt32 handler_type = 0; int pixels = Width * Height; if (pixels > 0) { handler_type = Box.FourCC("vide"); } else { handler_type = Box.FourCC("soun"); } ous.Write(handler_type); ous.Write((UInt32)0); // a few more reserved fields... ous.Write((UInt32)0); // ... ous.Write((UInt32)0); // ..! ous.Write((UInt32)0); // Null-terminated user readable string. Seems only good for copyrights and secret messages. }
public void WriteTest() { List<byte> m = new List<byte>(); MemoryStream ms = new MemoryStream(); using (BigEndianWriter w = new BigEndianWriter(ms)) { w.Write((int)0x12345678); m.Add(0x12); m.Add(0x34); m.Add(0x56); m.Add(0x78); w.Write((short)0x2345); m.Add(0x23); m.Add(0x45); w.WriteBCD(12345678,4); m.Add(0x12); m.Add(0x34); m.Add(0x56); m.Add(0x78); } Assert.AreEqual(m.ToArray(), ms.ToArray()); }
static void WriteMessage(BigEndianWriter writer, Message message) { var offset = message.Address.Length + 1; var excess = offset % PadLength; if (excess != 0) { offset += PadLength - excess; } var array = message.Buffer.Array; var count = message.Buffer.Count - offset; writer.Write(array, offset, count); }
public static byte[] EncodeVarBindList(List <Variable> VarBindList) { MemoryStream stream = new MemoryStream(); using (var write = new BigEndianWriter(stream)) { foreach (var vb in VarBindList) { var bytes = EncodeVarBind(vb); write.Write((byte)1); write.Write((Int16)bytes.Length); write.Write(bytes); } write.Write((byte)255); } var data = stream.ToArray(); stream.Dispose(); return(data); }
/// <summary> /// Output the header data for this Box. /// Override this to add extra data if your sub-class adds extra fields /// </summary> /// <returns></returns> protected virtual byte[] selfData() { ulong size = deepSize(); MemoryStream ms = new MemoryStream(); BigEndianWriter ous = new BigEndianWriter(ms); if (size >= UInt32.MaxValue) { ous.Write((UInt32)1U); ous.Write((UInt32)_fourCC); ous.Write((UInt64)size); } else { ous.Write((UInt32)size); ous.Write((UInt32)_fourCC); } if (_flags != null) { ous.WriteForward(_flags); } return(ms.ToArray()); }
/// <summary> /// Create a new SMIL container box. Please supply your own SMIL file. /// </summary> public SmoothSmil(byte[] SmilFile) : base("uuid") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); // I have no idea what this GUID relates to or what it means. // I took this value from a socket capture. Many Bothans died to bring us this information. //Guid uuid_head = new Guid("A5 D4 0B 30 E8 14 11 DD BA 2F 08 00 20 0C 9A 66"); ous.WriteForward(new byte[] { 0xA5, 0xD4, 0x0B, 0x30, 0xE8, 0x14, 0x11, 0xDD, 0xBA, 0x2F, 0x08, 0x00, 0x20, 0x0C, 0x9A, 0x66 }); UInt32 blank = 0U; ous.Write(blank); ous.WriteForward(SmilFile); }
public mdhd() : base(1, 0, "mdhd") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); // Version = 1 means a few 64-bit values: UInt64 creation_time = Box.BoxDate(DateTime.Now); UInt64 modified_time = creation_time; UInt32 timescale = 10000000; // This is the .Net value. Normal MPEG might need 900000; UInt64 duration = 0; // This is unknown for live, and currently unused by Silverlight. ous.Write(creation_time); ous.Write(modified_time); ous.Write(timescale); ous.Write(duration); UInt16 language = 0x55C4; // this is both the 1 bit pad and the 5 bit x 3 char code for 'und'; ous.Write(language); ous.Write((UInt16)0); // Why have 'language' so crushed, and yet have this waste? }
public static byte[] EncodeVarBind(Variable vb) { var stream = new MemoryStream(); using (var write = new BigEndianWriter(stream)) { var idNums = vb.Id.ToNumerical(); write.Write((byte)FieldType.OID); write.Write((Int16)(idNums.Length * sizeof(Int32))); foreach (var part in idNums) { write.Write((Int32)part); } write.Write((byte)vb.Data.TypeCode); switch ((FieldType)vb.Data.TypeCode) { default: write.Write((Int16)0); break; case FieldType.Int32: write.Write((Int16)sizeof(Int32)); write.Write((Int32)(vb.Data as Integer32).ToInt32()); break; case FieldType.String: write.Write((Int16)(vb.Data as OctetString).ToBytes().Length); write.Write((vb.Data as OctetString).ToBytes()); break; case FieldType.OID: write.Write((Int16)((vb.Data as ObjectIdentifier).ToNumerical().Length *sizeof(Int32))); foreach (var part in (vb.Data as ObjectIdentifier).ToNumerical()) { write.Write((Int32)part); } break; case FieldType.IPAddress: write.Write((Int16)(vb.Data as IP).GetRaw().Length); write.Write((vb.Data as IP).GetRaw()); break; case FieldType.Counter32: write.Write((Int16)sizeof(Int32)); write.Write((Int32)(vb.Data as Counter32).ToUInt32()); break; case FieldType.Gauge32: write.Write((Int16)sizeof(Int32)); write.Write((Int32)(vb.Data as Gauge32).ToUInt32()); break; case FieldType.TimeTicks: write.Write((Int16)sizeof(Int32)); write.Write((Int32)(vb.Data as TimeTicks).ToUInt32()); break; } } var buf = stream.ToArray(); stream.Dispose(); return(buf); }
private void DoWriteWoffToTTF(MemoryStream ms) { var dirs = this.Directories.ToArray(); BigEndianWriter writer = new BigEndianWriter(ms); writer.Write(TypefaceVersionReader.TrueTypeHeaderBytes); writer.WriteUInt16((ushort)dirs.Length); var checkOffset = ms.Position; ushort max2 = 2; while (max2 * 2 <= this.Directories.Count) { max2 *= 2; } ushort search = (ushort)(max2 * 16); ushort entry = (ushort)Math.Log(max2, 2); ushort range = (ushort)((dirs.Length * 16) - search); writer.WriteUInt16(search); writer.WriteUInt16(entry); writer.WriteUInt16(range); var offset = writer.Position; var dirOffsets = new long[dirs.Length]; var tableOffsets = new long[dirs.Length]; for (int i = 0; i < dirs.Length; i++) { var dir = dirs[i] as WoffTableEntry; if (dir.DecompressedData == null) { throw new InvalidOperationException("The directrory " + dir.Tag + " does not have any decompressed data"); } writer.WriteASCIIChars(dir.Tag); writer.WriteUInt32(dir.CheckSum); //Write zero as the offset initially and then we will come back and update dirOffsets[i] = writer.Position; writer.WriteUInt32(0); writer.WriteUInt32(dir.Length); } for (var i = 0; i < dirs.Length; i++) { var dir = dirs[i] as WoffTableEntry; //pad to 4 bytes while (writer.Position % 4 != 0) { writer.WriteByte(Zero); } //remember the position and write the decompressed data tableOffsets[i] = writer.Position; writer.Write(dir.DecompressedData); } //Now go back and update the positions for (int i = 0; i < dirs.Length; i++) { writer.Position = dirOffsets[i]; writer.WriteUInt32((uint)tableOffsets[i]); } }
void Write(byte value) { _writer.Write(value); }
/// <summary> /// Create a new track header /// </summary> public tkhd(int Width, int Height, int TrackId) : base(0x01, 0x0007, "tkhd") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); // Version = 1 means a few 64-bit values: UInt64 creation_time = Box.BoxDate(DateTime.Now); UInt64 modified_time = creation_time; UInt32 track_id = (UInt32)TrackId; UInt32 reserved_1 = 0; UInt64 duration = 0; // This is unknown for live, and currently unused by Silverlight. UInt64 reserved_2 = 0; // spec has this as UInt32[2] ous.Write(creation_time); ous.Write(modified_time); ous.Write(track_id); ous.Write(reserved_1); ous.Write(duration); ous.Write(reserved_2); // These all seem pointless: Int16 layer = 0; Int16 alternate_group = 0; int pixels = Width * Height; Int16 volume = (pixels > 0) ? ((Int16)0x0000) : ((Int16)0x0100); // spec says this should be 0 for video, 0x0100 for audio. Int16 reserved_3 = 0; ous.Write(layer); ous.Write(alternate_group); ous.Write(volume); ous.Write(reserved_3); // Unity matrix: (a waste of 36 bytes that was already wasted in mvhd) ous.Write((Int32)0x00010000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x00010000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x40000000); UInt32 fx_width = (UInt32)((Width & 0xFFFF) << 16); UInt32 fx_height = (UInt32)((Height & 0xFFFF) << 16); ous.Write(fx_width); ous.Write(fx_height); }
public mvhd() : base(0x01, 0, "mvhd") { _data = new System.IO.MemoryStream(); BigEndianWriter ous = new BigEndianWriter(_data); // Version = 1 means a few 64-bit values: UInt64 creation_time = Box.BoxDate(DateTime.Now); UInt64 modified_time = creation_time; UInt32 timescale = 10000000; // I think Silverlight ignores this. UInt64 duration = 0; // This is unknown for live, and currently unused by Silverlight. ous.Write(creation_time); ous.Write(modified_time); ous.Write(timescale); ous.Write(duration); // These are all constants for now: Int32 DisplayRate = 0x00010000; // Fixed point value = 1.0f -> normal playback, forward. Int16 Volume = 0x0100; // 100% volume Int16 Reserved_1 = 0; UInt64 Reserved_2 = 0; // spec has this as Int32[2]. ous.Write(DisplayRate); ous.Write(Volume); ous.Write(Reserved_1); ous.Write(Reserved_2); // Unity matrix: (another waste of 36 bytes) ous.Write((Int32)0x00010000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x00010000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x00000000); ous.Write((Int32)0x40000000); // Big chunk of zeros for no know reason: for (int i = 0; i < 6; i++) { ous.Write((Int32)0x00000000); // why have both version numbers *AND* reserved values? } // Weird value: "next_track_id"; // This is meant to be the next, non-zero id that isn't currently used in the file. // Thankfully if we set it to 0xFFFFFFFF, it signals that a search should be used. ous.Write((UInt32)0xFFFFFFFFu); }
public static byte[] ExtractTTFfromTTC(System.IO.Stream ttc, int ttfHeadOffset) { using (System.IO.MemoryStream ttf = new System.IO.MemoryStream()) { BigEndianReader reader = new BigEndianReader(ttc); reader.Position = ttfHeadOffset; TrueTypeHeader header; if (TrueTypeHeader.TryReadHeader(reader, out header) == false) { throw new NotSupportedException("The current stream is not a supported OpenType or TrueType font file"); } List <TrueTypeTableEntry> dirs; try { dirs = new List <TrueTypeTableEntry>(); for (int i = 0; i < header.NumberOfTables; i++) { TrueTypeTableEntry dir = new TrueTypeTableEntry(); dir.Read(reader); dirs.Add(dir); } } catch (TypefaceReadException) { throw; } catch (Exception ex) { throw new TypefaceReadException("Could not read the TTF File", ex); } BigEndianWriter writer = new BigEndianWriter(ttf); writer.Write(header.Version.HeaderData); writer.WriteUInt16((ushort)header.NumberOfTables); writer.WriteUInt16((ushort)header.SearchRange); writer.WriteUInt16((ushort)header.EntrySelector); writer.WriteUInt16((ushort)header.RangeShift); long[] dirOffsets = new long[dirs.Count]; //Set to the byte position of the Offset32 in the header to point to the table long[] tableOffsets = new long[dirs.Count]; //Set to the byte position of the table in the file for (var i = 0; i < dirs.Count; i++) { var dir = dirs[i]; writer.WriteASCIIChars(dir.Tag); writer.WriteUInt32(dir.CheckSum); //Write zero as the offset initially and then we will come back and update dirOffsets[i] = writer.Position; writer.WriteUInt32(0); writer.WriteUInt32(dir.Length); } for (var i = 0; i < dirs.Count; i++) { var dir = dirs[i]; while (writer.Position % 4 != 0) { writer.WriteByte(Zero); } //Remember the start position of the table tableOffsets[i] = writer.Position; reader.Position = dir.Offset; //we can improve this var data = reader.Read((int)dir.Length); writer.Write(data); } for (int i = 0; i < dirs.Count; i++) { writer.Position = dirOffsets[i]; writer.WriteUInt32((uint)tableOffsets[i]); } writer.Position = 0; var fileData = ttf.ToArray(); return(fileData); } }