public static bool Sharpen(Bitmap b, int nWeight = 11)
        {
            ConvMatrix m = new ConvMatrix();

            m.SetAll(0);
            m.Pixel  = nWeight;
            m.TopMid = m.MidLeft = m.MidRight = m.BottomMid = -2;
            m.Factor = nWeight - 8;

            return(Conv3x3(b, m));
        }
        public static bool GaussianBlur(Bitmap b, int nWeight = 4)
        {
            ConvMatrix m = new ConvMatrix();

            m.SetAll(1);
            m.Pixel  = nWeight;
            m.TopMid = m.MidLeft = m.MidRight = m.BottomMid = 2;
            m.Factor = nWeight + 12;

            return(Conv3x3(b, m));
        }
        public static bool Conv3x3(Bitmap b, ConvMatrix m)
        {
            if (0 == m.Factor)
            {
                return(false);
            }

            Bitmap bSrc = (Bitmap)b.Clone();

            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 EdgeDetectConvolution(Bitmap b, short nType, byte nThreshold)
        {
            ConvMatrix m = new ConvMatrix();


            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;
            }

            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;
            }

            Conv3x3(bTemp, m);


            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);
        }