Image Manipulation

gbertoli3 0 Tallied Votes 158 Views Share

Set the Image's Gamma, Brightness, Contrast, Color; Enhance an Image's Edge; Turn it to a Grayscale Image; and Invert the Image.

#region Effects
        #region Invert Image
        /// <summary>
        /// Inverts an Image with the option to Invert it's Transparency.
        /// </summary>
        /// <param name="bitmap">The Bitmap Image you want to Invert.</param>
        /// <param name="InvertAlpha">True to Invert it's Transparency. False to Invert the Image Only.</param>
        /// <returns>An Inverted Image</returns>
        public Bitmap Invert(Bitmap bitmap)
        {
            //X Axis
            int x;
            //Y Axis
            int y;

            //For the Width
            for (x = 0; x <= bitmap.Width - 1; x++)
            {
                //For the Height
                for (y = 0; y <= bitmap.Height - 1; y += 1)
                {
                    //The Old Color to Replace
                    Color oldColor = bitmap.GetPixel(x, y);
                    //The New Color to Replace the Old Color
                    Color newColor;

                    //Set the Color for newColor
                    newColor = System.Drawing.Color.FromArgb(oldColor.A, 255 - oldColor.R, 255 - oldColor.G, 255 - oldColor.B);

                    //Replace the Old Color with the New Color
                    bitmap.SetPixel(x, y, newColor);
                }
            }
            //Return the Inverted Bitmap
            return bitmap;
        }

        /// <summary>
        /// Inverts an Image with the option to Invert it's Transparency.
        /// </summary>
        /// <param name="bitmap">The Bitmap Image you want to Invert.</param>
        /// <param name="InvertAlpha">True to Invert it's Transparency. False to Invert the Image Only.</param>
        /// <returns>An Inverted Image</returns>
        public Bitmap Invert(Bitmap bitmap, bool InvertAlpha)
        {
            //X Axis
            int x;
            //Y Axis
            int y;
            //For the Width
            for (x = 0; x <= bitmap.Width - 1; x++)
            {
                //For the Height
                for (y = 0; y <= bitmap.Height - 1; y += 1)
                {
                    //The Old Color to Replace
                    Color oldColor = bitmap.GetPixel(x, y);
                    //The New Color to Replace the Old Color
                    Color newColor;
                    //If the user has chosen to Invert the Transparency
                    if (InvertAlpha)
                    {
                        //Set the Color for newColor
                        newColor = System.Drawing.Color.FromArgb(255 - oldColor.A, 255 - oldColor.R, 255 - oldColor.G, 255 - oldColor.B);
                    }
                    else
                    {
                        //Set the Color for newColor
                        newColor = System.Drawing.Color.FromArgb(oldColor.A, 255 - oldColor.R, 255 - oldColor.G, 255 - oldColor.B);
                    }
                    //Replace the Old Color with the New Color
                    bitmap.SetPixel(x, y, newColor);
                }
            }
            //Return the Inverted Bitmap
            return bitmap;
        }
        #endregion

        #region Grayscale
        // <summary>
        /// Convert an Image to a Grayscale Image.
        /// </summary>
        /// <param name="Bitmap">The Bitmap to Convert to Grayscale.</param>
        /// <returns>A Grayscale Image.</returns>
        public Bitmap MakeGrayscale(Bitmap Bitmap)
        {
            //Declare myBitmap as a new Bitmap with the same Width & Height
            Bitmap myBitmap = new Bitmap(Bitmap.Width, Bitmap.Height);

            for (int x = 0; x < Bitmap.Width; x++)
            {
                for (int y = 0; y < Bitmap.Height; y++)
                {
                    //Get the Pixel
                    Color BitmapColor = Bitmap.GetPixel(x, y);

                    //Declare grayScale as the Grayscale Pixel
                    int grayScale = (int)((BitmapColor.R * 0.3) + (BitmapColor.G * 0.59) + (BitmapColor.B * 0.11));

                    //Declare myColor as a Grayscale Color
                    Color myColor = System.Drawing.Color.FromArgb(grayScale, grayScale, grayScale);

                    //Set the Grayscale Pixel
                    myBitmap.SetPixel(x, y, myColor);
                }
            }
            return myBitmap;
        }
        #endregion

        #region Gamma
        private static Bitmap Gamma(Bitmap b, double red, double green, double blue)
        {
            if (red < .2 || red > 5) return b;
            if (green < .2 || green > 5) return b;
            if (blue < .2 || blue > 5) return b;

            byte[] redGamma = new byte[256];
            byte[] greenGamma = new byte[256];
            byte[] blueGamma = new byte[256];

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

            // GDI+ still lies to us - the return format is BGR, NOT 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 b;
        }
        #endregion

        #region Brightness
        private static Bitmap Brightness(Bitmap b, int nBrightness)
        {
            if (nBrightness < -255 || nBrightness > 255)
                return b;

            // GDI+ still lies to us - the return format is BGR, NOT 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 b;
        }
        #endregion

        #region Contrast
        private static Bitmap Contrast(Bitmap b, sbyte nContrast)
        {
            if (nContrast < -100) return b;
            if (nContrast > 100) return b;

            double pixel = 0, contrast = (100.0 + nContrast) / 100.0;

            contrast *= contrast;

            int red, green, blue;

            // GDI+ still lies to us - the return format is BGR, NOT 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 b;
        }
        #endregion

        #region Color
        private static Bitmap Color(Bitmap b, int red, int green, int blue)
        {
            if (red < -255 || red > 255) return b;
            if (green < -255 || green > 255) return b;
            if (blue < -255 || blue > 255) return b;

            // GDI+ still lies to us - the return format is BGR, NOT 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 nPixel;

                for (int y = 0; y < b.Height; ++y)
                {
                    for (int x = 0; x < b.Width; ++x)
                    {
                        nPixel = p[2] + red;
                        nPixel = Math.Max(nPixel, 0);
                        p[2] = (byte)Math.Min(255, nPixel);

                        nPixel = p[1] + green;
                        nPixel = Math.Max(nPixel, 0);
                        p[1] = (byte)Math.Min(255, nPixel);

                        nPixel = p[0] + blue;
                        nPixel = Math.Max(nPixel, 0);
                        p[0] = (byte)Math.Min(255, nPixel);

                        p += 3;
                    }
                    p += nOffset;
                }
            }

            b.UnlockBits(bmData);

            return b;
        }
        #endregion

        #region EdgeEnhance
        private static Bitmap 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();

            // GDI+ still lies to us - the return format is BGR, NOT 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 b;
        }
        #endregion
#endregion