在 C# 中更改位图的像素颜色

时间:2021-06-30 12:23:51

标签: c# image winforms bitmap pixel

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

我想要做的是导入一个图像,改变它的一个像素的颜色,然后导出它。

我做错了什么? 提前致谢。

2 个答案:

答案 0 :(得分:0)

设置颜色操作后,您应该再次设置带有颜色对象的文件。

那样;

image.SetPixel(50, 50, Color.Red);
File = image;

我希望这对你有用! (我编码并且它对我来说正确运行)

答案 1 :(得分:0)

您的代码实际上有几个问题:

  • 您没有关闭您打开的图像的文件流,这意味着您将永远无法将修改后的图像保存为相同的文件名。事实上,在您的程序关闭之前,任何程序都无法覆盖该文件。
  • 您不会检查是否可以进行编辑;打开任一维度小于 50 像素的图像,保存操作将崩溃。
  • 您只提供保存为 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))
    {
        File = new Bitmap(img);
    }
    pictureBox1.Image = File;
}

new Bitmap(image) 构造函数是 one of the few safe ways to make a clone of an image object that's completely disconnected from the original loaded source。如果之前采用不同的颜色格式,它确实会产生将图像转换为 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);
    }
}