【问题标题】:Change alpha coefficient using Lockbits使用 Lockbits 更改 alpha 系数
【发布时间】:2015-11-18 15:24:57
【问题描述】:

我写了一个函数来改变图像的 alpha 系数。我使用 setpixel 和 getpixel,这非常慢。我发现 Lockbits 方法更快。我怎样才能用 Lockbits 做到这一点? 这是我当前的代码:

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

        }


    }
}

【问题讨论】:

  • this post 中的第一个例程可能会作为 Lockbits 示例感兴趣..
  • 代码中的主要问题是当您更改不透明度时,您再次将结果设置为图片框的图像并再次在结果上应用不透明度。换句话说,您对之前应用不透明度的图像应用不透明度。
  • Reza,你还有什么建议吗?
  • 查看我的答案的编辑部分,找到您在使用该方法时遇到的问题:)

标签: c# winforms pixel alpha lockbits


【解决方案1】:

您可以更改图像的不透明度,方法是使用新的ColorMatrix 在新位图中绘制图像,并为其Matrix33 分配一个介于 0 和 1 之间的浮点值作为其新的 alpha 值:

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

这是一个示例用法:

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

别忘了添加using System.Drawing;using System.Drawing.Imaging;

你可以在下面看到value=127调用函数之前和之后:

编辑

如果您想在PictureBox 中查看结果,请注意使用 2 个不同的图片框,一个用于原始图像,一个用于更改图像:

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

正如我在您的代码中看到的那样,当您更改不透明度时,您再次将结果设置为 PictureBox1 的图像并再次对结果应用不透明度。换句话说,您将不透明度应用到您一遍又一遍地对其应用不透明度的图像上。

【讨论】:

  • 它工作但不正常,我有一个具有最小值 0 和最大值 255 的轨迹栏,当我减小它时,它在这个距离内没有变化,在 200 上它已经不可见,当我增加时它无论如何都变得不可见了
  • 我附上的图片是使用这种方法的结果。当你的值降低时,你的图像会更透明,当你的值增加时,你的图像会变得不那么透明。
  • 当我增加值时,它变得越来越透明,这很奇怪
  • 实际上它工作了 :) 你的 changealpha 现在工作得很好,拿另一个图片框解决了这个问题,我的旧功能很慢,我用谷歌搜索了 setpixel 和 getpixel 方法很慢。谢谢你的帮助
【解决方案2】:
public Form1()
{
    ...
    originalImage = new Bitmap("C:\\Users\\rati\\Desktop\\water.jpg");
    pictureBox1.Image = originalImage;
    ...
}

// Add an extra field to the Form class.
Bitmap originalImage;

void trackBar1_Scroll(object sender, EventArgs e)
{
    pictureBox1.Image = ChangeAlpha((byte)trackBar1.Value);
    textBox1.Text = trackBar1.Value.ToString();
}

Image ChangeAlpha(byte alpha)
{
    Bitmap bmp = new Bitmap(originalImage);

    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);

    IntPtr ptr = bmpData.Scan0;

    int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
    byte[] rgbValues = new byte[bytes];

    Marshal.Copy(ptr, rgbValues, 0, bytes);

    // Set every fourth value to alpha. A 32bpp bitmap will change transparency.
    for (int counter = 3; counter < rgbValues.Length; counter += 4)
        rgbValues[counter] = alpha;

    // Also you can try parallelize loop.
    //int length = rgbValues.Length / 4;
    //Parallel.For(3, length, counter => rgbValues[counter * 4 - 1] = alpha);

    Marshal.Copy(rgbValues, 0, ptr, bytes);
    bmp.UnlockBits(bmpData);

    return bmp;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-05
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    相关资源
    最近更新 更多