/// <summary> /// Implements the operator |. /// </summary> /// <param name="Image1">The first image.</param> /// <param name="Image2">The second image</param> /// <returns>The result of the operator.</returns> public static SwiftBitmap operator |(SwiftBitmap Image1, SwiftBitmap Image2) { Contract.Requires <ArgumentNullException>(Image1 != null, "Image1"); Contract.Requires <ArgumentNullException>(Image2 != null, "Image2"); Image1.Lock(); Image2.Lock(); var Result = new SwiftBitmap(Image1.Width, Image1.Height); Result.Lock(); Parallel.For(0, Result.Width, x => { for (int y = 0; y < Result.Height; ++y) { var Pixel1 = Image1.GetPixel(x, y); var Pixel2 = Image2.GetPixel(x, y); Result.SetPixel(x, y, Color.FromArgb(Pixel1.R | Pixel2.R, Pixel1.G | Pixel2.G, Pixel1.B | Pixel2.B)); } }); Image2.Unlock(); Image1.Unlock(); return(Result.Unlock()); }
/// <summary> /// Loads an image /// </summary> /// <param name="ImageUsing">Image to load</param> public virtual void LoadImage(SwiftBitmap ImageUsing) { Contract.Requires <ArgumentNullException>(ImageUsing != null, "ImageUsing"); Width = ImageUsing.Width; Height = ImageUsing.Height; ImageUsing.Lock(); R.Clear(); G.Clear(); B.Clear(); for (int x = 0; x < ImageUsing.Width; ++x) { for (int y = 0; y < ImageUsing.Height; ++y) { var TempColor = ImageUsing.GetPixel(x, y); ++R[(int)TempColor.R]; ++G[(int)TempColor.G]; ++B[(int)TempColor.B]; } } ImageUsing.Unlock(); }
/// <summary> /// Pixelates an image /// </summary> /// <param name="OriginalImage">Image to pixelate</param> /// <param name="PixelSize">Size of the "pixels" in pixels</param> /// <returns>A SwiftBitmap image</returns> public static SwiftBitmap Pixelate(this SwiftBitmap OriginalImage, int PixelSize = 5) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); using (SwiftBitmap NewSwiftBitmap = new SwiftBitmap(OriginalImage.Width, OriginalImage.Height)) { NewSwiftBitmap.Lock(); OriginalImage.Lock(); for (int x = 0; x < NewSwiftBitmap.Width; x += (PixelSize / 2)) { int MinX = (x - (PixelSize / 2)).Clamp(NewSwiftBitmap.Width, 0); int MaxX = (x + (PixelSize / 2)).Clamp(NewSwiftBitmap.Width, 0); for (int y = 0; y < NewSwiftBitmap.Height; y += (PixelSize / 2)) { int RValue = 0; int GValue = 0; int BValue = 0; int MinY = (y - (PixelSize / 2)).Clamp(NewSwiftBitmap.Height, 0); int MaxY = (y + (PixelSize / 2)).Clamp(NewSwiftBitmap.Height, 0); for (int x2 = MinX; x2 < MaxX; ++x2) { for (int y2 = MinY; y2 < MaxY; ++y2) { Color Pixel = OriginalImage.GetPixel(x2, y2); RValue += Pixel.R; GValue += Pixel.G; BValue += Pixel.B; } } RValue = RValue / (PixelSize * PixelSize); GValue = GValue / (PixelSize * PixelSize); BValue = BValue / (PixelSize * PixelSize); Color TempPixel = Color.FromArgb(RValue.Clamp(255, 0), GValue.Clamp(255, 0), BValue.Clamp(255, 0)); Parallel.For(MinX, MaxX, x2 => { for (int y2 = MinY; y2 < MaxY; ++y2) { NewSwiftBitmap.SetPixel(x2, y2, TempPixel); } }); } } NewSwiftBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewSwiftBitmap); } }
/// <summary> /// Creates the normal map /// </summary> /// <param name="ImageUsing">Image to create the normal map from</param> /// <param name="InvertX">Invert the X direction</param> /// <param name="InvertY">Invert the Y direction</param> /// <returns>Returns the resulting normal map</returns> public static SwiftBitmap NormalMap(this SwiftBitmap ImageUsing, bool InvertX = false, bool InvertY = false) { Contract.Requires<ArgumentNullException>(ImageUsing != null, "ImageUsing"); using (SwiftBitmap TempImageX = ((SwiftBitmap)ImageUsing.Clone()).BumpMap(Direction.LeftRight, InvertX)) { using (SwiftBitmap TempImageY = ((SwiftBitmap)ImageUsing.Clone()).BumpMap(Direction.TopBottom, InvertY)) { using (SwiftBitmap ReturnImage = new SwiftBitmap(TempImageX.Width, TempImageX.Height)) { TempImageX.Lock(); TempImageY.Lock(); ReturnImage.Lock(); int Width = TempImageX.Width; int Height = TempImageX.Height; Parallel.For(0, Height, y => { var TempVector = new Vector3(0.0, 0.0, 0.0); for (int x = 0; x < Width; ++x) { Color TempPixelX = TempImageX.GetPixel(x, y); Color TempPixelY = TempImageY.GetPixel(x, y); TempVector.X = (double)(TempPixelX.R) / 255.0; TempVector.Y = (double)(TempPixelY.R) / 255.0; TempVector.Z = 1.0; TempVector.Normalize(); TempVector.X = ((TempVector.X + 1.0) / 2.0) * 255.0; TempVector.Y = ((TempVector.Y + 1.0) / 2.0) * 255.0; TempVector.Z = ((TempVector.Z + 1.0) / 2.0) * 255.0; ReturnImage.SetPixel(x, y, Color.FromArgb((int)TempVector.X, (int)TempVector.Y, (int)TempVector.Z)); } }); TempImageX.Unlock(); TempImageY.Unlock(); ReturnImage.Unlock(); return ImageUsing.Copy(ReturnImage); } } } }
/// <summary> /// gets the negative of the image /// </summary> /// <param name="OriginalImage">Image to manipulate</param> /// <returns>A SwiftBitmap image</returns> public static SwiftBitmap Negative(this SwiftBitmap OriginalImage) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); using (SwiftBitmap NewSwiftBitmap = new SwiftBitmap(OriginalImage.Width, OriginalImage.Height)) { NewSwiftBitmap.Lock(); OriginalImage.Lock(); int Width = NewSwiftBitmap.Width; int Height = NewSwiftBitmap.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { Color CurrentPixel = OriginalImage.GetPixel(x, y); Color TempValue = Color.FromArgb(255 - CurrentPixel.R, 255 - CurrentPixel.G, 255 - CurrentPixel.B); NewSwiftBitmap.SetPixel(x, y, TempValue); } }); NewSwiftBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewSwiftBitmap); } }
/// <summary> /// Does smoothing using a median filter /// </summary> /// <param name="OriginalImage">Image to manipulate</param> /// <param name="Size">Size of the aperture</param> /// <returns>A SwiftBitmap image</returns> public static SwiftBitmap MedianFilter(this SwiftBitmap OriginalImage, int Size = 3) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); using (SwiftBitmap NewSwiftBitmap = new SwiftBitmap(OriginalImage.Width, OriginalImage.Height)) { NewSwiftBitmap.Lock(); OriginalImage.Lock(); int ApetureMin = -(Size / 2); int ApetureMax = (Size / 2); int Width = NewSwiftBitmap.Width; int Height = NewSwiftBitmap.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { var RValues = new List<int>(); var GValues = new List<int>(); var BValues = new List<int>(); for (int x2 = ApetureMin; x2 < ApetureMax; ++x2) { int TempX = x + x2; if (TempX >= 0 && TempX < Width) { for (int y2 = ApetureMin; y2 < ApetureMax; ++y2) { int TempY = y + y2; if (TempY >= 0 && TempY < Height) { Color TempColor = OriginalImage.GetPixel(TempX, TempY); RValues.Add(TempColor.R); GValues.Add(TempColor.G); BValues.Add(TempColor.B); } } } } Color MedianPixel = Color.FromArgb(RValues.Median(), GValues.Median(), BValues.Median()); NewSwiftBitmap.SetPixel(x, y, MedianPixel); } }); NewSwiftBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewSwiftBitmap); } }
/// <summary> /// Does smoothing using a kuwahara blur /// </summary> /// <param name="OriginalImage">Image to manipulate</param> /// <param name="Size">Size of the aperture</param> /// <returns>A SwiftBitmap object</returns> public static SwiftBitmap KuwaharaBlur(this SwiftBitmap OriginalImage, int Size = 3) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); using (SwiftBitmap NewSwiftBitmap = new SwiftBitmap(OriginalImage.Width, OriginalImage.Height)) { NewSwiftBitmap.Lock(); OriginalImage.Lock(); int[] ApetureMinX = { -(Size / 2), 0, -(Size / 2), 0 }; int[] ApetureMaxX = { 0, (Size / 2), 0, (Size / 2) }; int[] ApetureMinY = { -(Size / 2), -(Size / 2), 0, 0 }; int[] ApetureMaxY = { 0, 0, (Size / 2), (Size / 2) }; int Width = NewSwiftBitmap.Width; int Height = NewSwiftBitmap.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { int[] RValues = { 0, 0, 0, 0 }; int[] GValues = { 0, 0, 0, 0 }; int[] BValues = { 0, 0, 0, 0 }; int[] NumPixels = { 0, 0, 0, 0 }; int[] MaxRValue = { 0, 0, 0, 0 }; int[] MaxGValue = { 0, 0, 0, 0 }; int[] MaxBValue = { 0, 0, 0, 0 }; int[] MinRValue = { 255, 255, 255, 255 }; int[] MinGValue = { 255, 255, 255, 255 }; int[] MinBValue = { 255, 255, 255, 255 }; for (int i = 0; i < 4; ++i) { for (int x2 = ApetureMinX[i]; x2 < ApetureMaxX[i]; ++x2) { int TempX = x + x2; if (TempX >= 0 && TempX < Width) { for (int y2 = ApetureMinY[i]; y2 < ApetureMaxY[i]; ++y2) { int TempY = y + y2; if (TempY >= 0 && TempY < Height) { Color TempColor = OriginalImage.GetPixel(TempX, TempY); RValues[i] += TempColor.R; GValues[i] += TempColor.G; BValues[i] += TempColor.B; if (TempColor.R > MaxRValue[i]) MaxRValue[i] = TempColor.R; else if (TempColor.R < MinRValue[i]) MinRValue[i] = TempColor.R; if (TempColor.G > MaxGValue[i]) MaxGValue[i] = TempColor.G; else if (TempColor.G < MinGValue[i]) MinGValue[i] = TempColor.G; if (TempColor.B > MaxBValue[i]) MaxBValue[i] = TempColor.B; else if (TempColor.B < MinBValue[i]) MinBValue[i] = TempColor.B; ++NumPixels[i]; } } } } } int j = 0; int MinDifference = 10000; for (int i = 0; i < 4; ++i) { int CurrentDifference = (MaxRValue[i] - MinRValue[i]) + (MaxGValue[i] - MinGValue[i]) + (MaxBValue[i] - MinBValue[i]); if (CurrentDifference < MinDifference && NumPixels[i] > 0) { j = i; MinDifference = CurrentDifference; } } Color MeanPixel = Color.FromArgb(RValues[j] / NumPixels[j], GValues[j] / NumPixels[j], BValues[j] / NumPixels[j]); NewSwiftBitmap.SetPixel(x, y, MeanPixel); } }); NewSwiftBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewSwiftBitmap); } }
/// <summary> /// Applies the convolution filter to the image /// </summary> /// <param name="filter">The filter.</param> /// <param name="absolute">if set to <c>true</c> then the absolute value is used</param> /// <param name="offset">The offset to use for each pixel</param> /// <returns>Returns the image with the filter applied</returns> public SwiftBitmap ApplyConvolutionFilter(int[][] filter, bool absolute = false, int offset = 0) { Contract.Requires<NullReferenceException>(InternalBitmap != null); using (SwiftBitmap Result = new SwiftBitmap(Width, Height)) { Lock(); Result.Lock(); Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { int RValue = 0; int GValue = 0; int BValue = 0; int Weight = 0; int XCurrent = -filter[0].Length / 2; for (int x2 = 0; x2 < filter[0].Length; ++x2) { if (XCurrent + x < Width && XCurrent + x >= 0) { int YCurrent = -filter.Length / 2; for (int y2 = 0; y2 < filter.Length; ++y2) { if (YCurrent + y < Height && YCurrent + y >= 0) { var Pixel = GetPixel(XCurrent + x, YCurrent + y); RValue += filter[x2][y2] * Pixel.R; GValue += filter[x2][y2] * Pixel.G; BValue += filter[x2][y2] * Pixel.B; Weight += filter[x2][y2]; } ++YCurrent; } } ++XCurrent; } var MeanPixel = GetPixel(x, y); if (Weight == 0) Weight = 1; if (Weight > 0) { if (absolute) { RValue = System.Math.Abs(RValue); GValue = System.Math.Abs(GValue); BValue = System.Math.Abs(BValue); } RValue = (RValue / Weight) + offset; RValue = RValue.Clamp(255, 0); GValue = (GValue / Weight) + offset; GValue = GValue.Clamp(255, 0); BValue = (BValue / Weight) + offset; BValue = BValue.Clamp(255, 0); MeanPixel = Color.FromArgb(RValue, GValue, BValue); } Result.SetPixel(x, y, MeanPixel); } }); Unlock(); Result.Unlock(); return Copy(Result); } }
/// <summary> /// Does turbulence manipulation of the image /// </summary> /// <param name="OriginalImage">Image to transform</param> /// <param name="Roughness">Roughness of the movement</param> /// <param name="Power">How strong the movement is</param> /// <param name="Seed">Random seed</param> /// <returns>A SwiftBitmap object containing the new image</returns> public static SwiftBitmap Turbulence(this SwiftBitmap OriginalImage, int Roughness = 8, float Power = 5.0f, int Seed = 25123864) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); int Width = OriginalImage.Width; int Height = OriginalImage.Height; OriginalImage.Lock(); using (SwiftBitmap NewSwiftBitmap = new SwiftBitmap(Width, Height)) { NewSwiftBitmap.Lock(); using (SwiftBitmap XNoise = PerlinNoise.Generate(Width, Height, 255, 0, 0.0625f, 1.0f, 0.5f, Roughness, Seed)) { XNoise.Lock(); using (SwiftBitmap YNoise = PerlinNoise.Generate(Width, Height, 255, 0, 0.0625f, 1.0f, 0.5f, Roughness, Seed * 2)) { YNoise.Lock(); Parallel.For(0, Height, y => { for (int x = 0; x < Width; ++x) { float XDistortion = x + (GetHeight(x, y, XNoise) * Power); float YDistortion = y + (GetHeight(x, y, YNoise) * Power); int X1 = ((int)XDistortion).Clamp(Width - 1, 0); int Y1 = ((int)YDistortion).Clamp(Height - 1, 0); NewSwiftBitmap.SetPixel(x, y, OriginalImage.GetPixel(X1, Y1)); } }); YNoise.Unlock(); } XNoise.Unlock(); } NewSwiftBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewSwiftBitmap); } }
/// <summary> /// Does threshold manipulation of the image /// </summary> /// <param name="OriginalImage">Image to transform</param> /// <param name="Threshold"> /// Float defining the threshold at which to set the pixel to black vs white. /// </param> /// <returns>A SwiftBitmap object containing the new image</returns> public static SwiftBitmap Threshold(this SwiftBitmap OriginalImage, float Threshold = 0.5f) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); using (SwiftBitmap NewSwiftBitmap = new SwiftBitmap(OriginalImage.Width, OriginalImage.Height)) { NewSwiftBitmap.Lock(); OriginalImage.Lock(); int Width = NewSwiftBitmap.Width; int Height = NewSwiftBitmap.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { Color TempColor = OriginalImage.GetPixel(x, y); if ((TempColor.R + TempColor.G + TempColor.B) / 755.0f > Threshold) NewSwiftBitmap.SetPixel(x, y, Color.White); else NewSwiftBitmap.SetPixel(x, y, Color.Black); } }); NewSwiftBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewSwiftBitmap); } }
/// <summary> /// Stretches the contrast /// </summary> /// <param name="OriginalImage">Image to manipulate</param> /// <returns>A SwiftBitmap image</returns> public static SwiftBitmap StretchContrast(this SwiftBitmap OriginalImage) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); using (SwiftBitmap NewBitmap = new SwiftBitmap(OriginalImage.Width, OriginalImage.Height)) { NewBitmap.Lock(); OriginalImage.Lock(); Color MinValue; Color MaxValue; GetMinMaxPixel(out MinValue, out MaxValue, OriginalImage); int Width = NewBitmap.Width; int Height = NewBitmap.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { Color CurrentPixel = OriginalImage.GetPixel(x, y); Color TempValue = Color.FromArgb(Map(CurrentPixel.R, MinValue.R, MaxValue.R), Map(CurrentPixel.G, MinValue.G, MaxValue.G), Map(CurrentPixel.B, MinValue.B, MaxValue.B)); NewBitmap.SetPixel(x, y, TempValue); } }); NewBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewBitmap); } }
/// <summary> /// Sobel edge detection function /// </summary> /// <param name="Input">Image to manipulate</param> /// <returns>A SwiftBitmap image</returns> public static SwiftBitmap SobelEdgeDetection(this SwiftBitmap Input) { Contract.Requires<ArgumentNullException>(Input != null, "Input"); Input.BlackAndWhite(); using (SwiftBitmap TempImageX = ((SwiftBitmap)Input.Clone()).ApplyConvolutionFilter(new int[][]{ new int[] {-1, 0, 1}, new int[] {-2, 0, 2}, new int[] {-1, 0, 1} }, true)) { using (SwiftBitmap TempImageY = ((SwiftBitmap)Input.Clone()).ApplyConvolutionFilter(new int[][]{ new int[] {1, 2, 1}, new int[] {0, 0, 0}, new int[] {-1, -2, -1} }, true)) { using (SwiftBitmap NewBitmap = new SwiftBitmap(Input.Width, Input.Height)) { NewBitmap.Lock(); TempImageX.Lock(); TempImageY.Lock(); int Width = NewBitmap.Width; int Height = NewBitmap.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { Color Pixel1 = TempImageX.GetPixel(x, y); Color Pixel2 = TempImageY.GetPixel(x, y); NewBitmap.SetPixel(x, y, Color.FromArgb((Pixel1.R + Pixel2.R).Clamp(255, 0), (Pixel1.G + Pixel2.G).Clamp(255, 0), (Pixel1.B + Pixel2.B).Clamp(255, 0))); } }); NewBitmap.Unlock(); TempImageY.Unlock(); TempImageX.Unlock(); return Input.Copy(NewBitmap).Negative(); } } } }
/// <summary> /// Does smoothing using a SNN blur /// </summary> /// <param name="OriginalImage">Image to manipulate</param> /// <param name="Size">Size of the aperture</param> /// <returns>The resulting SwiftBitmap</returns> public static SwiftBitmap SNNBlur(this SwiftBitmap OriginalImage, int Size = 3) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); using (SwiftBitmap NewSwiftBitmap = new SwiftBitmap(OriginalImage.Width, OriginalImage.Height)) { NewSwiftBitmap.Lock(); OriginalImage.Lock(); int ApetureMinX = -(Size / 2); int ApetureMaxX = (Size / 2); int ApetureMinY = -(Size / 2); int ApetureMaxY = (Size / 2); int Width = NewSwiftBitmap.Width; int Height = NewSwiftBitmap.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { int RValue = 0; int GValue = 0; int BValue = 0; int NumPixels = 0; for (int x2 = ApetureMinX; x2 < ApetureMaxX; ++x2) { int TempX1 = x + x2; int TempX2 = x - x2; if (TempX1 >= 0 && TempX1 < Width && TempX2 >= 0 && TempX2 < Width) { for (int y2 = ApetureMinY; y2 < ApetureMaxY; ++y2) { int TempY1 = y + y2; int TempY2 = y - y2; if (TempY1 >= 0 && TempY1 < Height && TempY2 >= 0 && TempY2 < Height) { Color TempColor = OriginalImage.GetPixel(x, y); Color TempColor2 = OriginalImage.GetPixel(TempX1, TempY1); Color TempColor3 = OriginalImage.GetPixel(TempX2, TempY2); if (Distance(TempColor.R, TempColor2.R, TempColor.G, TempColor2.G, TempColor.B, TempColor2.B) < Distance(TempColor.R, TempColor3.R, TempColor.G, TempColor3.G, TempColor.B, TempColor3.B)) { RValue += TempColor2.R; GValue += TempColor2.G; BValue += TempColor2.B; } else { RValue += TempColor3.R; GValue += TempColor3.G; BValue += TempColor3.B; } ++NumPixels; } } } } Color MeanPixel = Color.FromArgb(RValue / NumPixels, GValue / NumPixels, BValue / NumPixels); NewSwiftBitmap.SetPixel(x, y, MeanPixel); } }); NewSwiftBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewSwiftBitmap); } }
/// <summary> /// Loads an image /// </summary> /// <param name="ImageUsing">Image to load</param> public virtual void LoadImage(SwiftBitmap ImageUsing) { Contract.Requires<ArgumentNullException>(ImageUsing != null, "ImageUsing"); Width = ImageUsing.Width; Height = ImageUsing.Height; ImageUsing.Lock(); R.Clear(); G.Clear(); B.Clear(); for (int x = 0; x < ImageUsing.Width; ++x) { for (int y = 0; y < ImageUsing.Height; ++y) { Color TempColor = ImageUsing.GetPixel(x, y); ++R[(int)TempColor.R]; ++G[(int)TempColor.G]; ++B[(int)TempColor.B]; } } ImageUsing.Unlock(); }
/// <summary> /// Does a "wave" effect on the image /// </summary> /// <param name="OriginalImage">Image to manipulate</param> /// <param name="Amplitude">Amplitude of the sine wave</param> /// <param name="Frequency">Frequency of the sine wave</param> /// <param name="XDirection">Determines if this should be done in the X direction</param> /// <param name="YDirection">Determines if this should be done in the Y direction</param> /// <returns>A SwiftBitmap which has been modified</returns> public static SwiftBitmap SinWave(this SwiftBitmap OriginalImage, float Amplitude, float Frequency, bool XDirection, bool YDirection) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); using (SwiftBitmap NewSwiftBitmap = new SwiftBitmap(OriginalImage.Width, OriginalImage.Height)) { NewSwiftBitmap.Lock(); OriginalImage.Lock(); int Width = NewSwiftBitmap.Width; int Height = NewSwiftBitmap.Height; Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { double Value1 = 0; double Value2 = 0; if (YDirection) Value1 = System.Math.Sin(((x * Frequency) * System.Math.PI) / 180.0d) * Amplitude; if (XDirection) Value2 = System.Math.Sin(((y * Frequency) * System.Math.PI) / 180.0d) * Amplitude; Value1 = y - (int)Value1; Value2 = x - (int)Value2; while (Value1 < 0) Value1 += Height; while (Value2 < 0) Value2 += Width; while (Value1 >= Height) Value1 -= Height; while (Value2 >= Width) Value2 -= Width; NewSwiftBitmap.SetPixel(x, y, OriginalImage.GetPixel((int)Value2, (int)Value1)); } }); NewSwiftBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewSwiftBitmap); } }
/// <summary> /// Uses an RGB histogram to equalize the image /// </summary> /// <param name="OriginalImage">Image to manipulate</param> /// <returns>The resulting SwiftBitmap image</returns> public static SwiftBitmap Equalize(this SwiftBitmap OriginalImage) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); using (SwiftBitmap NewSwiftBitmap = new SwiftBitmap(OriginalImage.Width, OriginalImage.Height)) { var TempHistogram = new RGBHistogram(OriginalImage); TempHistogram.Equalize(); NewSwiftBitmap.Lock(); OriginalImage.Lock(); Parallel.For(0, OriginalImage.Width, x => { for (int y = 0; y < OriginalImage.Height; ++y) { Color Current = OriginalImage.GetPixel(x, y); var NewR = (int)TempHistogram.R[Current.R]; var NewG = (int)TempHistogram.G[Current.G]; var NewB = (int)TempHistogram.B[Current.B]; NewR = NewR.Clamp(255, 0); NewG = NewG.Clamp(255, 0); NewB = NewB.Clamp(255, 0); NewSwiftBitmap.SetPixel(x, y, Color.FromArgb(NewR, NewG, NewB)); } }); NewSwiftBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewSwiftBitmap); } }
/// <summary> /// Causes a "Jitter" effect /// </summary> /// <param name="OriginalImage">Image to manipulate</param> /// <param name="MaxJitter">Maximum number of pixels the item can move</param> /// <returns>A SwiftBitmap object</returns> public static SwiftBitmap Jitter(this SwiftBitmap OriginalImage, int MaxJitter = 5) { Contract.Requires<ArgumentNullException>(OriginalImage != null, "OriginalImage"); using (SwiftBitmap NewSwiftBitmap = new SwiftBitmap(OriginalImage.Width, OriginalImage.Height)) { NewSwiftBitmap.Lock(); OriginalImage.Lock(); Parallel.For(0, OriginalImage.Width, x => { for (int y = 0; y < OriginalImage.Height; ++y) { int NewX = Random.Random.ThreadSafeNext(-MaxJitter, MaxJitter); int NewY = Random.Random.ThreadSafeNext(-MaxJitter, MaxJitter); NewX += x; NewY += y; NewX = NewX.Clamp(OriginalImage.Width - 1, 0); NewY = NewY.Clamp(OriginalImage.Height - 1, 0); NewSwiftBitmap.SetPixel(x, y, OriginalImage.GetPixel(NewX, NewY)); } }); NewSwiftBitmap.Unlock(); return OriginalImage.Unlock().Copy(NewSwiftBitmap); } }
/// <summary> /// Applies the convolution filter to the image /// </summary> /// <param name="filter">The filter.</param> /// <param name="absolute">if set to <c>true</c> then the absolute value is used</param> /// <param name="offset">The offset to use for each pixel</param> /// <returns>Returns the image with the filter applied</returns> public SwiftBitmap ApplyConvolutionFilter(int[][] filter, bool absolute = false, int offset = 0) { Contract.Requires <NullReferenceException>(InternalBitmap != null); using (SwiftBitmap Result = new SwiftBitmap(Width, Height)) { Lock(); Result.Lock(); Parallel.For(0, Width, x => { for (int y = 0; y < Height; ++y) { int RValue = 0; int GValue = 0; int BValue = 0; int Weight = 0; int XCurrent = -filter[0].Length / 2; for (int x2 = 0; x2 < filter[0].Length; ++x2) { if (XCurrent + x < Width && XCurrent + x >= 0) { int YCurrent = -filter.Length / 2; for (int y2 = 0; y2 < filter.Length; ++y2) { if (YCurrent + y < Height && YCurrent + y >= 0) { var Pixel = GetPixel(XCurrent + x, YCurrent + y); RValue += filter[x2][y2] * Pixel.R; GValue += filter[x2][y2] * Pixel.G; BValue += filter[x2][y2] * Pixel.B; Weight += filter[x2][y2]; } ++YCurrent; } } ++XCurrent; } var MeanPixel = GetPixel(x, y); if (Weight == 0) { Weight = 1; } if (Weight > 0) { if (absolute) { RValue = System.Math.Abs(RValue); GValue = System.Math.Abs(GValue); BValue = System.Math.Abs(BValue); } RValue = (RValue / Weight) + offset; RValue = RValue.Clamp(255, 0); GValue = (GValue / Weight) + offset; GValue = GValue.Clamp(255, 0); BValue = (BValue / Weight) + offset; BValue = BValue.Clamp(255, 0); MeanPixel = Color.FromArgb(RValue, GValue, BValue); } Result.SetPixel(x, y, MeanPixel); } }); Unlock(); Result.Unlock(); return(Copy(Result)); } }
/// <summary> /// Implements the operator |. /// </summary> /// <param name="Image1">The first image.</param> /// <param name="Image2">The second image</param> /// <returns>The result of the operator.</returns> public static SwiftBitmap operator |(SwiftBitmap Image1, SwiftBitmap Image2) { Contract.Requires<ArgumentNullException>(Image1 != null, "Image1"); Contract.Requires<ArgumentNullException>(Image2 != null, "Image2"); Image1.Lock(); Image2.Lock(); var Result = new SwiftBitmap(Image1.Width, Image1.Height); Result.Lock(); Parallel.For(0, Result.Width, x => { for (int y = 0; y < Result.Height; ++y) { var Pixel1 = Image1.GetPixel(x, y); var Pixel2 = Image2.GetPixel(x, y); Result.SetPixel(x, y, Color.FromArgb(Pixel1.R | Pixel2.R, Pixel1.G | Pixel2.G, Pixel1.B | Pixel2.B)); } }); Image2.Unlock(); Image1.Unlock(); return Result.Unlock(); }