/// <summary> /// Analizes all frames (from the end to the start) and paints all unchanged pixels with a given color, /// after, it cuts the image to reduce filesize. /// </summary> /// <param name="listToEncode">The list of frames to analize.</param> /// <param name="id">The Id of the Task.</param> /// <param name="tokenSource">The cancelation token source.</param> public static List <FrameInfo> CutUnchanged(List <FrameInfo> listToEncode, int id, CancellationTokenSource tokenSource) { //First frame rect. var size = listToEncode[0].ImageLocation.ScaledSize(); listToEncode[0].Rect = new Int32Rect(0, 0, (int)size.Width, (int)size.Height); //End to start FOR for (var index = listToEncode.Count - 1; index > 0; index--) { #region Cancellation if (tokenSource.Token.IsCancellationRequested) { Windows.Other.Encoder.SetStatus(Status.Canceled, id); break; } #endregion #region For each Frame, from the end to the start Windows.Other.Encoder.Update(id, index - 1); //First frame is ignored. if (index <= 0) { continue; } #region Get Image Info var imageAux1 = listToEncode[index - 1].ImageLocation.From(); var imageAux2 = listToEncode[index].ImageLocation.From(); var startY = new bool[imageAux1.Height]; var startX = new bool[imageAux1.Width]; var image1 = new PixelUtilOld(imageAux1); //Previous image var image2 = new PixelUtilOld(imageAux2); //Actual image image1.LockBits(); image2.LockBits(); var height = imageAux1.Height; var width = imageAux1.Width; #endregion //Only use Parallel if the image is big enough. if (width * height > 150000) { #region Parallel Loop //x - width - sides Parallel.For(0, width, x => { //y - height - up/down for (var y = 0; y < height; y++) { if (image1.GetPixel(x, y) != image2.GetPixel(x, y)) { #region Get the Changed Pixels startX[x] = true; startY[y] = true; #endregion } } }); //SPEEEEEED, alot! #endregion } else { #region Sequential Loop //x - width - sides for (var x = 0; x < width; x++) { //y - height - up/down for (var y = 0; y < height; y++) { #region For each Pixel if (image1.GetPixel(x, y) == image2.GetPixel(x, y)) { continue; } #region Get the Changed Pixels startX[x] = true; startY[y] = true; #endregion #endregion } } #endregion } image1.UnlockBits(); image2.UnlockBits(); #region Verify positions var firstX = startX.ToList().FindIndex(x => x); var lastX = startX.ToList().FindLastIndex(x => x); if (firstX == -1) { firstX = 0; } if (lastX == -1) { lastX = imageAux1.Width; } var firstY = startY.ToList().FindIndex(x => x); var lastY = startY.ToList().FindLastIndex(x => x); if (lastY == -1) { lastY = imageAux1.Height; } if (firstY == -1) { firstY = 0; } if (lastX < firstX) { var aux = lastX; lastX = firstX; firstX = aux; } if (lastY < firstY) { var aux = lastY; lastY = firstY; firstY = aux; } #endregion #region Get the Width and Height var heightCut = Math.Abs(lastY - firstY); var widthCut = Math.Abs(lastX - firstX); //If nothing changed, shift the delay. if (heightCut + widthCut == height + width) { listToEncode[index - 1].Delay += listToEncode[index].Delay; listToEncode[index].Rect = new Int32Rect(0, 0, 0, 0); GC.Collect(1); continue; } if (heightCut != height) { heightCut++; } if (widthCut != width) { widthCut++; } listToEncode[index].Rect = new Int32Rect(firstX, firstY, widthCut, heightCut); #endregion #region Update Image Info and Save //Cut the images and get the new values. var imageSave2 = new Bitmap(imageAux2.Clone(new Rectangle(firstX, firstY, widthCut, heightCut), imageAux2.PixelFormat)); imageAux2.Dispose(); imageAux1.Dispose(); imageSave2.Save(listToEncode[index].ImageLocation); #endregion GC.Collect(1); #endregion } return(listToEncode); }
/// <summary> /// Calculates the difference between one given frame and another. /// </summary> /// <param name="first">The first frame to compare.</param> /// <param name="second">The second frame to compare.</param> /// <returns>The similarity between the two frames in percentage.</returns> public static double CalculateDifference(FrameInfo first, FrameInfo second) { #region Get Image Info var imageAux1 = first.Path.From(); var imageAux2 = second.Path.From(); var image1 = new PixelUtilOld(imageAux1); //First image var image2 = new PixelUtilOld(imageAux2); //Last image image1.LockBits(); image2.LockBits(); var height = imageAux1.Height; var width = imageAux1.Width; var equalCount = 0; #endregion //Only use Parallel if the image is big enough. if (width * height > 150000) { #region Parallel Loop //x - width - sides Parallel.For(0, width, x => { //y - height - up/down for (var y = 0; y < height; y++) { if (image1.GetPixel(x, y) == image2.GetPixel(x, y)) { Interlocked.Increment(ref equalCount); } //equalCount = equalCount + (image1.GetPixel(x, y) == image2.GetPixel(x, y) ? 1 : 0); } }); #endregion } else { #region Sequential Loop //x - width - sides for (var x = 0; x < width; x++) { //y - height - up/down for (var y = 0; y < height; y++) { equalCount = equalCount + (image1.GetPixel(x, y) == image2.GetPixel(x, y) ? 1 : 0); } } #endregion } image1.UnlockBits(); image2.UnlockBits(); GC.Collect(1); return(Other.CrossMultiplication(width * height, equalCount, null)); }