在 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.

打开图像时要记住的基本规则是:

要解决未关闭流的问题,您可以这样加载图像:

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