Search code examples
c#winformspixelalphalockbits

Change alpha coefficient using Lockbits


I have written a function which changes the alpha coefficient of an image. I use setpixel and getpixel,which is very slow. I found out that Lockbits method is faster.How can I do it with Lockbits? Here is my current code:

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        private static Image Tran(Image s,int alpha)
        {
            int x = 0, y = 0;
            Bitmap tImage = new Bitmap(s);
            for (x = 0; x < tImage.Width; x++)
            {
                for (y = 0; y < tImage.Height; y++)
                {

                    tImage.SetPixel(x, y, Color.FromArgb(alpha, tImage.GetPixel(x, y).R, tImage.GetPixel(x, y).G, tImage.GetPixel(x, y).B));
                }
            }
            return tImage;

        }
        public Form1()
        {
            InitializeComponent();
            trackBar1.TickStyle = TickStyle.Both;
            trackBar1.Orientation = Orientation.Vertical;
            trackBar1.Minimum = 0;
            trackBar1.Maximum = 255;
            trackBar1.Height = 101;
            trackBar1.Value = 255;
            pictureBox1.Image = Image.FromFile("C:\\Users\\rati\\Desktop\\water.jpg");
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
        }
        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            pictureBox1.Image = ChangeAlpha(pictureBox1.Image, trackBar1.Value);

            textBox1.Text = trackBar1.Value.ToString();

        }


    }
}

Solution

  • You can change the opacity of your image by drawing it in a new bitmap using a new ColorMatrix and assigning a float value between 0 and 1 to its Matrix33 as its new alpha value:

    public Image ChangeAlpha(Image img, int value)
    {
        if (value < 0 || value > 255)
            throw new Exception("value must be between 0 and 255");
    
        Bitmap bmp = new Bitmap(img.Width, img.Height); // Determining Width and Height of Source Image
        Graphics graphics = Graphics.FromImage(bmp);
        ColorMatrix colormatrix = new ColorMatrix();
        colormatrix.Matrix33 = value / 255f;
        ImageAttributes imgAttribute = new ImageAttributes();
        imgAttribute.SetColorMatrix(colormatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
        graphics.DrawImage(img, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imgAttribute);
        graphics.Dispose();   // Releasing all resource used by graphics 
        return bmp;
    }
    

    And here is a sample usage:

    private void button1_Click(object sender, EventArgs e)
    {
        int opacityvalue = 127;
        var img = ChangeAlpha(Image.FromFile(@"d:\1.png"), opacityvalue);
        img.Save(@"d:\2.png");
    }
    

    Don't forget to add using System.Drawing; and using System.Drawing.Imaging;.

    You can see before and after calling the function with value=127 below:

    enter image description hereenter image description here

    EDIT

    If you want to see the result in a PictureBox you should pay attention to using 2 different picture boxes, one for original image, and one for changed image:

    private void trackBar1_Scroll(object sender, EventArgs e)
    {
        this.pictureBox2.Image = ChangeAlpha(this.pictureBox1.Image, this.trackBar1.Value);
    }
    

    As I see in your code when you change the opacity, you set the result as image of your PictureBox1 again and apply opacity again on the result. In other word you apply opacity on an image that you applied opacity to it before over and over again.