Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Windows.Forms;
- using System.Runtime.InteropServices;
- namespace LowLevelBitmapEdit
- {
- /// <summary>
- /// This static class accessing the given picture via its Scan0 ptr.
- /// <para />
- /// The normal access goes via:
- /// <para />
- /// <remarks>
- /// void Method(Bitmap bmp)<para />
- /// {<para />
- /// BitmapData bmpDat;<para />
- /// bmpDat = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);<para />
- /// unsafe<para />
- /// {<para />
- /// byte* picPtr = (byte*)bmpDat.Scan0;<para />
- /// int size = bmp.Height * bmp.Width;<para />
- /// for (int i = 0; i < size; i++)<para />
- /// {<para />
- /// //do some operations here<para />
- /// }<para />
- /// }<para />
- /// bmp.UnlockBits(bmpDat);<para />
- /// }<para />
- /// </remarks>
- /// </summary>
- public static class Filters
- {
- #region Manipulating Methods
- /// <summary>
- ///
- /// </summary>
- /// <param name="bmp"></param>
- public static void SetOnlyBlue(Bitmap bmp)
- {
- BitmapData bmpDat;
- byte blue;
- bmpDat = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
- unsafe
- {
- byte* picPtr = (byte*)bmpDat.Scan0;
- int size = (bmp.Height) * (bmp.Width);
- for (int i = 0; i < size; i++)
- {
- blue = picPtr[0];
- picPtr[0] = 0;
- picPtr += 4;
- }
- }
- bmp.UnlockBits(bmpDat);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="bmp"></param>
- public static void Invertion(Bitmap bmp)
- {
- BitmapData bmpDat;
- bmpDat = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- unsafe
- {
- byte* picPtr = (byte*)bmpDat.Scan0;
- int size = bmp.Height * bmp.Width * 4;
- for (int i = 0; i < size; i++)
- picPtr[i] = (byte)(255 - picPtr[i]);
- }
- bmp.UnlockBits(bmpDat);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="bmp"></param>
- public static void GreyScale(Bitmap bmp)
- {
- BitmapData bmpDat;
- bmpDat = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
- unsafe
- {
- byte* picPtr = (byte*)bmpDat.Scan0;
- int size = bmp.Height * bmp.Width;
- for (int i = 0; i < size; i++)
- {
- //getting the rgb colors/values
- byte blue = picPtr[0];
- byte green = picPtr[1];
- byte red = picPtr[2];
- //computing the grey colors:
- byte grey = (byte)((77 * blue + 151 * green + 28 * red) / 256);
- //write it back to the picture:
- picPtr[0] = picPtr[1] = picPtr[2] = grey;
- picPtr += 4;
- }
- }
- bmp.UnlockBits(bmpDat);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="bmp"></param>
- /// <param name="val"></param>
- public static void Brightness(Bitmap bmp, short val)
- {
- //at first we computes a so called Look-Up-Table (lut)
- //that makes sense for the performance by very large pictures.
- //because in this way we writes the picture bytes into an array,
- //and could simply accessing the needed bytes via this array.
- //here we go with our LUT:
- byte[] picBytes = new byte[256];
- for (int i = 0; i < 256; i++)
- {
- picBytes[i] = Norming(i + val);
- }
- BitmapData bmpDat;
- bmpDat = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
- unsafe
- {
- byte* picPtr = (byte*)bmpDat.Scan0;
- int size = bmp.Height * bmp.Width;
- for (int i = 0; i < size; i++)
- {
- //and now we simply get the values from our LUT:
- picPtr[0] = picBytes[picPtr[0]]; //blue
- picPtr[1] = picBytes[picPtr[1]]; //green
- picPtr[2] = picBytes[picPtr[2]]; //red
- //increment our ptr with 4;
- picPtr += 4;
- }
- }
- bmp.UnlockBits(bmpDat);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="bmp"></param>
- /// <param name="val"></param>
- public static void SetContrast(Bitmap bmp, float val)
- {
- byte[] picBytes = new byte[256];
- val = (1 + val / 100);
- //creating our LUT:
- for (int i = 0; i < 256; i++)
- {
- picBytes[i] = Norming((int)((i - 128) * val) + 128);
- }
- BitmapData bmpDat;
- bmpDat = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
- unsafe
- {
- byte* picPtr = (byte*)bmpDat.Scan0;
- int size = bmp.Height * bmp.Width;
- for (int i = 0; i < size; i++)
- {
- //and now we simply get the values from our LUT:
- picPtr[0] = picBytes[picPtr[0]]; //blue
- picPtr[1] = picBytes[picPtr[1]]; //green
- picPtr[2] = picBytes[picPtr[2]]; //red
- //increment our ptr with 4;
- picPtr += 4;
- }
- }
- bmp.UnlockBits(bmpDat);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="bmp"></param>
- /// <param name="val"></param>
- public static void SetGamma(Bitmap bmp, double val)
- {
- byte[] picBytes = new byte[256];
- for (int i = 0; i < 256; i++)
- {
- picBytes[i] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(i / 255.0, 1.0 / val)) + 0.5));
- }
- BitmapData bmpDat;
- bmpDat = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
- unsafe
- {
- byte* picPtr = (byte*)bmpDat.Scan0;
- int size = bmp.Height * bmp.Width;
- for (int i = 0; i < size; i++)
- {
- //and now we simply get the values from our LUT:
- picPtr[0] = picBytes[picPtr[0]]; //blue
- picPtr[1] = picBytes[picPtr[1]]; //green
- picPtr[2] = picBytes[picPtr[2]]; //red
- //increment our ptr with 4;
- picPtr += 4;
- }
- }
- bmp.UnlockBits(bmpDat);
- }
- /// <summary>
- /// This Method is needed to stretch the Histograph of a Picture.<para />
- /// This could be useful for Photos with a wrong exposure.
- /// </summary>
- /// <param name="bmp"></param>
- public static void AutoAdjustment(Bitmap bmp)
- {
- //this time we need a little bit more computations.
- //at first we start also with our LUT, but we need to compute every color-layer:
- int[,] picBytes = new int[256, 3];
- BitmapData bmpDat;
- bmpDat = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
- unsafe
- {
- byte* picPtr = (byte*)bmpDat.Scan0;
- int size = bmp.Height * bmp.Width;
- for (int i = 0; i < size; i++)
- {
- //no we create the histograph with our LUT,
- //and counting the given color/byte values
- picBytes[picPtr[0], 0]++; //blue layer
- picBytes[picPtr[1], 1]++; //green layer
- picBytes[picPtr[2], 2]++; //red layer
- picPtr += 4;
- }
- //here we have to compute every single color-channel:
- for (int colr = 0; colr < 3; colr++)
- {
- //determine whats the minimal and the maximal uses color value:
- //min:
- int i = 0;
- while (picBytes[i, colr] == 0)
- i++;
- int min = i;
- //max:
- i = 255;
- while (picBytes[i, colr] == 0)
- i--;
- int max = i;
- //compute the scale
- float scale = 255 / (float)(max - min);
- //getting the LUT for the specific color channel
- for (int k = 0; k < 244; k++)
- {
- picBytes[k, colr] = Norming((int)((k - min) * scale));
- }
- }
- //setting the ptr to the first byte:
- picPtr = (byte*)bmpDat.Scan0;
- //working on all color-channels via the LUT:
- for (int i = 0; i < size; i++)
- {
- //and now we simply get the values from our LUT:
- picPtr[0] = (byte)picBytes[picPtr[0], 0]; //blue
- picPtr[1] = (byte)picBytes[picPtr[1], 1]; //green
- picPtr[2] = (byte)picBytes[picPtr[2], 2]; //red
- //increment our ptr with 4;
- picPtr += 4;
- }
- }
- bmp.UnlockBits(bmpDat);
- }
- #region ShortedMethods
- /// <summary>
- ///
- /// </summary>
- /// <param name="bmp"></param>
- public static void GaussianSmoothing(Bitmap bmp)
- {
- GraphicFilter gf = new GraphicFilter();
- gf.Divider = 16;
- gf.ColorMatrix[0, 0] = 1;
- gf.ColorMatrix[1, 0] = 2;
- gf.ColorMatrix[2, 0] = 1;
- gf.ColorMatrix[0, 1] = 2;
- gf.ColorMatrix[1, 1] = 4;
- gf.ColorMatrix[2, 1] = 2;
- gf.ColorMatrix[0, 2] = 1;
- gf.ColorMatrix[1, 2] = 2;
- gf.ColorMatrix[2, 2] = 1;
- gf.Execution(bmp);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="bmp"></param>
- public static void Emboss(Bitmap bmp)
- {
- GraphicFilter gf = new GraphicFilter();
- gf.Divider = 1;
- gf.Offset = 127;
- gf.ColorMatrix[0, 0] = -1;
- gf.ColorMatrix[1, 0] = 0;
- gf.ColorMatrix[2, 0] = -1;
- gf.ColorMatrix[0, 1] = 0;
- gf.ColorMatrix[1, 1] = 4;
- gf.ColorMatrix[2, 1] = 0;
- gf.ColorMatrix[0, 2] = -1;
- gf.ColorMatrix[1, 2] = 0;
- gf.ColorMatrix[2, 2] = -1;
- gf.Execution(bmp);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="bmp"></param>
- public static void Smoothing(Bitmap bmp)
- {
- GraphicFilter gf = new GraphicFilter();
- gf.Divider = 8;
- gf.ColorMatrix[0, 0] = 1;
- gf.ColorMatrix[1, 0] = 1;
- gf.ColorMatrix[2, 0] = 1;
- gf.ColorMatrix[0, 1] = 1;
- gf.ColorMatrix[1, 1] = 1;
- gf.ColorMatrix[2, 1] = 1;
- gf.ColorMatrix[0, 2] = 1;
- gf.ColorMatrix[1, 2] = 1;
- gf.ColorMatrix[2, 2] = 1;
- gf.Execution(bmp);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="bmp"></param>
- public static void Sharpen(Bitmap bmp)
- {
- GraphicFilter gf = new GraphicFilter();
- gf.Divider = 3;
- gf.ColorMatrix[0, 0] = 0;
- gf.ColorMatrix[1, 0] = -2;
- gf.ColorMatrix[2, 0] = 0;
- gf.ColorMatrix[0, 1] = -2;
- gf.ColorMatrix[1, 1] = 11;
- gf.ColorMatrix[2, 1] = -2;
- gf.ColorMatrix[0, 2] = 0;
- gf.ColorMatrix[1, 2] = -2;
- gf.ColorMatrix[2, 2] = 0;
- gf.Execution(bmp);
- }
- #endregion
- #endregion
- #region helperMethod
- /// <summary>
- /// Ensures that the values got its correct/allowed values between 0 and 255.
- /// </summary>
- /// <param name="val"><see cref="System.Int32"/>.</param>
- /// <returns>A <see cref="System.Byte"/>.</returns>
- private static byte Norming(int val)
- {
- if (val < 0)
- return 0;
- if (val > 255)
- return 255;
- return (byte)val;
- }
- #endregion
- public static Bitmap MedianFilter(Bitmap Image, int Size)
- {
- Bitmap TempBitmap = Image;
- Bitmap NewBitmap = new Bitmap(TempBitmap.Width, TempBitmap.Height);
- Graphics NewGraphics = Graphics.FromImage(NewBitmap);
- NewGraphics.DrawImage(TempBitmap, new Rectangle(0, 0, TempBitmap.Width, TempBitmap.Height), new Rectangle(0, 0, TempBitmap.Width, TempBitmap.Height), GraphicsUnit.Pixel);
- NewGraphics.Dispose();
- Random TempRandom = new Random();
- int ApetureMin = -(Size / 2);
- int ApetureMax = (Size / 2);
- for (int x = 0; x < NewBitmap.Width; ++x)
- {
- for (int y = 0; y < NewBitmap.Height; ++y)
- {
- List<int> RValues = new List<int>();
- List<int> GValues = new List<int>();
- List<int> BValues = new List<int>();
- for (int x2 = ApetureMin; x2 < ApetureMax; ++x2)
- {
- int TempX = x + x2;
- if (TempX >= 0 && TempX < NewBitmap.Width)
- {
- for (int y2 = ApetureMin; y2 < ApetureMax; ++y2)
- {
- int TempY = y + y2;
- if (TempY >= 0 && TempY < NewBitmap.Height)
- {
- Color TempColor = TempBitmap.GetPixel(TempX, TempY);
- RValues.Add(TempColor.R);
- GValues.Add(TempColor.G);
- BValues.Add(TempColor.B);
- }
- }
- }
- }
- RValues.Sort();
- GValues.Sort();
- BValues.Sort();
- Color MedianPixel = Color.FromArgb( RValues[RValues.Count / 2],
- GValues[GValues.Count / 2],
- BValues[BValues.Count / 2]);
- NewBitmap.SetPixel(x, y, MedianPixel);
- }
- }
- return NewBitmap;
- }
- public static Bitmap MedianFilter(Bitmap bmp)
- {
- int Size = 2;
- List<byte> R = new List<byte>();
- List<byte> G = new List<byte>();
- List<byte> B = new List<byte>();
- int ApetureMin = -(Size / 2);
- int ApetureMax = (Size / 2);
- BitmapData imageData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
- unsafe
- {
- byte* start = (byte*)imageData.Scan0;
- for (int x = 0; x < imageData.Width; x++)
- {
- for (int y = 0; y < imageData.Height; y++)
- {
- for (int x1 = ApetureMin; x1 < ApetureMax; x1++)
- {
- int valx = x + x1;
- if (valx >= 0 && valx < imageData.Width)
- {
- for (int y1 = ApetureMin; y1 < ApetureMax; y1++)
- {
- int valy = y + y1;
- if (valy >= 0 && valy < imageData.Height)
- {
- // error come from here
- Color tempColor = bmp.GetPixel(valx, valy);
- R.Add(tempColor.R);
- G.Add(tempColor.G);
- B.Add(tempColor.B);
- }
- }
- }
- }
- }
- }
- R.Sort();
- G.Sort();
- B.Sort();
- }
- bmp.UnlockBits(imageData);
- return bmp;
- }
- }
- /// <summary>
- /// This Class helps us to encapsulates and to compute the nearly same actions.
- /// </summary>
- public class GraphicFilter
- {
- /// <summary>
- ///
- /// </summary>
- public int[,] ColorMatrix = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
- /// <summary>
- ///
- /// </summary>
- public int Divider = 0;
- /// <summary>
- ///
- /// </summary>
- public int Offset = 0;
- /// <summary>
- /// Ensures that the values got its correct/allowed values between 0 and 255.
- /// </summary>
- /// <param name="val"><see cref="System.Int32"/>.</param>
- /// <returns>A <see cref="System.Byte"/>.</returns>
- private byte Norming(int val)
- {
- if (val < 0)
- return 0;
- if (val > 255)
- return 255;
- return (byte)val;
- }
- /// <summary>
- /// This Method represents all the actions we have to do by manipulating Bitmaps.
- /// </summary>
- /// <param name="bmp"></param>
- public void Execution(Bitmap bmp)
- {
- //create a copy of the bmp:
- Bitmap bmpSource = (Bitmap)bmp.Clone();
- BitmapData bmpSourceDat = bmpSource.LockBits(new Rectangle(0, 0, bmpSource.Width, bmpSource.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
- BitmapData bmpDestinationDat = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
- unsafe
- {
- byte* pByte = (byte*)bmpDestinationDat.Scan0 + bmp.Width * 4 + 4;
- byte* pLine0 = (byte*)bmpSourceDat.Scan0;
- byte* pLine1 = (byte*)bmpSourceDat.Scan0 + bmp.Width * 4;
- byte* pLine2 = (byte*)bmpSourceDat.Scan0 + bmp.Width * 8;
- int size = (bmp.Width - 2) * (bmp.Height - 2);
- for (int i = 0; i < size; i++)
- {
- pByte[0] = Norming((((pLine0[0] * ColorMatrix[0, 0]) + (pLine0[4] * ColorMatrix[1, 0]) + (pLine0[8] * ColorMatrix[2, 0]) +
- (pLine1[0] * ColorMatrix[0, 1]) + (pLine1[4] * ColorMatrix[1, 1]) + (pLine1[8] * ColorMatrix[2, 1]) +
- (pLine2[0] * ColorMatrix[0, 2]) + (pLine2[4] * ColorMatrix[1, 2]) + (pLine2[8] * ColorMatrix[2, 2])) / Divider) + Offset);
- pByte[1] = Norming((((pLine0[1] * ColorMatrix[0, 0]) + (pLine0[5] * ColorMatrix[1, 0]) + (pLine0[9] * ColorMatrix[2, 0]) +
- (pLine1[1] * ColorMatrix[0, 1]) + (pLine1[5] * ColorMatrix[1, 1]) + (pLine1[9] * ColorMatrix[2, 1]) +
- (pLine2[1] * ColorMatrix[0, 2]) + (pLine2[5] * ColorMatrix[1, 2]) + (pLine2[9] * ColorMatrix[2, 2])) / Divider) + Offset);
- pByte[2] = Norming((((pLine0[2] * ColorMatrix[0, 0]) + (pLine0[6] * ColorMatrix[1, 0]) + (pLine0[10] * ColorMatrix[2, 0]) +
- (pLine1[2] * ColorMatrix[0, 1]) + (pLine1[6] * ColorMatrix[1, 1]) + (pLine1[10] * ColorMatrix[2, 1]) +
- (pLine2[2] * ColorMatrix[0, 2]) + (pLine2[6] * ColorMatrix[1, 2]) + (pLine2[10] * ColorMatrix[2, 2])) / Divider) + Offset);
- pByte += 4;
- pLine0 += 4;
- pLine1 += 4;
- pLine2 += 4;
- }
- }
- bmp.UnlockBits(bmpDestinationDat);
- bmpSource.UnlockBits(bmpSourceDat);
- bmpSource.Dispose();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement