private bool GetPopulairPoint(Rectangle rect, ref PopulairPoint PopuPoint) { for (int i = 0; i < populairPoints.Count; i++) { PopulairPoint point = populairPoints[i]; if (point.Rect.Width == rect.Width && point.Rect.Height == rect.Height && point.Rect.X == rect.X && point.Rect.Y == rect.Y) { PopuPoint = populairPoints[i]; return(true); } } return(false); }
public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) { lock (ImageProcessLock) { byte *pScan0 = (byte *)Scan0.ToInt32(); if (!outStream.CanWrite) { throw new Exception("Must have access to Write in the Stream"); } int Stride = 0; int RawLength = 0; int PixelSize = 0; switch (Format) { case PixelFormat.Format24bppRgb: PixelSize = 3; break; case PixelFormat.Format32bppArgb: case PixelFormat.Format32bppPArgb: PixelSize = 4; break; default: throw new NotSupportedException(Format.ToString()); } Stride = ImageSize.Width * PixelSize; RawLength = Stride * ImageSize.Height; if (EncodeBuffer == null) { this.EncodedFormat = Format; this.EncodedWidth = ImageSize.Width; this.EncodedHeight = ImageSize.Height; this.EncodeBuffer = new byte[RawLength]; fixed(byte *ptr = EncodeBuffer) { byte[] temp = null; using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) { temp = base.jpgCompression.Compress(TmpBmp); } outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); outStream.Write(temp, 0, temp.Length); NativeMethods.memcpy(new IntPtr(ptr), Scan0, (uint)RawLength); } return; } if (ScreenRefreshSW.ElapsedMilliseconds > ScreenRefreshTimer) { for (int i = 0; i < populairPoints.Count; i++) { if (populairPoints[i].Score == 0 || populairPoints[i].LastUpdate.Elapsed.Seconds > 5) { populairPoints.RemoveAt(i); } } ScreenRefreshSW = Stopwatch.StartNew(); } long oldPos = outStream.Position; outStream.Write(new byte[4], 0, 4); int TotalDataLength = 0; List <byte[]> updates = new List <byte[]>(); MemoryStream ms = new MemoryStream(); byte[] buffer = null; if (this.EncodedFormat != Format) { throw new Exception("PixelFormat is not equal to previous Bitmap"); } if (this.EncodedWidth != ImageSize.Width || this.EncodedHeight != ImageSize.Height) { throw new Exception("Bitmap width/height are not equal to previous bitmap"); } List <Rectangle> Blocks = new List <Rectangle>(); int index = 0; Size s = new Size(ScanArea.Width, CheckBlock.Height); Size lastSize = new Size(ScanArea.Width % CheckBlock.Width, ScanArea.Height % CheckBlock.Height); int lasty = ScanArea.Height - lastSize.Height; int lastx = ScanArea.Width - lastSize.Width; Rectangle cBlock = new Rectangle(); List <Rectangle> finalUpdates = new List <Rectangle>(); PopulairPoint[] points = GetPossibleVideos(); if (points.Length > 0) { ScanArea = new Rectangle(points[0].Rect.X, points[0].Rect.Y, points[0].Rect.Width + points[0].Rect.X, points[0].Rect.Height + points[0].Rect.Y); } s = new Size(ScanArea.Width, s.Height); fixed(byte *encBuffer = EncodeBuffer) { if (points.Length == 0) //only scan if there is no video { for (int y = ScanArea.Y; y != ScanArea.Height;) { if (y == lasty) { s = new Size(ScanArea.Width, lastSize.Height); } cBlock = new Rectangle(ScanArea.X, y, ScanArea.Width, s.Height); int offset = (y * Stride) + (ScanArea.X * PixelSize); if (NativeMethods.memcmp(encBuffer + offset, pScan0 + offset, (uint)Stride) != 0) { if (onCodeDebugScan != null) { onCodeDebugScan(cBlock); } 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; } for (int i = 0, x = ScanArea.X; i < Blocks.Count; i++) { s = new Size(CheckBlock.Width, Blocks[i].Height); x = ScanArea.X; while (x != ScanArea.Width) { if (x == lastx) { s = new Size(lastSize.Width, Blocks[i].Height); } cBlock = new Rectangle(x, Blocks[i].Y, s.Width, Blocks[i].Height); bool FoundChanges = false; int blockStride = PixelSize * cBlock.Width; for (int j = 0; j < cBlock.Height; j++) { int blockOffset = (Stride * (cBlock.Y + j)) + (PixelSize * cBlock.X); if (NativeMethods.memcmp(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride) != 0) { FoundChanges = true; } NativeMethods.memcpy(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride); //copy-changes } if (onCodeDebugScan != null) { onCodeDebugScan(cBlock); } if (FoundChanges) { index = finalUpdates.Count - 1; if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X) { Rectangle rect = finalUpdates[index]; int newWidth = cBlock.Width + rect.Width; cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); finalUpdates[index] = cBlock; } else { finalUpdates.Add(cBlock); } } x += s.Width; } } } else { finalUpdates.Add(points[0].Rect); } } for (int i = 0; i < finalUpdates.Count; i++) { Rectangle rect = finalUpdates[i]; int blockStride = PixelSize * rect.Width; Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); for (int j = 0, offset = 0; j < rect.Height; j++) { int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); NativeMethods.memcpy((byte *)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes offset += blockStride; } TmpBmp.UnlockBits(TmpData); outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); outStream.Write(new byte[4], 0, 4); long length = outStream.Position; long OldPos = outStream.Position; base.jpgCompression.Compress(TmpBmp, ref outStream); length = outStream.Position - length; outStream.Position = OldPos - 4; outStream.Write(BitConverter.GetBytes((int)length), 0, 4); outStream.Position += length; if (rect.Width > VideoScreenSize.Width && rect.Height > VideoScreenSize.Height) { PopulairPoint point = null; if (GetPopulairPoint(rect, ref point)) { point.Score++; point.LastUpdate = Stopwatch.StartNew(); //Console.WriteLine("[" + populairPoints.Count + "]Video spotted at x:" + rect.X + ", y:" + rect.Y + ", width:" + rect.Width + ", height:" + rect.Height); } else { populairPoints.Add(new PopulairPoint(rect)); } } TmpBmp.Dispose(); TotalDataLength += (int)length + (4 * 5); } /*for (int i = 0; i < finalUpdates.Count; i++) * { * Rectangle rect = finalUpdates[i]; * int blockStride = PixelSize * rect.Width; * buffer = new byte[blockStride * rect.Height]; * * fixed (byte* ptr = buffer) * { * for (int j = 0, offset = 0; j < rect.Height; j++) * { * int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); * NativeMethods.memcpy(ptr + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes * offset += blockStride; * } * * using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * PixelSize, Format, new IntPtr(ptr))) * { * buffer = base.jpgCompression.Compress(TmpBmp); * * if (rect.Width > VideoScreenSize.Width && rect.Height > VideoScreenSize.Height) * { * PopulairPoint point = null; * if (GetPopulairPoint(rect, ref point)) * { * point.Score++; * point.LastUpdate = Stopwatch.StartNew(); * Console.WriteLine("[" + populairPoints.Count + "]Video spotted at x:" + rect.X + ", y:" + rect.Y + ", width:" + rect.Width + ", height:" + rect.Height); * } * else * { * populairPoints.Add(new PopulairPoint(rect)); * } * } * } * } * * outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); * outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); * outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); * outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); * outStream.Write(BitConverter.GetBytes(buffer.Length), 0, 4); * outStream.Write(buffer, 0, buffer.Length); * TotalDataLength += buffer.Length + (4 * 5); * }*/ outStream.Position = oldPos; outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); Blocks.Clear(); ms.Close(); ms.Dispose(); } }