public override unsafe void CodeImage(Bitmap bitmap, Stream outStream) { lock (ImageProcessLock) { if (!outStream.CanWrite) { throw new Exception("Must have access to Write in the Stream"); } if (LastFrame == null) { byte[] temp = base.jpgCompression.Compress(bitmap); outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); outStream.Write(temp, 0, temp.Length); SetLastFrame(ref bitmap); return; } long oldPos = outStream.Position; outStream.Write(new byte[4], 0, 4); int TotalDataLength = 0; List <byte[]> updates = new List <byte[]>(); SimpleBitmap sbBmp = new SimpleBitmap(bitmap); MemoryStream ms = new MemoryStream(); byte[] buffer = null; if (!LastFrame.Locked) { LastFrame.Lock(); } sbBmp.Lock(); if (sbBmp.Info.PixelSize != LastFrame.Info.PixelSize) { throw new Exception("PixelFormat is not equal to previous Bitmap"); } if (LastFrame.Info.Width != sbBmp.Info.Width || LastFrame.Info.Height != sbBmp.Info.Height) { sbBmp.Unlock(); throw new Exception("Bitmap width/height are not equal to previous bitmap"); } List <Rectangle> Blocks = new List <Rectangle>(); int index = 0; int y = 0; int x = 0; Size s = new Size(bitmap.Width, CheckBlock.Height); Size lastSize = new Size(bitmap.Width % CheckBlock.Width, bitmap.Height % CheckBlock.Height); int lasty = bitmap.Height - lastSize.Height; int lastx = bitmap.Width - lastSize.Width; Rectangle cBlock = new Rectangle(); s = new Size(bitmap.Width, s.Height); while (y != bitmap.Height) { if (y == lasty) { s = new Size(bitmap.Width, lastSize.Height); } cBlock = new Rectangle(0, y, bitmap.Width, s.Height); if (onCodeDebugScan != null) { onCodeDebugScan(cBlock); } if (!SimpleBitmap.Compare(cBlock, LastFrame.Scan0_int, sbBmp.Scan0_int, sbBmp.Info)) //if (!SimpleBitmap.Compare(y, s.Height, LastFrame.Scan0_int, sbBmp.Scan0_int, sbBmp.Info)) { index = Blocks.Count - 1; if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) { cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); Blocks[index] = cBlock; } else { Blocks.Add(cBlock); } } y += s.Height; } List <CacheInfo> finalUpdates = new List <CacheInfo>(); const int CheckHeight = 50; for (int i = 0; i < Blocks.Count; i++) { s = new Size(CheckBlock.Width, Blocks[i].Height); y = Blocks[i].Y; lasty = (Blocks[i].Y + Blocks[i].Height); while (y != lasty) { int ScanHeight = y + CheckHeight > lasty ? lasty - y : CheckHeight; x = 0; while (x != bitmap.Width) { if (x == lastx) { s = new Size(lastSize.Width, Blocks[i].Height); } cBlock = new Rectangle(x, y, s.Width, ScanHeight); if (onCodeDebugScan != null) { onCodeDebugScan(cBlock); } if (!SimpleBitmap.Compare(cBlock, sbBmp.Scan0_int, LastFrame.Scan0_int, sbBmp.Info)) { /*byte[] tempData = new byte[0]; * LastFrame.CopyBlock(cBlock, ref tempData); * finalUpdates.Add(new CacheInfo(0, false, tempData, cBlock));*/ //hash it and see if exists in cache hasher = new CRC32(); //re-initialize for seed byte[] tempData = new byte[0]; LastFrame.CopyBlock(cBlock, ref tempData); int hash = BitConverter.ToInt32(hasher.ComputeHash(tempData), 0); if (codeCached.Count >= MaxBuffers) { codeCached.RemoveAt(0); } if (codeCached.ContainsKey(hash)) { CachedSize += (ulong)tempData.Length; finalUpdates.Add(new CacheInfo(hash, true, new byte[0], cBlock)); } else { //nothing found in cache let's use the normal way codeCached.Add(hash, tempData); finalUpdates.Add(new CacheInfo(hash, false, tempData, cBlock)); } } x += s.Width; } y += ScanHeight; } } for (int i = 0; i < finalUpdates.Count; i++) { buffer = new byte[0]; Rectangle rect = finalUpdates[i].Rect; if (!finalUpdates[i].isCached) { fixed(byte *ptr = finalUpdates[i].Data) { using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * LastFrame.Info.PixelSize, LastFrame.bitmapData.PixelFormat, new IntPtr(ptr))) { buffer = base.jpgCompression.Compress(TmpBmp); } } } outStream.WriteByte(finalUpdates[i].isCached ? (byte)1 : (byte)0); outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.X), 0, 4); outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.Y), 0, 4); outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.Width), 0, 4); outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.Height), 0, 4); outStream.Write(BitConverter.GetBytes(finalUpdates[i].Hash), 0, 4); outStream.Write(BitConverter.GetBytes(buffer.Length), 0, 4); outStream.Write(buffer, 0, buffer.Length); TotalDataLength += buffer.Length + (4 * 6) + 1; } outStream.Position = oldPos; outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); Blocks.Clear(); SetLastFrame(sbBmp); ms.Close(); ms.Dispose(); } }