使用 Lockbits 更改 alpha 系数
Change alpha coefficient using Lockbits
我写了一个函数来改变图像的 alpha 系数。我使用 setpixel 和 getpixel,速度很慢。我发现 Lockbits 方法是 faster.How 我可以用 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();
}
}
}
您可以通过使用新的 ColorMatrix
and assigning a float value between 0 and 1 to its Matrix33
作为其新的 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:.png"), opacityvalue);
img.Save(@"d:.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
的图像,并再次对结果应用不透明度。换句话说,您将不透明度应用于您之前一遍又一遍对其应用不透明度的图像。
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;
}
我写了一个函数来改变图像的 alpha 系数。我使用 setpixel 和 getpixel,速度很慢。我发现 Lockbits 方法是 faster.How 我可以用 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();
}
}
}
您可以通过使用新的 ColorMatrix
and assigning a float value between 0 and 1 to its Matrix33
作为其新的 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:.png"), opacityvalue);
img.Save(@"d:.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
的图像,并再次对结果应用不透明度。换句话说,您将不透明度应用于您之前一遍又一遍对其应用不透明度的图像。
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;
}