/// <summary> /// Writes a int value as 2 bytes, but inverted. /// 100 = 64 00 instead of 00 64. /// </summary> /// <param name="value"></param> private void WriteShort(int value) { //Writes the second part first. //The "& 0xff" makes sure that the int will stay on range 0-255, it will cut any number above 255. InternalStream.WriteByte(Convert.ToByte(value & 0xff)); InternalStream.WriteByte(Convert.ToByte((value >> 8) & 0xff)); }
/// <inheritdoc/> public override void WriteByte(byte value) { if (endPosition != -1 && InternalStream.Position >= endPosition) { throw new NotSupportedException("Can't write beyond end of stream."); } InternalStream.WriteByte(value); }
/// <summary> /// Writes the comment for the animation. /// </summary> /// <param name="comment">The comment to write to the gif.</param> private void WriteComment(string comment) { InternalStream.WriteByte(0x21); InternalStream.WriteByte(0xfe); //byte[] length = StringToByteArray(comment.Length.ToString("X")); //foreach (byte b in length) // fs.WriteByte(b); var bytes = System.Text.Encoding.ASCII.GetBytes(comment); InternalStream.WriteByte((byte)bytes.Length); InternalStream.Write(bytes, 0, bytes.Length); InternalStream.WriteByte(0); }
private void WriteByte(int value) { InternalStream.WriteByte(Convert.ToByte(value)); }
internal void AddFrame(string path, Int32Rect rect, int delay = 66) { using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { if (IsFirstFrame) { //Png Header: 8 bytes. InternalStream.WriteBytes(stream.ReadBytes(8)); //IHDR chunk. 13 bytes (Length + Type + CRC, 4 bytes each) = 25 bytes. InternalStream.WriteBytes(stream.ReadBytes(25)); //acTL: Animation control chunk. 8 bytes (Length + Type + CRC, 4 bytes each) = 20 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(8u)); //Length, 4 bytes. InternalStream.WriteBytes(Encoding.ASCII.GetBytes("acTL")); //Chunk type, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)FrameCount)); //NumFrames, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)RepeatCount)); //NumPlays, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - 12, 12)))); //CRC, 4 bytes. } //fcTL: Frame control chunk. 26 bytes (Length + Type + CRC, 4 bytes each) = 38 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(26u)); //Length, 4 bytes. InternalStream.WriteBytes(Encoding.ASCII.GetBytes("fcTL")); //Chunk type, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)SequenceNumber++)); //SequenceNumber, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.Width)); //Width, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.Height)); //Height, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.X)); //OffsetX, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.Y)); //OffsetY, 4 bytes. InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)delay)); //Delay numerator, 2 bytes. InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)1000)); //Delay denominator, 2 bytes. if (IsFirstFrame) { InternalStream.WriteByte((byte)DisposeOps.None); //DisposeOp, 1 byte. InternalStream.WriteByte((byte)BlendOps.Source); //BlendOp, 1 byte. } else { InternalStream.WriteByte((byte)DisposeOps.None); //DisposeOp, 1 byte. InternalStream.WriteByte((byte)BlendOps.Over); //BlendOp, 1 byte. } InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - 30, 30)))); //CRC, 4 bytes. //fdAT: Frame data chunk. 4 + n bytes (Length + Type + CRC, 4 bytes each) = 16 + n bytes, where n is the frame data. var dataList = GetData(stream); foreach (var data in dataList) { if (IsFirstFrame) { InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)data.Length)); //Length, 4 bytes. InternalStream.WriteBytes(Encoding.ASCII.GetBytes("IDAT")); //Chunk type, 4 bytes. InternalStream.WriteBytes(data); //Frame data, n bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - (data.Length + 4), data.Length + 4)))); //CRC, 4 bytes. } else { InternalStream.WriteUInt32(BitHelper.ConvertEndian(4 + (uint)data.Length)); //Length, 4 bytes. InternalStream.WriteBytes(Encoding.ASCII.GetBytes("fdAT")); //Chunk type, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)SequenceNumber++)); //SequenceNumber, 4 bytes. InternalStream.WriteBytes(data); //Frame data, n bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - (data.Length + 8), data.Length + 8)))); //CRC, 4 bytes. } } IsFirstFrame = false; } }
internal void AddFrame(string path, int delay = 66) { using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { if (IsFirstFrame) { IsFirstFrame = false; //Psd Header: XX bytes. InternalStream.WriteBytes(Encoding.ASCII.GetBytes("8BPS")); //Chunk type, 4 bytes. InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)1)); //File version, 1 - PSD, 2 - PSB, 2 bytes. InternalStream.Position += 6; //Must be zero, 6 bytes. InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)3)); //Number of channels, 2 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)Height)); //Height of the image, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)Width)); //Width of the image, 4 bytes. InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)8)); //Number of bits per channel, 2 bytes. InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)3)); //The color mode of the file, 3 - RGB, 2 bytes. //Color mode data. 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(0u)); //The size of the color mode data block, 0 bytes for RGB mode, 4 bytes. //TODO: Write the image resource block to another stream, then merge with the main one. //TODO: Or save the position and update later. //Image resources. XX bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(0u)); //The size of the image resource block, 4 bytes. TODO //InternalStream.WriteBytes(Encoding.ASCII.GetBytes("8BIM")); //Chunk type, 4 bytes. //InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)0x0)); //Image Resource Id, 2 bytes. //InternalStream.WriteBytes(new byte[] { 0, 0 }); //Save the position //Layers and Masks list. XX bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(0u)); //The size of the layer and global mask block, 4 bytes. TODO InternalStream.WriteUInt32(BitHelper.ConvertEndian(0u)); //The size of the layer block, 4 bytes. TODO InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)0)); //The layer count, 2 bytes. TODO } InternalStream.WriteUInt32(BitHelper.ConvertEndian(0u)); //Top, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(0u)); //Left, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)Height)); //Bottom, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)Width)); //Right, 4 bytes. InternalStream.WriteInt16(BitHelper.ConvertEndian((short)4)); //Number of channels, 2 bytes. for (int i = -1; i < 4; i++) { InternalStream.WriteInt16(BitHelper.ConvertEndian((short)i)); //Channel ID, 2 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)0)); //Data lenght of channel, 4 bytes. TODO } InternalStream.WriteBytes(Encoding.ASCII.GetBytes("8BIM")); //Blend mode signature, 4 bytes. InternalStream.WriteInt32(BitHelper.ConvertEndian(0x6e6f726d)); //Blend mode value, Normal, 4 bytes. InternalStream.WriteByte(255); //Opacity, 1 byte. InternalStream.WriteByte(0); //Clipping, 1 byte. InternalStream.WriteByte(10); //Flags, Visible = true, 1 byte. InternalStream.WriteByte(0); //Filler, 1 byte. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)0)); //Extra data lenght, 4 bytes. TODO InternalStream.WriteInt32(BitHelper.ConvertEndian(0)); //Layer mask size, 4 bytes. InternalStream.WriteInt32(BitHelper.ConvertEndian(0)); //Blending ranges size, 4 bytes. TODO: Check if it's possible o have this as zero. var name = $"Frame {0}".Truncate(255); InternalStream.WriteByte((byte)name.Length); //Layer name size, 1 byte. InternalStream.WriteString1252(name); //Layer name size, 1 byte. var padding = 4 - (name.Length + 1) % 4; if (padding != 4) //There's zero padding if equals to 4. { InternalStream.Position += padding; } //For each Aditional Layer Information: //InternalStream.WriteBytes(Encoding.ASCII.GetBytes("8BIM")); //Aditional Layer Information signature, 4 bytes. //InternalStream.WriteBytes(Encoding.ASCII.GetBytes("shmd")); //ALI ID, 4 bytes. var a = new TiffBitmapEncoder { Compression = TiffCompressOption.None }; a.Frames.Add(BitmapFrame.Create(path.SourceFrom())); using (var ms = new MemoryStream()) { a.Save(ms); ImageDataList.Add(ms.ToArray()); } } }
public override void WriteByte(byte value) { InternalStream.WriteByte(value); }