在 C# 中更改位图的像素颜色
Change the pixel color of a bitmap in C#
public partial class Form1 : Form
{
Image File;
public Form1()
{
InitializeComponent();
}
private void Import_Click(object sender, EventArgs e)
{
OpenFileDialog f = new OpenFileDialog();
f.Filter = "Image files (*.jpg, *.png) | *.jpg; *.png";
if (f.ShowDialog() == DialogResult.OK)
{
File = Image.FromFile(f.FileName);
pictureBox1.Image = File;
}
}
private void Export_Click(object sender, EventArgs e)
{
Bitmap image = new Bitmap(File);
image.SetPixel(50, 50, Color.Black);
SaveFileDialog f = new SaveFileDialog();
f.Filter = "JPG(*.JPG)|*.jpg";
if (f.ShowDialog() == DialogResult.OK)
{
File.Save(f.FileName);
}
}
}
我想做的是导入一张图片,改变其中一个像素的颜色,然后导出。
我做错了什么?
提前致谢。
设置颜色操作完成后,需要用彩色对象重新设置文件。
那边;
image.SetPixel(50, 50, Color.Red);
File = image;
希望这对你有用! (我编码并且它为我正确运行)
您的代码实际上存在几个问题:
- 您没有关闭您打开的图像的文件流,这意味着您将永远无法将修改后的图像保存为相同的文件名。事实上,在您的程序关闭之前,任何程序都无法覆盖该文件。
- 您没有检查是否可以编辑;打开任一维度小于 51 像素的图像,保存操作将崩溃。
- 您只提供另存为 jpeg...一种格式,在这种格式中,单个像素的变化将不可避免地被压缩弄脏。
- 您没有实际保存为 jpeg。未指定类型的默认保存将使图像最终为 png 格式。它只会有错误的文件扩展名。
- 正如 ilyas varol 指出的那样,您保存的是未修改的
File
而不是已编辑的 image
.
打开图像时要记住的基本规则是:
- 从文件 will lock the file during the life cycle of the image object 创建的
Image
对象,防止文件被覆盖或删除,直到图像被释放。
- 从流 will need the stream to remain open for the entire life cycle of the image object 创建的
Image
对象。与文件不同,没有任何主动强制执行这一点,但在流关闭后,图像在保存、克隆或以其他方式操作时会出错。
要解决未关闭流的问题,您可以这样加载图像:
private void Import_Click(object sender, EventArgs e)
{
OpenFileDialog f = new OpenFileDialog();
f.Filter = "Image files (*.jpg, *.png)|*.jpg;*.png";
if (f.ShowDialog() != DialogResult.OK)
return;
using (Bitmap img = new Bitmap(f.FileName))
{
// if a file was already opened, dispose the old one.
// Start by setting the shown image to null so it
// will never try to show the disposed object.
pictureBox1.Image = null;
if (File != null)
{
try { File.Dispose(); }
catch { /* ignore */ }
}
// Clone loaded image into new object
File = new Bitmap(img);
}
pictureBox1.Image = File;
}
new Bitmap(image)
构造函数是 。它确实有将图像转换为 32 位颜色的副作用,如果它以前是不同的颜色格式的话。
不过这里还有另一个问题。在导出功能中,您再次制作了一个您未处置的新 Bitmap
。你为什么要制造那个克隆人?直接使用 File
有什么问题吗?如果没有,直接编辑即可,像素变化也会显示在UI上。如果您只想将更改应用到已保存的图片,请再次为新对象使用 using
块,这样内存中的图像资源会在之后自动清理。
此外,您应该只在用户实际确认文件名后才执行该操作。即使他们按下“取消”,您的代码也会执行它,因为它甚至在您显示对话框之前就已执行。
private void Export_Click(object sender, EventArgs e)
{
SaveFileDialog f = new SaveFileDialog();
f.Filter = "Png Image (.png)|*.png";
if (f.ShowDialog() != DialogResult.OK)
return;
// OPTION 1: Edit "File" directly:
// Don't edit without doing the necessary checks.
if (File.Width > 50 && File.Height > 50)
File.SetPixel(50, 50, Color.Black);
File.Save(f.FileName, ImageFormat.Png);
// OPTION 2: Edit clone without affecting "File":
using (Bitmap image = new Bitmap(File))
{
// Don't edit without doing the necessary checks.
if (image.Width > 50 && image.Height > 50)
image.SetPixel(50, 50, Color.Black);
image.Save(f.FileName, ImageFormat.Png);
}
}
public partial class Form1 : Form
{
Image File;
public Form1()
{
InitializeComponent();
}
private void Import_Click(object sender, EventArgs e)
{
OpenFileDialog f = new OpenFileDialog();
f.Filter = "Image files (*.jpg, *.png) | *.jpg; *.png";
if (f.ShowDialog() == DialogResult.OK)
{
File = Image.FromFile(f.FileName);
pictureBox1.Image = File;
}
}
private void Export_Click(object sender, EventArgs e)
{
Bitmap image = new Bitmap(File);
image.SetPixel(50, 50, Color.Black);
SaveFileDialog f = new SaveFileDialog();
f.Filter = "JPG(*.JPG)|*.jpg";
if (f.ShowDialog() == DialogResult.OK)
{
File.Save(f.FileName);
}
}
}
我想做的是导入一张图片,改变其中一个像素的颜色,然后导出。
我做错了什么? 提前致谢。
设置颜色操作完成后,需要用彩色对象重新设置文件。
那边;
image.SetPixel(50, 50, Color.Red);
File = image;
希望这对你有用! (我编码并且它为我正确运行)
您的代码实际上存在几个问题:
- 您没有关闭您打开的图像的文件流,这意味着您将永远无法将修改后的图像保存为相同的文件名。事实上,在您的程序关闭之前,任何程序都无法覆盖该文件。
- 您没有检查是否可以编辑;打开任一维度小于 51 像素的图像,保存操作将崩溃。
- 您只提供另存为 jpeg...一种格式,在这种格式中,单个像素的变化将不可避免地被压缩弄脏。
- 您没有实际保存为 jpeg。未指定类型的默认保存将使图像最终为 png 格式。它只会有错误的文件扩展名。
- 正如 ilyas varol 指出的那样,您保存的是未修改的
File
而不是已编辑的image
.
打开图像时要记住的基本规则是:
- 从文件 will lock the file during the life cycle of the image object 创建的
Image
对象,防止文件被覆盖或删除,直到图像被释放。 - 从流 will need the stream to remain open for the entire life cycle of the image object 创建的
Image
对象。与文件不同,没有任何主动强制执行这一点,但在流关闭后,图像在保存、克隆或以其他方式操作时会出错。
要解决未关闭流的问题,您可以这样加载图像:
private void Import_Click(object sender, EventArgs e)
{
OpenFileDialog f = new OpenFileDialog();
f.Filter = "Image files (*.jpg, *.png)|*.jpg;*.png";
if (f.ShowDialog() != DialogResult.OK)
return;
using (Bitmap img = new Bitmap(f.FileName))
{
// if a file was already opened, dispose the old one.
// Start by setting the shown image to null so it
// will never try to show the disposed object.
pictureBox1.Image = null;
if (File != null)
{
try { File.Dispose(); }
catch { /* ignore */ }
}
// Clone loaded image into new object
File = new Bitmap(img);
}
pictureBox1.Image = File;
}
new Bitmap(image)
构造函数是
不过这里还有另一个问题。在导出功能中,您再次制作了一个您未处置的新 Bitmap
。你为什么要制造那个克隆人?直接使用 File
有什么问题吗?如果没有,直接编辑即可,像素变化也会显示在UI上。如果您只想将更改应用到已保存的图片,请再次为新对象使用 using
块,这样内存中的图像资源会在之后自动清理。
此外,您应该只在用户实际确认文件名后才执行该操作。即使他们按下“取消”,您的代码也会执行它,因为它甚至在您显示对话框之前就已执行。
private void Export_Click(object sender, EventArgs e)
{
SaveFileDialog f = new SaveFileDialog();
f.Filter = "Png Image (.png)|*.png";
if (f.ShowDialog() != DialogResult.OK)
return;
// OPTION 1: Edit "File" directly:
// Don't edit without doing the necessary checks.
if (File.Width > 50 && File.Height > 50)
File.SetPixel(50, 50, Color.Black);
File.Save(f.FileName, ImageFormat.Png);
// OPTION 2: Edit clone without affecting "File":
using (Bitmap image = new Bitmap(File))
{
// Don't edit without doing the necessary checks.
if (image.Width > 50 && image.Height > 50)
image.SetPixel(50, 50, Color.Black);
image.Save(f.FileName, ImageFormat.Png);
}
}