private void EyeDropperButton_PreviewMouseMove(object sender, MouseEventArgs e) { var str = new Native.PointW(); Native.GetCursorPos(ref str); var image = Native.CaptureBitmapSource((int)_captureSize.Width, (int)_captureSize.Height, str.X - (int)(_captureSize.Width / 2d), str.Y - (int)(_captureSize.Height / 2d)); if (image.Format != PixelFormats.Bgra32) { image = new FormatConvertedBitmap(image, PixelFormats.Bgra32, null, 0); } EyeDropperImage.Source = image; var pix = new PixelUtil(image); pix.LockBits(); UpdateMarkerPosition(pix.GetPixel((int)(_captureSize.Width / 2d), (int)(_captureSize.Height / 2d))); #region Update the values _isUpdating = true; AlphaIntegerUpDown.Value = SelectedColor.A; RedIntegerUpDown.Value = SelectedColor.R; GreenIntegerUpDown.Value = SelectedColor.G; BlueIntegerUpDown.Value = SelectedColor.B; _isUpdating = false; #endregion pix.UnlockBits(); }
private void EyeDropperButton_PreviewMouseMove(object sender, MouseEventArgs e) { var str = new Native.PointW(); Native.GetCursorPos(ref str); var image = Native.CaptureBitmapSource((int)_captureSize.Width, (int)_captureSize.Height, str.X - (int)(_captureSize.Width / 2d), str.Y - (int)(_captureSize.Height / 2d)); if (image.Format != PixelFormats.Bgra32) { image = new FormatConvertedBitmap(image, PixelFormats.Bgra32, null, 0); } EyeDropperImage.Source = image; var pix = new PixelUtil(image); pix.LockBits(); UpdateMarkerPosition(pix.GetPixel((int)(_captureSize.Width / 2d), (int)(_captureSize.Height / 2d))); pix.UnlockBits(); }
/// <summary> /// Applies the pixelate effect in given frame. /// </summary> /// <param name="image">The image to pixelate.</param> /// <param name="rectangle">The area to pixelate.</param> /// <param name="pixelateSize">The size of the pixel.</param> /// <param name="useMedian">Calculate the median color of the pixel block.</param> /// <returns>A pixelated Bitmap.</returns> public static BitmapSource Pixelate(BitmapSource image, Int32Rect rectangle, int pixelateSize, bool useMedian) { var croppedImage = new CroppedBitmap(image, rectangle); var pixelUtil = new PixelUtil(croppedImage); pixelUtil.LockBits(); //Loop through all the blocks that should be pixelated. for (var xx = 0; xx < croppedImage.PixelWidth; xx += pixelateSize) { for (var yy = 0; yy < croppedImage.PixelHeight; yy += pixelateSize) { var offsetX = pixelateSize / 2; var offsetY = pixelateSize / 2; if (xx + offsetX >= croppedImage.PixelWidth) { offsetX = croppedImage.PixelWidth; } if (yy + offsetY >= croppedImage.PixelHeight) { offsetY = croppedImage.PixelHeight; } //Get the pixel color in the center of the soon to be pixelated area. var pixel = useMedian ? pixelUtil.GetMedianColor(xx, yy, offsetX, offsetY) : pixelUtil.GetPixel(xx + offsetX, yy + offsetY); //For each pixel in the pixelate size, set it to the center color. for (var x = xx; x < xx + pixelateSize && x < croppedImage.PixelWidth; x++) { for (var y = yy; y < yy + pixelateSize && y < croppedImage.PixelHeight; y++) { pixelUtil.SetPixel(x, y, pixel); } } } } return(pixelUtil.UnlockBits()); }
private void GeneratePalette(string path) { var colorList = new List <Color>(); NonIndexedPixels = new List <Color>(); #region Get the Pixels var image = path.SourceFrom(); var pixelUtil = new PixelUtil(image); pixelUtil.LockBits(); for (int x = 0; x < image.PixelWidth; x++) { for (int y = 0; y < image.PixelHeight; y++) { colorList.Add(pixelUtil.GetPixel(x, y)); } } pixelUtil.UnlockBits(); #endregion //Save all the pixels in a property. NonIndexedPixels.AddRange(colorList); //TODO: more ways to decide which color to get //Like removing similar colors (with less than 5% similarity) if there is more than 256 colors, etc. //I probably can do that, using the groupby method. //if (NonIndexedPixels.Count == 100) //{ // ColorTable = new List<Color> // { // Color.FromRgb(255, 255, 255), // Color.FromRgb(255, 0, 0), // Color.FromRgb(0, 0, 255) // }; // return; //} ColorTable = colorList.GroupBy(x => x) //Grouping based on its value .OrderByDescending(g => g.Count()) //Order by most frequent values .Select(g => g.FirstOrDefault()) //take the first among the group .Take(256).ToList(); //Make sure that the transparent color is added to list. if (!IsFirstFrame && TransparentColor.HasValue && ColorTable.Count == 256) { //Only adds if there is 256 colors, so I need to make sure that the color won't be ignored. //If there is less than 256 selected colors, it means that the transparent color is already selected. //If the color isn't on the list, add or replace. if (ColorTable.All(x => x != TransparentColor.Value)) { //Adds to the last spot, keeping it sorted. (Since all the colors are ordered by descending) ColorTable.Insert(255, TransparentColor.Value); //Remove the exceding value at the last position. ColorTable.RemoveAt(256); } } //I need to signal the other method that I won't need transparency. WillUseTransparency = TransparentColor.HasValue && ColorTable.Contains(TransparentColor.Value); }
/// <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="transparent">The color to paint the unchanged pixels.</param> /// <param name="id">The Id of the current Task.</param> /// <param name="tokenSource">The cancelation token source.</param> /// <returns>A List contaning all frames and its cut points</returns> public static List <FrameInfo> PaintTransparentAndCut(List <FrameInfo> listToEncode, Color transparent, int id, CancellationTokenSource tokenSource) { //End to start FOR for (int index = listToEncode.Count - 1; index > 0; index--) { #region Cancellation if (tokenSource.Token.IsCancellationRequested) { Encoder.SetStatus(Status.Cancelled, id); break; } #endregion #region For each Frame, from the end to the start 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 PixelUtil(imageAux1); //Previous image var image2 = new PixelUtil(imageAux2); //Actual image image1.LockBits(); image2.LockBits(); int height = imageAux1.Height; int 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 (int y = 0; y < height; y++) { if (image1.GetPixel(x, y) == image2.GetPixel(x, y)) { image2.SetPixel(x, y, transparent); } else { #region Get the Changed Pixels startX[x] = true; startY[y] = true; #endregion } } }); //SPEEEEEED, alot! #endregion } else { #region Sequential Loop //x - width - sides for (int x = 0; x < width; x++) { //y - height - up/down for (int y = 0; y < height; y++) { #region For each Pixel if (image1.GetPixel(x, y) == image2.GetPixel(x, y)) { image2.SetPixel(x, y, transparent); } else { #region Get the Changed Pixels startX[x] = true; startY[y] = true; #endregion } #endregion } } #endregion } image1.UnlockBits(); image2.UnlockBits(); #region Verify positions int firstX = startX.ToList().FindIndex(x => x); int lastX = startX.ToList().FindLastIndex(x => x); if (firstX == -1) { firstX = 0; } if (lastX == -1) { lastX = imageAux1.Width; } int firstY = startY.ToList().FindIndex(x => x); int lastY = startY.ToList().FindLastIndex(x => x); if (lastY == -1) { lastY = imageAux1.Height; } if (firstY == -1) { firstY = 0; } if (lastX < firstX) { int aux = lastX; lastX = firstX; firstX = aux; } if (lastY < firstY) { int aux = lastY; lastY = firstY; firstY = aux; } #endregion #region Get the Width and Height int heigthCut = Math.Abs(lastY - firstY); int widthCut = Math.Abs(lastX - firstX); if (heigthCut != height) { heigthCut++; } else { //It means that no pixel got changed. heigthCut = 1; //So i cut to 1 pixel to save the most, 0 can't be. } if (widthCut != width) { widthCut++; } else { widthCut = 1; } #endregion //Cut the images and get the new values. var imageSave2 = new Bitmap(imageAux2.Clone(new Rectangle(firstX, firstY, widthCut, heigthCut), imageAux2.PixelFormat)); imageAux2.Dispose(); imageAux1.Dispose(); #region Update Image Info and Save imageSave2.Save(listToEncode[index].ImageLocation); listToEncode[index].PositionTopLeft = new Point(firstX, firstY); #endregion GC.Collect(1); #endregion } return(listToEncode); }
/// <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 (int index = listToEncode.Count - 1; index > 0; index--) { #region Cancellation if (tokenSource.Token.IsCancellationRequested) { Windows.Encoder.SetStatus(Status.Canceled, id); break; } #endregion #region For each Frame, from the end to the start Windows.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 PixelUtil(imageAux1); //Previous image var image2 = new PixelUtil(imageAux2); //Actual image image1.LockBits(); image2.LockBits(); int height = imageAux1.Height; int 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 (int 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 (int x = 0; x < width; x++) { //y - height - up/down for (int y = 0; y < height; y++) { #region For each Pixel if (image1.GetPixel(x, y) != image2.GetPixel(x, y)) { #region Get the Changed Pixels startX[x] = true; startY[y] = true; #endregion } #endregion } } #endregion } image1.UnlockBits(); image2.UnlockBits(); #region Verify positions int firstX = startX.ToList().FindIndex(x => x); int lastX = startX.ToList().FindLastIndex(x => x); if (firstX == -1) { firstX = 0; } if (lastX == -1) { lastX = imageAux1.Width; } int firstY = startY.ToList().FindIndex(x => x); int lastY = startY.ToList().FindLastIndex(x => x); if (lastY == -1) { lastY = imageAux1.Height; } if (firstY == -1) { firstY = 0; } if (lastX < firstX) { int aux = lastX; lastX = firstX; firstX = aux; } if (lastY < firstY) { int aux = lastY; lastY = firstY; firstY = aux; } #endregion #region Get the Width and Height int heightCut = Math.Abs(lastY - firstY); int 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; } else { 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); }