//0 xxxxxxx // val 0 - 127 // 8 bits //10 xxxxxxxx // val 128 - 383 // 10 bits //11 xxxxxxxx0 // val 384 - 639 // 11 bits //11 xxxxxxxx1 xxxx0 // val 384 - 4479 // 16 bits //11 xxxxxxxx1 xxxx1 xxxx0 // 384 - 65919 // 21 bits //11 xxxxxxxx1 xxxx1 xxxx1 xxxx1 xxxx1 xxxx1 xxxx1 xxxx1 xxxx1 xxxx1 xxxx1 xxxx1 xxxx1 xxxx1 xxxx0 // 81 bits worst case public static void WriteDynamicLength(BitStreamWriter aWriter, ulong aValue) { if (aValue < 128) { aWriter.WriteBit(0); aWriter.WriteBits(aValue, 7); } else if (aValue < 384) { aWriter.WriteBit(1); aWriter.WriteBit(0); aWriter.WriteBits(aValue - 128UL, 8); } else { aValue -= 384UL; aWriter.WriteBit(1); aWriter.WriteBit(1); aWriter.WriteBits(aValue, 8); aValue >>= 8; while (aValue > 0) { aWriter.WriteBit(1); aWriter.WriteBits(aValue, 4); aValue >>= 4; } aWriter.WriteBit(0); } }
public static void ChangeDemoDir(SourceDemo demo, Stream s, string newDir) { void Write(byte[] buf) => s.Write(buf, 0, buf.Length); string old = demo.Header.GameDirectory; if (old == newDir) { // no difference Write(demo.Reader.Data); return; } int lenDiff = newDir.Length - old.Length; BitStreamReader bsr = demo.Reader; byte[] dirBytes = Encoding.ASCII.GetBytes(newDir); Write(bsr.ReadBytes(796)); Write(dirBytes); // header doesn't matter but I change it anyway Write(new byte[260 - newDir.Length]); bsr.SkipBytes(260); Write(bsr.ReadBytes(12)); byte[] tmp = BitConverter.GetBytes((uint)(bsr.ReadUInt() + lenDiff)); if (!BitConverter.IsLittleEndian) { tmp = tmp.Reverse().ToArray(); } Write(tmp); foreach (SignOn signOn in demo.FilterForPacket <SignOn>().Where(signOn => signOn.FilterForMessage <SvcServerInfo>().Any())) { // catch up to signOn packet int byteCount = (signOn.Reader.AbsoluteBitIndex - bsr.AbsoluteBitIndex) / 8; Write(bsr.ReadBytes(byteCount)); bsr.SkipBits(signOn.Reader.BitLength); BitStreamWriter bsw = new BitStreamWriter(); BitStreamReader signOnReader = signOn.Reader; bsw.WriteBits(signOnReader.ReadRemainingBits()); signOnReader = signOnReader.FromBeginning(); int bytesToMessageStreamSize = demo.DemoInfo.MaxSplitscreenPlayers * 76 + 8; signOnReader.SkipBytes(bytesToMessageStreamSize); // edit the message stream length - read uint, and edit at index before the reading of said uint bsw.EditIntAtIndex((int)(signOnReader.ReadUInt() + lenDiff), signOnReader.CurrentBitIndex - 32, 32); // actually change the game dir SvcServerInfo serverInfo = signOn.FilterForMessage <SvcServerInfo>().Single(); int editIndex = serverInfo.GameDirBitIndex - signOn.Reader.AbsoluteBitIndex; bsw.RemoveBitsAtIndex(editIndex, old.Length * 8); bsw.InsertBitsAtIndex(dirBytes, editIndex, newDir.Length * 8); Write(bsw.AsArray); } Write(bsr.ReadRemainingBits().bytes); }
// writes a edited version of the given demo to the stream // this is all manually hacked together and it shall stay this way for now public static void RemoveCaptions(SourceDemo demo, Stream s) { void Write(byte[] buf) => s.Write(buf, 0, buf.Length); Packet[] closeCaptionPackets = demo.FilterForPacket <Packet>() .Where(packet => packet.FilterForMessage <SvcUserMessage>() .Any(frame => frame.MessageType == UserMessageType.CloseCaption)).ToArray(); if (closeCaptionPackets.Length == 0) { Write(demo.Reader.Data); return; } int changedPackets = 0; Write(demo.Header.Reader.ReadRemainingBits().bytes); foreach (PacketFrame frame in demo.Frames) { if (frame.Packet != closeCaptionPackets[changedPackets]) { Write(frame.Reader.ReadRemainingBits().bytes); // write frames that aren't changed } else { Packet p = (Packet)frame.Packet; BitStreamWriter bsw = new BitStreamWriter(frame.Reader.BitLength / 8); var last = p.MessageStream.Last().message; int len = last.Reader.AbsoluteStart - frame.Reader.AbsoluteStart + last.Reader.BitLength; bsw.WriteBits(frame.Reader.ReadBits(len), len); int msgSizeOffset = p.MessageStream.Reader.AbsoluteStart - frame.Reader.AbsoluteStart; int typeInfoLen = demo.DemoInfo.NetMsgTypeBits + demo.DemoInfo.UserMessageLengthBits + 8; bsw.RemoveBitsAtIndices(p.FilterForUserMessage <CloseCaption>() .Select(caption => (caption.Reader.AbsoluteStart - frame.Reader.AbsoluteStart - typeInfoLen, caption.Reader.BitLength + typeInfoLen))); bsw.WriteUntilByteBoundary(); bsw.EditIntAtIndex((bsw.BitLength - msgSizeOffset - 32) >> 3, msgSizeOffset, 32); Write(bsw.AsArray); // if we've edited all the packets, write the rest of the data in the demo if (++changedPackets == closeCaptionPackets.Length) { BitStreamReader tmp = demo.Reader; tmp.SkipBits(frame.Reader.AbsoluteStart + frame.Reader.BitLength); Write(tmp.ReadRemainingBits().bytes); break; } } } }
public void WriteBits() { var random = new Random(0); for (int i = 0; i < Iterations; i++) { int skip = i % 16; BitStreamWriter bsw = new BitStreamWriter(); bsw.WriteBitsFromSInt(random.Next(), skip); int bitLen = random.Next(1, 100); byte[] rand = new byte[(bitLen >> 3) + ((bitLen & 0x07) == 0 ? 0 : 1)]; random.NextBytes(rand); bsw.WriteBits(rand, bitLen); if ((bitLen & 0x07) != 0) { rand[^ 1] &= (byte)(0xff >> (8 - (bitLen & 0x07))); // get rid of unused bits
public static byte[] Encode(byte[] aData) { using (MemoryStream data = new MemoryStream()) { BitStreamWriter writer = new BitStreamWriter(data); var leaves = Analyze(aData); var tree = GenerateTree(leaves); tree.Serialize(writer); WriteDynamicLength(writer, (ulong)aData.LongLength); var lookup = GenerateLookup(leaves); for (int i = 0; i < aData.Length; i++) { var n = lookup[aData[i]]; writer.WriteBits(n.bitPattern, n.bitCount); } writer.Flush(); return(data.ToArray()); } }
public void SkipBits() { var random = new Random(0); BitStreamWriter bsw = new BitStreamWriter(); List <(int skipCount, uint val)> data = new List <(int skipCount, uint val)>(); byte[] randArr = new byte[100 / 8 + 1]; random.NextBytes(randArr); for (int _ = 0; _ < Iterations; _++) { (int skip, uint val)r = (random.Next(0, 100), (uint)random.Next()); data.Add(r); bsw.WriteBits(randArr, r.skip); bsw.WriteUInt(r.val); } BitStreamReader bsr = new BitStreamReader(bsw); for (int i = 0; i < Iterations; i++) { bsr.SkipBits(data[i].skipCount); Assert.AreEqual(data[i].val, bsr.ReadUInt(), $"index: {i}"); } }
/// <summary> /// Decodes a single pixel row. /// </summary> public byte[] DecodeRow(byte[] data) { m_Reset(CCITT4DecoderState.White); var reader = new BitStreamReaderReverse(new MemoryStream(data)); var writer = new BitStreamWriter(new MemoryStream()); while (reader.Position < reader.Length) { // read a bit m_CurrentValue = (m_CurrentValue << 1) | reader.ReadBit(); m_CurrentBitLength++; if (m_CurrentBitLength > 13) { throw new FormatException(); } // did we get a EndOfLine code ? if ((m_CurrentBitLength == EOL[1]) && (m_CurrentValue == EOL[0])) { m_Reset(0); continue; } if (m_State == 0) { // white makeup search for (int i = 0; i < WhiteMakeUpCodes.GetLength(0); i++) { if ((WhiteMakeUpCodes[i, 1] == m_CurrentBitLength) && (WhiteMakeUpCodes[i, 0] == m_CurrentValue)) { writer.WriteBits(WhiteMakeUpCodes[i, 2], true); m_Reset(CCITT4DecoderState.WhiteTerminationRequired); break; } } if (m_State != 0) { continue; } } if ((int)m_State <= 1) { // white termination search for (int i = 0; i < WhiteTerminatingCodes.GetLength(0); i++) { if ((WhiteTerminatingCodes[i, 1] == m_CurrentBitLength) && (WhiteTerminatingCodes[i, 0] == m_CurrentValue)) { writer.WriteBits(i, true); m_Reset(CCITT4DecoderState.Black); break; } } if ((int)m_State != 1) { continue; } } if ((int)m_State == 2) { // black makeup search for (int i = 0; i < BlackMakeUpCodes.GetLength(0); i++) { if ((BlackMakeUpCodes[i, 1] == m_CurrentBitLength) && (BlackMakeUpCodes[i, 0] == m_CurrentValue)) { writer.WriteBits(BlackMakeUpCodes[i, 2], false); m_Reset(CCITT4DecoderState.BlackTerminationRequired); break; } } if ((int)m_State != 2) { continue; } } if ((int)m_State >= 2) { // black termination search for (int i = 0; i < BlackTerminatingCodes.GetLength(0); i++) { if ((BlackTerminatingCodes[i, 1] == m_CurrentBitLength) && (BlackTerminatingCodes[i, 0] == m_CurrentValue)) { writer.WriteBits(i, false); m_Reset(CCITT4DecoderState.White); break; } } if ((int)m_State != 3) { continue; } } } return(((MemoryStream)writer.BaseStream).ToArray()); }
/// <summary> /// Creates a 32x32 fingerprint for the specified bitmap. /// </summary> /// <param name="bitmap">The bitmap.</param> /// <returns>Returns a fingerprint with 6 bits per pixel (32 px = 6144 bit = 768 byte = 1024 base32 chars).</returns> public static FingerPrint Create(IBitmap32 bitmap) { using (Bitmap32 thumb = bitmap.Resize(32, 32, ResizeMode.TouchFromInside)) { ARGBImageData data = thumb.Data; using (var ms = new MemoryStream()) { // calculate fingerprint and distance matrix var writer = new BitStreamWriter(ms); float[] distanceMatrix = new float[16]; { int x = 0, y = 0; ARGB last = 0; foreach (ARGB pixel in data.Data) { if (++x > 15) { x = 0; ++y; } int r = pixel.Red >> 6; int g = pixel.Green >> 6; int b = pixel.Blue >> 6; writer.WriteBits(r, 2); writer.WriteBits(g, 2); writer.WriteBits(b, 2); unchecked { int i = ((y << 1) & 0xC) + (x >> 2); float distance = Math.Abs(pixel.GetDistance(last)); distanceMatrix[i] += distance; last = pixel; } } } // normalize matrix float maxDistance = distanceMatrix.Max(); for (int i = 0; i < distanceMatrix.Length; i++) { distanceMatrix[i] /= maxDistance; } // calculate blocks uint[] blocks = new uint[4]; int[] index = new int[] { 0, 2, 8, 10 }; for (int i = 0; i < 4; i++) { int idx = index[i]; uint blockValue = (uint)(255 * distanceMatrix[idx]) << 24; blockValue |= (uint)(255 * distanceMatrix[idx + 1]) << 16; blockValue |= (uint)(255 * distanceMatrix[idx + 4]) << 8; blockValue |= (uint)(255 * distanceMatrix[idx + 5]); blocks[i] = blockValue; } /* * uint b1 = (uint)(uint.MaxValue * (distanceMatrix[0] + distanceMatrix[1] + distanceMatrix[4] + distanceMatrix[5]) /4); * uint b2 = (uint)(uint.MaxValue * (distanceMatrix[3] + distanceMatrix[2] + distanceMatrix[7] + distanceMatrix[6]) / 4); * uint b3 = (uint)(uint.MaxValue * (distanceMatrix[12] + distanceMatrix[13] + distanceMatrix[8] + distanceMatrix[9]) / 4); * uint b4 = (uint)(uint.MaxValue * (distanceMatrix[15] + distanceMatrix[14] + distanceMatrix[11] + distanceMatrix[10]) / 4); */ return(new FingerPrint(32, blocks, ms.ToArray())); } } }
public static void WriteByte(this BitStreamWriter writer, Byte value) { writer.WriteBits(value, 8); }
public static void WriteFloat32(this BitStreamWriter writer, Single value) { writer.WriteBits(BitConverterX.Float32ToUInt32(value), 32); }
public static void WriteUInt32(this BitStreamWriter writer, UInt32 value) { writer.WriteBits(value, 32); }
public static void WriteUInt16(this BitStreamWriter writer, UInt16 value) { writer.WriteBits(value, 16); }
public static void WriteInt32(this BitStreamWriter writer, Int32 value) { writer.WriteBits(BitConverterX.Int32ToUInt32(value), 32); }
public static void WriteChar(this BitStreamWriter writer, Char value) { writer.WriteBits(value, 16); }
public void Serialize(BitStreamWriter aWriter) { aWriter.WriteBit(1); aWriter.WriteBits(data, 8); }