예제 #1
0
        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();
            }
        }