BitmapFilter.cs
Description du code
BitmapFilter.cs est un fichier du projet PhotoBrol.Ce fichier est situé dans /var/www/bin/sniplets/bibliobrol/photobrol/.
Projet PhotoBrol :
Editeur d'images en CSharp.
Code source ou contenu du fichier
Code c# (BitmapFilter.cs) (1529 lignes)
using System; using System.Drawing; using System.Drawing.Imaging; namespace be.gaudry.photobrol.model.filters { public class BitmapFilter { public const short EDGE_DETECT_KIRSH = 1; public const short EDGE_DETECT_PREWITT = 2; public const short EDGE_DETECT_SOBEL = 3; public static bool Invert(Bitmap b) { // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; int nOffset = stride - b.Width*3; int nWidth = b.Width * 3; for(int y=0;y<b.Height;++y) { for(int x=0; x < nWidth; ++x ) { p[0] = (byte)(255-p[0]); ++p; } p += nOffset; } } b.UnlockBits(bmData); return true; } public static bool GrayScale(Bitmap b) { // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int remain = bmpData.Stride - bmpData.Width * 3; unsafe { byte* ptr = (byte*)bmpData.Scan0; byte t; for (int i = 0; i < bmpData.Height; i++) { for (int j = 0; j < bmpData.Width; j++) { //t = (byte)(0.333 * ptr[2] + 0.333 * ptr[1] + 0.334 * ptr[0]); t = (byte)(.299 * ptr[2] + .587 * ptr[1] + .114 * ptr[0]); ptr[2] = t; ptr[1] = t; ptr[0] = t; ptr += 3; } ptr += remain; } } b.UnlockBits(bmpData); return true; } public static bool Brightness(Bitmap b, int nBrightness) { if (nBrightness < -255 || nBrightness > 255) return false; // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; int nVal = 0; unsafe { byte * p = (byte *)(void *)Scan0; int nOffset = stride - b.Width*3; int nWidth = b.Width * 3; for(int y=0;y<b.Height;++y) { for(int x=0; x < nWidth; ++x ) { nVal = (int) (p[0] + nBrightness); if (nVal < 0) nVal = 0; if (nVal > 255) nVal = 255; p[0] = (byte)nVal; ++p; } p += nOffset; } } b.UnlockBits(bmData); return true; } public static bool Contrast(Bitmap b, sbyte nContrast) { if (nContrast < -100) return false; if (nContrast > 100) return false; double pixel = 0, contrast = (100.0+nContrast)/100.0; contrast *= contrast; int red, green, blue; // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; int nOffset = stride - b.Width*3; for(int y=0;y<b.Height;++y) { for(int x=0; x < b.Width; ++x ) { blue = p[0]; green = p[1]; red = p[2]; pixel = red/255.0; pixel -= 0.5; pixel *= contrast; pixel += 0.5; pixel *= 255; if (pixel < 0) pixel = 0; if (pixel > 255) pixel = 255; p[2] = (byte) pixel; pixel = green/255.0; pixel -= 0.5; pixel *= contrast; pixel += 0.5; pixel *= 255; if (pixel < 0) pixel = 0; if (pixel > 255) pixel = 255; p[1] = (byte) pixel; pixel = blue/255.0; pixel -= 0.5; pixel *= contrast; pixel += 0.5; pixel *= 255; if (pixel < 0) pixel = 0; if (pixel > 255) pixel = 255; p[0] = (byte) pixel; p += 3; } p += nOffset; } } b.UnlockBits(bmData); return true; } public static bool Gamma(Bitmap b, double red, double green, double blue) { if (red < .2 || red > 5) return false; if (green < .2 || green > 5) return false; if (blue < .2 || blue > 5) return false; for (int i = 0; i< 256; ++i) { redGamma[i] = (byte)Math.Min(255, (int)(( 255.0 * Math.Pow(i/255.0, 1.0/red)) + 0.5)); greenGamma[i] = (byte)Math.Min(255, (int)(( 255.0 * Math.Pow(i/255.0, 1.0/green)) + 0.5)); blueGamma[i] = (byte)Math.Min(255, (int)(( 255.0 * Math.Pow(i/255.0, 1.0/blue)) + 0.5)); } // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; int nOffset = stride - b.Width*3; for(int y=0;y<b.Height;++y) { for(int x=0; x < b.Width; ++x ) { p[2] = redGamma[ p[2] ]; p[1] = greenGamma[ p[1] ]; p[0] = blueGamma[ p[0] ]; p += 3; } p += nOffset; } } b.UnlockBits(bmData); return true; } public static bool ColorAvgLum(Bitmap b, int red, int green, int blue) { if (red < -255 || red > 255) return false; if (green < -255 || green > 255) return false; if (blue < -255 || blue > 255) return false; // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int remain = bmpData.Stride - bmpData.Width * 3; unsafe { byte* ptr = (byte*)bmpData.Scan0; byte temp, t; byte avg = (byte)((red + green + blue) / 3); ; for (int i = 0; i < bmpData.Height; i++) { for (int j = 0; j < bmpData.Width; j++) { //t = (byte)(0.333 * ptr[2] + 0.333 * ptr[1] + 0.334 * ptr[0]); temp = (byte)(.299 * ptr[2] + .587 * ptr[1] + .114 * ptr[0]); t = (temp - avg > 0) ? (byte)(temp - avg) : (byte)0; ptr[2] = ((byte)(((t + red) > 255) ? 255 : t + red)); ptr[1] = ((byte)(((t + green) > 255) ? 255 : t + green)); ptr[0] = ((byte)(((t + blue) > 255) ? 255 : t + blue)); ptr += 3; } ptr += remain; } } b.UnlockBits(bmpData); return true; } public static bool colorFast(Bitmap b, int red, int green, int blue) { if (red < -255 || red > 255) return false; if (green < -255 || green > 255) return false; if (blue < -255 || blue > 255) return false; // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int remain = bmpData.Stride - bmpData.Width * 3; unsafe { byte* ptr = (byte*)bmpData.Scan0; byte t; for (int i = 0; i < bmpData.Height; i++) { for (int j = 0; j < bmpData.Width; j++) { //t = (byte)(0.333 * ptr[2] + 0.333 * ptr[1] + 0.334 * ptr[0]); t = (byte)(.299 * ptr[2] + .587 * ptr[1] + .114 * ptr[0]); ptr[2] = ((byte)(((t + red) > 255) ? 255 : t + red)); ptr[1] = ((byte)(((t + green) > 255) ? 255 : t + green)); ptr[0] = ((byte)(((t + blue) > 255) ? 255 : t + blue)); ptr += 3; } ptr += remain; } } b.UnlockBits(bmpData); return true; } public static bool Conv3x3(Bitmap b, ConvMatrix m) { // Avoid divide by zero errors if (0 == m.Factor) return false; Bitmap bSrc = (Bitmap)b.Clone(); // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; int stride2 = stride * 2; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr SrcScan0 = bmSrc.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; byte * pSrc = (byte *)(void *)SrcScan0; int nOffset = stride - b.Width*3; int nWidth = b.Width - 2; int nHeight = b.Height - 2; int nPixel; for(int y=0;y < nHeight;++y) { for(int x=0; x < nWidth; ++x ) { nPixel = ( ( ( (pSrc[2] * m.TopLeft) + (pSrc[5] * m.TopMid) + (pSrc[8] * m.TopRight) + (pSrc[2 + stride] * m.MidLeft) + (pSrc[5 + stride] * m.Pixel) + (pSrc[8 + stride] * m.MidRight) + (pSrc[2 + stride2] * m.BottomLeft) + (pSrc[5 + stride2] * m.BottomMid) + (pSrc[8 + stride2] * m.BottomRight)) / m.Factor) + m.Offset); if (nPixel < 0) nPixel = 0; if (nPixel > 255) nPixel = 255; p[5 + stride]= (byte)nPixel; nPixel = ( ( ( (pSrc[1] * m.TopLeft) + (pSrc[4] * m.TopMid) + (pSrc[7] * m.TopRight) + (pSrc[1 + stride] * m.MidLeft) + (pSrc[4 + stride] * m.Pixel) + (pSrc[7 + stride] * m.MidRight) + (pSrc[1 + stride2] * m.BottomLeft) + (pSrc[4 + stride2] * m.BottomMid) + (pSrc[7 + stride2] * m.BottomRight)) / m.Factor) + m.Offset); if (nPixel < 0) nPixel = 0; if (nPixel > 255) nPixel = 255; p[4 + stride] = (byte)nPixel; nPixel = ( ( ( (pSrc[0] * m.TopLeft) + (pSrc[3] * m.TopMid) + (pSrc[6] * m.TopRight) + (pSrc[0 + stride] * m.MidLeft) + (pSrc[3 + stride] * m.Pixel) + (pSrc[6 + stride] * m.MidRight) + (pSrc[0 + stride2] * m.BottomLeft) + (pSrc[3 + stride2] * m.BottomMid) + (pSrc[6 + stride2] * m.BottomRight)) / m.Factor) + m.Offset); if (nPixel < 0) nPixel = 0; if (nPixel > 255) nPixel = 255; p[3 + stride] = (byte)nPixel; p += 3; pSrc += 3; } p += nOffset; pSrc += nOffset; } } b.UnlockBits(bmData); bSrc.UnlockBits(bmSrc); return true; } public static bool Smooth(Bitmap b, int nWeight /* default to 1 */) { m.SetAll(1); m.Pixel = nWeight; m.Factor = nWeight + 8; return BitmapFilter.Conv3x3(b, m); } public static bool GaussianBlur(Bitmap b, int nWeight /* default to 4*/) { m.SetAll(1); m.Pixel = nWeight; m.TopMid = m.MidLeft = m.MidRight = m.BottomMid = 2; m.Factor = nWeight + 12; return BitmapFilter.Conv3x3(b, m); } public static bool MeanRemoval(Bitmap b, int nWeight /* default to 9*/ ) { m.SetAll(-1); m.Pixel = nWeight; m.Factor = nWeight - 8; return BitmapFilter.Conv3x3(b, m); } public static bool Sharpen(Bitmap b, int nWeight /* default to 11*/ ) { m.SetAll(0); m.Pixel = nWeight; m.TopMid = m.MidLeft = m.MidRight = m.BottomMid = -2; m.Factor = nWeight - 8; return BitmapFilter.Conv3x3(b, m); } public static bool EmbossLaplacian(Bitmap b) { m.SetAll(-1); m.TopMid = m.MidLeft = m.MidRight = m.BottomMid = 0; m.Pixel = 4; m.Offset = 127; return BitmapFilter.Conv3x3(b, m); } public static bool EdgeDetectQuick(Bitmap b) { m.TopLeft = m.TopMid = m.TopRight = -1; m.MidLeft = m.Pixel = m.MidRight = 0; m.BottomLeft = m.BottomMid = m.BottomRight = 1; m.Offset = 127; return BitmapFilter.Conv3x3(b, m); } public static bool EdgeDetectConvolution(Bitmap b, short nType, byte nThreshold) { // I need to make a copy of this bitmap BEFORE I alter it 80) Bitmap bTemp = (Bitmap)b.Clone(); switch (nType) { case EDGE_DETECT_SOBEL: m.SetAll(0); m.TopLeft = m.BottomLeft = 1; m.TopRight = m.BottomRight = -1; m.MidLeft = 2; m.MidRight = -2; m.Offset = 0; break; case EDGE_DETECT_PREWITT: m.SetAll(0); m.TopLeft = m.MidLeft = m.BottomLeft = -1; m.TopRight = m.MidRight = m.BottomRight = 1; m.Offset = 0; break; case EDGE_DETECT_KIRSH: m.SetAll(-3); m.Pixel = 0; m.TopLeft = m.MidLeft = m.BottomLeft = 5; m.Offset = 0; break; } BitmapFilter.Conv3x3(b, m); switch (nType) { case EDGE_DETECT_SOBEL: m.SetAll(0); m.TopLeft = m.TopRight = 1; m.BottomLeft = m.BottomRight = -1; m.TopMid = 2; m.BottomMid = -2; m.Offset = 0; break; case EDGE_DETECT_PREWITT: m.SetAll(0); m.BottomLeft = m.BottomMid = m.BottomRight = -1; m.TopLeft = m.TopMid = m.TopRight = 1; m.Offset = 0; break; case EDGE_DETECT_KIRSH: m.SetAll(-3); m.Pixel = 0; m.BottomLeft = m.BottomMid = m.BottomRight = 5; m.Offset = 0; break; } BitmapFilter.Conv3x3(bTemp, m); // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmData2 = bTemp.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr Scan02 = bmData2.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; byte * p2 = (byte *)(void *)Scan02; int nOffset = stride - b.Width*3; int nWidth = b.Width * 3; int nPixel = 0; for(int y=0;y<b.Height;++y) { for(int x=0; x < nWidth; ++x ) { nPixel = (int) Math.Sqrt((p[0]*p[0]) + (p2[0] * p2[0])); if (nPixel<nThreshold)nPixel = nThreshold; if (nPixel>255) nPixel = 255; p[0] = (byte) nPixel; ++p; ++p2; } p += nOffset; p2 += nOffset; } } b.UnlockBits(bmData); bTemp.UnlockBits(bmData2); return true; } public static bool EdgeDetectHorizontal(Bitmap b) { Bitmap bmTemp = (Bitmap)b.Clone(); // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmData2 = bmTemp.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr Scan02 = bmData2.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; byte * p2 = (byte *)(void *)Scan02; int nOffset = stride - b.Width*3; int nWidth = b.Width * 3; int nPixel = 0; p += stride; p2 += stride; for(int y=1;y<b.Height-1;++y) { p += 9; p2 += 9; for(int x=9; x < nWidth-9; ++x ) { nPixel = ((p2 + stride - 9)[0] + (p2 + stride - 6)[0] + (p2 + stride - 3)[0] + (p2 + stride)[0] + (p2 + stride + 3)[0] + (p2 + stride + 6)[0] + (p2 + stride + 9)[0] - (p2 - stride - 9)[0] - (p2 - stride - 6)[0] - (p2 - stride - 3)[0] - (p2 - stride)[0] - (p2 - stride + 3)[0] - (p2 - stride + 6)[0] - (p2 - stride + 9)[0]); if (nPixel < 0) nPixel = 0; if (nPixel > 255) nPixel = 255; (p+stride)[0] = (byte) nPixel; ++ p; ++ p2; } p += 9 + nOffset; p2 += 9 + nOffset; } } b.UnlockBits(bmData); bmTemp.UnlockBits(bmData2); return true; } public static bool EdgeDetectVertical(Bitmap b) { Bitmap bmTemp = (Bitmap)b.Clone(); // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmData2 = bmTemp.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr Scan02 = bmData2.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; byte * p2 = (byte *)(void *)Scan02; int nOffset = stride - b.Width*3; int nWidth = b.Width * 3; int nPixel = 0; int nStride2 = stride *2; int nStride3 = stride * 3; p += nStride3; p2 += nStride3; for(int y=3;y<b.Height-3;++y) { p += 3; p2 += 3; for(int x=3; x < nWidth-3; ++x ) { nPixel = ((p2 + nStride3 + 3)[0] + (p2 + nStride2 + 3)[0] + (p2 + stride + 3)[0] + (p2 + 3)[0] + (p2 - stride + 3)[0] + (p2 - nStride2 + 3)[0] + (p2 - nStride3 + 3)[0] - (p2 + nStride3 - 3)[0] - (p2 + nStride2 - 3)[0] - (p2 + stride - 3)[0] - (p2 - 3)[0] - (p2 - stride - 3)[0] - (p2 - nStride2 - 3)[0] - (p2 - nStride3 - 3)[0]); if (nPixel < 0) nPixel = 0; if (nPixel > 255) nPixel = 255; p[0] = (byte) nPixel; ++ p; ++ p2; } p += 3 + nOffset; p2 += 3 + nOffset; } } b.UnlockBits(bmData); bmTemp.UnlockBits(bmData2); return true; } public static bool EdgeDetectHomogenity(Bitmap b, byte nThreshold) { // This one works by working out the greatest difference between a pixel and it's eight neighbours. // The threshold allows softer edges to be forced down to black, use 0 to negate it's effect. Bitmap b2 = (Bitmap) b.Clone(); // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmData2 = b2.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr Scan02 = bmData2.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; byte * p2 = (byte *)(void *)Scan02; int nOffset = stride - b.Width*3; int nWidth = b.Width * 3; int nPixel = 0, nPixelMax = 0; p += stride; p2 += stride; for(int y=1;y<b.Height-1;++y) { p += 3; p2 += 3; for(int x=3; x < nWidth-3; ++x ) { nPixelMax = Math.Abs(p2[0] - (p2+stride-3)[0]); nPixel = Math.Abs(p2[0] - (p2 + stride)[0]); if (nPixel>nPixelMax) nPixelMax = nPixel; nPixel = Math.Abs(p2[0] - (p2 + stride + 3)[0]); if (nPixel>nPixelMax) nPixelMax = nPixel; nPixel = Math.Abs(p2[0] - (p2 - stride)[0]); if (nPixel>nPixelMax) nPixelMax = nPixel; nPixel = Math.Abs(p2[0] - (p2 + stride)[0]); if (nPixel>nPixelMax) nPixelMax = nPixel; nPixel = Math.Abs(p2[0] - (p2 - stride - 3)[0]); if (nPixel>nPixelMax) nPixelMax = nPixel; nPixel = Math.Abs(p2[0] - (p2 - stride)[0]); if (nPixel>nPixelMax) nPixelMax = nPixel; nPixel = Math.Abs(p2[0] - (p2 - stride + 3)[0]); if (nPixel>nPixelMax) nPixelMax = nPixel; if (nPixelMax < nThreshold) nPixelMax = 0; p[0] = (byte) nPixelMax; ++ p; ++ p2; } p += 3 + nOffset; p2 += 3 + nOffset; } } b.UnlockBits(bmData); b2.UnlockBits(bmData2); return true; } public static bool EdgeDetectDifference(Bitmap b, byte nThreshold) { // This one works by working out the greatest difference between a pixel and it's eight neighbours. // The threshold allows softer edges to be forced down to black, use 0 to negate it's effect. Bitmap b2 = (Bitmap) b.Clone(); // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmData2 = b2.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr Scan02 = bmData2.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; byte * p2 = (byte *)(void *)Scan02; int nOffset = stride - b.Width*3; int nWidth = b.Width * 3; int nPixel = 0, nPixelMax = 0; p += stride; p2 += stride; for(int y=1;y<b.Height-1;++y) { p += 3; p2 += 3; for(int x=3; x < nWidth-3; ++x ) { nPixelMax = Math.Abs((p2 - stride + 3)[0] - (p2+stride-3)[0]); nPixel = Math.Abs((p2 + stride + 3)[0] - (p2 - stride - 3)[0]); if (nPixel>nPixelMax) nPixelMax = nPixel; nPixel = Math.Abs((p2 - stride)[0] - (p2 + stride)[0]); if (nPixel>nPixelMax) nPixelMax = nPixel; nPixel = Math.Abs((p2+3)[0] - (p2 - 3)[0]); if (nPixel>nPixelMax) nPixelMax = nPixel; if (nPixelMax < nThreshold) nPixelMax = 0; p[0] = (byte) nPixelMax; ++ p; ++ p2; } p += 3 + nOffset; p2 += 3 + nOffset; } } b.UnlockBits(bmData); b2.UnlockBits(bmData2); return true; } public static bool EdgeEnhance(Bitmap b, byte nThreshold) { // This one works by working out the greatest difference between a nPixel and it's eight neighbours. // The threshold allows softer edges to be forced down to black, use 0 to negate it's effect. Bitmap b2 = (Bitmap) b.Clone(); // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmData2 = b2.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr Scan02 = bmData2.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; byte * p2 = (byte *)(void *)Scan02; int nOffset = stride - b.Width*3; int nWidth = b.Width * 3; int nPixel = 0, nPixelMax = 0; p += stride; p2 += stride; for (int y = 1; y < b.Height-1; ++y) { p += 3; p2 += 3; for (int x = 3; x < nWidth-3; ++x) { nPixelMax = Math.Abs((p2 - stride + 3)[0] - (p2 + stride - 3)[0]); nPixel = Math.Abs((p2 + stride + 3)[0] - (p2 - stride - 3)[0]); if (nPixel > nPixelMax) nPixelMax = nPixel; nPixel = Math.Abs((p2 - stride)[0] - (p2 + stride)[0]); if (nPixel > nPixelMax) nPixelMax = nPixel; nPixel = Math.Abs((p2 + 3)[0] - (p2 - 3)[0]); if (nPixel > nPixelMax) nPixelMax = nPixel; if (nPixelMax > nThreshold && nPixelMax > p[0]) p[0] = (byte) Math.Max(p[0], nPixelMax); ++ p; ++ p2; } p += nOffset + 3; p2 += nOffset + 3; } } b.UnlockBits(bmData); b2.UnlockBits(bmData2); return true; } public static Bitmap Resize(Bitmap b, int nWidth, int nHeight, bool bBilinear) { Bitmap bTemp = (Bitmap)b.Clone(); double nXFactor = (double)bTemp.Width/(double)nWidth; double nYFactor = (double)bTemp.Height/(double)nHeight; if (bBilinear) { double fraction_x, fraction_y, one_minus_x, one_minus_y; int ceil_x, ceil_y, floor_x, floor_y; byte red, green, blue; byte b1, b2; for (int x = 0; x < b.Width; ++x) for (int y = 0; y < b.Height; ++y) { // Setup floor_x = (int)Math.Floor(x * nXFactor); floor_y = (int)Math.Floor(y * nYFactor); ceil_x = floor_x + 1; if (ceil_x >= bTemp.Width) ceil_x = floor_x; ceil_y = floor_y + 1; if (ceil_y >= bTemp.Height) ceil_y = floor_y; fraction_x = x * nXFactor - floor_x; fraction_y = y * nYFactor - floor_y; one_minus_x = 1.0 - fraction_x; one_minus_y = 1.0 - fraction_y; c1 = bTemp.GetPixel(floor_x, floor_y); c2 = bTemp.GetPixel(ceil_x, floor_y); c3 = bTemp.GetPixel(floor_x, ceil_y); c4 = bTemp.GetPixel(ceil_x, ceil_y); // Blue b1 = (byte)(one_minus_x * c1.B + fraction_x * c2.B); b2 = (byte)(one_minus_x * c3.B + fraction_x * c4.B); blue = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2)); // Green b1 = (byte)(one_minus_x * c1.G + fraction_x * c2.G); b2 = (byte)(one_minus_x * c3.G + fraction_x * c4.G); green = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2)); // Red b1 = (byte)(one_minus_x * c1.R + fraction_x * c2.R); b2 = (byte)(one_minus_x * c3.R + fraction_x * c4.R); red = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2)); b.SetPixel(x,y, System.Drawing.Color.FromArgb(255, red, green, blue)); } } else { for (int x = 0; x < b.Width; ++x) for (int y = 0; y < b.Height; ++y) b.SetPixel(x, y, bTemp.GetPixel((int)(Math.Floor(x * nXFactor)),(int)(Math.Floor(y * nYFactor)))); } return b; } public static bool OffsetFilterAbs(Bitmap b, Point[,] offset ) { Bitmap bSrc = (Bitmap)b.Clone(); // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int scanline = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr SrcScan0 = bmSrc.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; byte * pSrc = (byte *)(void *)SrcScan0; int nOffset = bmData.Stride - b.Width*3; int nWidth = b.Width; int nHeight = b.Height; int xOffset, yOffset; for(int y=0;y < nHeight;++y) { for(int x=0; x < nWidth; ++x ) { xOffset = offset[x,y].X; yOffset = offset[x,y].Y; if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth) { p[0] = pSrc[(yOffset * scanline) + (xOffset * 3)]; p[1] = pSrc[(yOffset * scanline) + (xOffset * 3) + 1]; p[2] = pSrc[(yOffset * scanline) + (xOffset * 3) + 2]; } p += 3; } p += nOffset; } } b.UnlockBits(bmData); bSrc.UnlockBits(bmSrc); return true; } public static bool OffsetFilter(Bitmap b, Point[,] offset ) { Bitmap bSrc = (Bitmap)b.Clone(); // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int scanline = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr SrcScan0 = bmSrc.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; byte * pSrc = (byte *)(void *)SrcScan0; int nOffset = bmData.Stride - b.Width*3; int nWidth = b.Width; int nHeight = b.Height; int xOffset, yOffset; for(int y=0;y < nHeight;++y) { for(int x=0; x < nWidth; ++x ) { xOffset = offset[x,y].X; yOffset = offset[x,y].Y; if (y+yOffset >= 0 && y+yOffset < nHeight && x+xOffset >= 0 && x+xOffset < nWidth) { p[0] = pSrc[((y+yOffset) * scanline) + ((x+xOffset) * 3)]; p[1] = pSrc[((y+yOffset) * scanline) + ((x+xOffset) * 3) + 1]; p[2] = pSrc[((y+yOffset) * scanline) + ((x+xOffset) * 3) + 2]; } p += 3; } p += nOffset; } } b.UnlockBits(bmData); bSrc.UnlockBits(bmSrc); return true; } public static bool OffsetFilterAntiAlias(Bitmap b, FloatPoint[,] fp) { Bitmap bSrc = (Bitmap)b.Clone(); // !! Don't forget GDI+ uses BGR format and nor RGB !!! BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int scanline = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr SrcScan0 = bmSrc.Scan0; unsafe { byte * p = (byte *)(void *)Scan0; byte * pSrc = (byte *)(void *)SrcScan0; int nOffset = bmData.Stride - b.Width*3; int nWidth = b.Width; int nHeight = b.Height; double xOffset, yOffset; double fraction_x, fraction_y, one_minus_x, one_minus_y; int ceil_x, ceil_y, floor_x, floor_y; Byte p1, p2; for(int y=0;y < nHeight;++y) { for(int x=0; x < nWidth; ++x ) { xOffset = fp[x,y].X; yOffset = fp[x,y].Y; // Setup floor_x = (int)Math.Floor(xOffset); floor_y = (int)Math.Floor(yOffset); ceil_x = floor_x + 1; ceil_y = floor_y + 1; fraction_x = xOffset - floor_x; fraction_y = yOffset - floor_y; one_minus_x = 1.0 - fraction_x; one_minus_y = 1.0 - fraction_y; if (floor_y >= 0 && ceil_y < nHeight && floor_x >= 0 && ceil_x < nWidth) { // Blue p1 = (Byte)(one_minus_x * (double)(pSrc[floor_y * scanline + floor_x * 3]) + fraction_x * (double)(pSrc[floor_y * scanline + ceil_x * 3])); p2 = (Byte)(one_minus_x * (double)(pSrc[ceil_y * scanline + floor_x * 3]) + fraction_x * (double)(pSrc[ceil_y * scanline + 3 * ceil_x])); p[x * 3 + y*scanline] = (Byte)(one_minus_y * (double)(p1) + fraction_y * (double)(p2)); // Green p1 = (Byte)(one_minus_x * (double)(pSrc[floor_y * scanline + floor_x * 3 + 1]) + fraction_x * (double)(pSrc[floor_y * scanline + ceil_x * 3 + 1])); p2 = (Byte)(one_minus_x * (double)(pSrc[ceil_y * scanline + floor_x * 3 + 1]) + fraction_x * (double)(pSrc[ceil_y * scanline + 3 * ceil_x + 1])); p[x * 3 + y*scanline + 1] = (Byte)(one_minus_y * (double)(p1) + fraction_y * (double)(p2)); // Red p1 = (Byte)(one_minus_x * (double)(pSrc[floor_y * scanline + floor_x * 3 + 2]) + fraction_x * (double)(pSrc[floor_y * scanline + ceil_x * 3 + 2])); p2 = (Byte)(one_minus_x * (double)(pSrc[ceil_y * scanline + floor_x * 3 + 2]) + fraction_x * (double)(pSrc[ceil_y * scanline + 3 * ceil_x + 2])); p[x * 3 + y*scanline + 2] = (Byte)(one_minus_y * (double)(p1) + fraction_y * (double)(p2)); } } } } b.UnlockBits(bmData); bSrc.UnlockBits(bmSrc); return true; } public static bool Flip(Bitmap b, bool bHorz, bool bVert) { int nWidth = b.Width; int nHeight = b.Height; for (int x = 0; x < nWidth; ++x) for (int y = 0; y < nHeight; ++y) { ptFlip[x, y].X = (bHorz) ? nWidth - (x+1) : x; ptFlip[x,y].Y = (bVert) ? nHeight - (y + 1) : y; } OffsetFilterAbs(b, ptFlip); return true; } public static bool RandomJitter(Bitmap b, short nDegree) { int nWidth = b.Width; int nHeight = b.Height; int newX, newY; short nHalf = (short)Math.Floor((double)nDegree/2); for (int x = 0; x < nWidth; ++x) for (int y = 0; y < nHeight; ++y) { newX = rnd.Next(nDegree) - nHalf; if (x + newX > 0 && x + newX < nWidth) ptRandJitter[x, y].X = newX; else ptRandJitter[x, y].X = 0; newY = rnd.Next(nDegree) - nHalf; if (y + newY > 0 && y + newY < nWidth) ptRandJitter[x, y].Y = newY; else ptRandJitter[x, y].Y = 0; } OffsetFilter(b, ptRandJitter); return true; } public static bool Swirl(Bitmap b, double fDegree, bool bSmoothing /* default fDegree to .05 */) { int nWidth = b.Width; int nHeight = b.Height; mid.X = nWidth/2; mid.Y = nHeight/2; double theta, radius; double newX, newY; for (int x = 0; x < nWidth; ++x) for (int y = 0; y < nHeight; ++y) { int trueX = x - mid.X; int trueY = y - mid.Y; theta = Math.Atan2((trueY),(trueX)); radius = Math.Sqrt(trueX*trueX + trueY*trueY); newX = mid.X + (radius * Math.Cos(theta + fDegree * radius)); if (newX > 0 && newX < nWidth) { fp[x, y].X = newX; pt[x, y].X = (int)newX; } else fp[x, y].X = pt[x, y].X = x; newY = mid.Y + (radius * Math.Sin(theta + fDegree * radius)); if (newY > 0 && newY < nHeight) { fp[x, y].Y = newY; pt[x, y].Y = (int)newY; } else fp[x, y].Y = pt[x, y].Y = y; } if(bSmoothing) OffsetFilterAntiAlias(b, fp); else OffsetFilterAbs(b, pt); return true; } public static bool Sphere(Bitmap b, bool bSmoothing, int displacement, int expand) { int nWidth = b.Width; int nHeight = b.Height; mid.X = nWidth / 2; mid.Y = nHeight / 2; double theta, radius; double newX, newY; for (int x = 0; x < nWidth; ++x) for (int y = 0; y < nHeight; ++y) { int trueX = x - mid.X; int trueY = y - mid.Y; theta = Math.Atan2((trueY), (trueX)); radius = Math.Sqrt(trueX*trueX + trueY*trueY); double newRadius = radius * radius/(Math.Max(mid.X, mid.Y)); newX = mid.X + (newRadius * Math.Cos(theta)) + displacement; if (newX > 0 && newX < nWidth) { fp[x, y].X = newX; pt[x, y].X = (int) newX; } else { fp[x, y].X = fp[x,y].Y = 0.0; pt[x, y].X = pt[x,y].Y = 0; } newY = mid.Y + (newRadius * Math.Sin(theta)) + expand; if (newY > 0 && newY < nHeight && newX > 0 && newX < nWidth) { fp[x, y].Y = newY; pt[x, y].Y = (int) newY; } else { fp[x, y].X = fp[x,y].Y = 0.0; pt[x, y].X = pt[x,y].Y = 0; } } if(bSmoothing) OffsetFilterAbs(b, pt); else OffsetFilterAntiAlias(b, fp); return true; } public static bool TimeWarp(Bitmap b, Byte factor, bool bSmoothing) { int nWidth = b.Width; int nHeight = b.Height; mid.X = nWidth/2; mid.Y = nHeight/2; double theta, radius; double newX, newY; for (int x = 0; x < nWidth; ++x) for (int y = 0; y < nHeight; ++y) { int trueX = x - mid.X; int trueY = y - mid.Y; theta = Math.Atan2((trueY),(trueX)); radius = Math.Sqrt(trueX*trueX + trueY*trueY); double newRadius = Math.Sqrt(radius) * factor; newX = mid.X + (newRadius * Math.Cos(theta)); if (newX > 0 && newX < nWidth) { fp[x, y].X = newX; pt[x, y].X = (int) newX; } else { fp[x, y].X = 0.0; pt[x, y].X = 0; } newY = mid.Y + (newRadius * Math.Sin(theta)); if (newY > 0 && newY < nHeight) { fp[x, y].Y = newY; pt[x, y].Y = (int) newY; } else { fp[x, y].Y = 0.0; pt[x, y].Y = 0; } } if(bSmoothing) OffsetFilterAbs(b, pt); else OffsetFilterAntiAlias(b, fp); return true; } public static bool Moire(Bitmap b, double fDegree) { int nWidth = b.Width; int nHeight = b.Height; mid.X = nWidth/2; mid.Y = nHeight/2; double theta, radius; int newX, newY; for (int x = 0; x < nWidth; ++x) for (int y = 0; y < nHeight; ++y) { int trueX = x - mid.X; int trueY = y - mid.Y; theta = Math.Atan2((trueX),(trueY)); radius = Math.Sqrt(trueX*trueX + trueY*trueY); newX = (int)(radius * Math.Sin(theta + fDegree * radius)); if (newX > 0 && newX < nWidth) { pt[x, y].X = (int) newX; } else { pt[x, y].X = 0; } newY = (int)(radius * Math.Sin(theta + fDegree * radius)); if (newY > 0 && newY < nHeight) { pt[x, y].Y = (int) newY; } else { pt[x, y].Y = 0; } } OffsetFilterAbs(b, pt); return true; } public static bool Water(Bitmap b, short nWave, bool bSmoothing) { int nWidth = b.Width; int nHeight = b.Height; mid.X = nWidth/2; mid.Y = nHeight/2; double newX, newY; double xo, yo; for (int x = 0; x < nWidth; ++x) for (int y = 0; y < nHeight; ++y) { xo = ((double)nWave * Math.Sin(2.0 * 3.1415 * (float)y / 128.0)); yo = ((double)nWave * Math.Cos(2.0 * 3.1415 * (float)x / 128.0)); newX = (x + xo); newY = (y + yo); if (newX > 0 && newX < nWidth) { fp[x, y].X = newX; pt[x, y].X = (int) newX; } else { fp[x, y].X = 0.0; pt[x, y].X = 0; } if (newY > 0 && newY < nHeight) { fp[x, y].Y = newY; pt[x, y].Y = (int) newY; } else { fp[x, y].Y = 0.0; pt[x, y].Y = 0; } } if(bSmoothing) OffsetFilterAbs(b, pt); else OffsetFilterAntiAlias(b, fp); return true; } public static bool Pixelate(Bitmap b, short pixel, bool bGrid) { int nWidth = b.Width; int nHeight = b.Height; int newX, newY; for (int x = 0; x < nWidth; ++x) for (int y = 0; y < nHeight; ++y) { newX = pixel - x%pixel; if (bGrid && newX == pixel) pt[x, y].X = -x; else if (x + newX > 0 && x +newX < nWidth) pt[x, y].X = newX; else pt[x, y].X = 0; newY = pixel - y%pixel; if (bGrid && newY == pixel) pt[x, y].Y = -y; else if (y + newY > 0 && y + newY < nHeight) pt[x, y].Y = newY; else pt[x, y].Y = 0; } OffsetFilter(b, pt); return true; } public static bool sepia(Bitmap b, int red, int green, int blue) { BitmapData bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int remain = bmpData.Stride - bmpData.Width * 3; unsafe { byte* ptr = (byte*)bmpData.Scan0; for (int i = 0; i < bmpData.Height; i++) { for (int j = 0; j < bmpData.Width; j++) { byte t = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]); ptr[2] = ((byte)((t > (206+red)) ? 255 : t + 49+red)); ptr[1] = ((byte)((t < (14+green)) ? 0 : t - (14+green))); ptr[0] = ((byte)((t < (56+blue)) ? 0 : t - (56+blue))); ptr += 3; } /* for (int j = 0; j < bmpData.Width; j++) { byte t = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]); ptr[2] = ((byte)((t > red) ? 255 : t + red)); ptr[1] = ((byte)((t > green) ? 255 : t + green)); ptr[0] = ((byte)((t > blue) ? 255 : t + blue)); ptr += 3; }*/ ptr += remain; } } b.UnlockBits(bmpData); return true; } } }
Structure et Fichiers du projet
Afficher/masquer...Icône | Nom | Taille | Modification |
Pas de sous-répertoires. | |||
Icône | Nom | Taille | Modification |
| _ | Répertoire parent | 0 octets | 1734975364 23/12/2024 18:36:04 |
Utilisation de l'explorateur de code
- Navigation :
- Un clic sur une icône de répertoire ouvre ce répertoire pour en afficher les fichiers.
- Lorsque le répertoire en cours ne contient pas de sous-répertoires il est possible de remonter vers le répertoire parent.
- La structure de répertoires en treetable (tableau en forme d'arborescence) n'est plus possibledans cette version.
- Un clic sur une icône de fichier ouvre ce fichier pour en afficher le code avec la coloration syntaxique adaptée en fonction du langage principal utilisé dans le fichier.
- Affichage :
- Il est possible de trier les répertoires ou les fichiers selon certains critères (nom, taille, date).
- Actions :
- Les actions possible sur les fichiers dépendent de vos droits d'utilisateur sur le site. Veuillez activer le mode utilisateur pour activer les actions.
English translation
You have asked to visit this site in English. For now, only the interface is translated, but not all the content yet.If you want to help me in translations, your contribution is welcome. All you need to do is register on the site, and send me a message asking me to add you to the group of translators, which will give you the opportunity to translate the pages you want. A link at the bottom of each translated page indicates that you are the translator, and has a link to your profile.
Thank you in advance.
Document created the 30/10/2009, last modified the 26/10/2018
Source of the printed document:https://www.gaudry.be/en/cs-photobrol-source-rf-model/filters//BitmapFilter.cs.html
The infobrol is a personal site whose content is my sole responsibility. The text is available under CreativeCommons license (BY-NC-SA). More info on the terms of use and the author.