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 | 1732583516 26/11/2024 02:11:56 |
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.
Version en cache
26/11/2024 02:11:56 Cette version de la page est en cache (à la date du 26/11/2024 02:11:56) afin d'accélérer le traitement. Vous pouvez activer le mode utilisateur dans le menu en haut pour afficher la dernère version de la page.Document créé le 30/10/2009, dernière modification le 26/10/2018
Source du document imprimé : https://www.gaudry.be/cs-photobrol-source-rf-model/filters//BitmapFilter.cs.html
L'infobrol est un site personnel dont le contenu n'engage que moi. Le texte est mis à disposition sous licence CreativeCommons(BY-NC-SA). Plus d'info sur les conditions d'utilisation et sur l'auteur.