You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WinForm的PictureBox1中展示两张图片的差异像素?

C# WinForm图片对比工具:新增差异像素可视化功能

先修正原代码的核心问题

原代码中发现差异像素后用break跳出内层循环,会导致只统计第一个差异像素就停止遍历,完全无法正确统计总差异数,必须先删除这个break。

UI调整准备

  • 在窗体上添加两个单选按钮(RadioButton),Text分别设为「实时显示差异像素」和「对比完成后批量显示」,Name设为radioRealTime和radioBatch,默认选中批量显示。
  • 将pictureBox1的SizeMode属性设置为Zoom,方便查看放大后的差异细节。

实现两种差异可视化模式

1. 实时逐像素显示差异

遍历过程中一旦发现差异,立刻标记到显示用的Bitmap上并刷新PictureBox,能直观看到对比过程,但频繁刷新会稍慢。

2. 批量显示差异

先收集所有差异像素的坐标,等整张图遍历完成后,一次性在Bitmap上标记所有差异,速度更快,适合大图片对比。


完整修改后的代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace ImageComparison
{
    public partial class Form1 : Form
    {
        string fname1, fname2;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            progressBar1.Visible = false;
            pictureBox1.Visible = false;
            // 默认选中批量显示模式
            radioBatch.Checked = true;
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            openFileDialog1.FileName = "";
            openFileDialog1.Title = "选择第一张图片";
            openFileDialog1.Filter = "图片文件|*.jpg; *.bmp; *.png";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                fname1 = openFileDialog1.FileName;
                // 预览第一张图
                pictureBox1.Image = Image.FromFile(fname1);
                pictureBox1.Visible = true;
            }
        }

        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            openFileDialog2.FileName = "";
            openFileDialog2.Title = "选择第二张图片";
            openFileDialog2.Filter = "图片文件|*.jpg; *.bmp; *.png";
            if (openFileDialog2.ShowDialog() == DialogResult.OK)
            {
                fname2 = openFileDialog2.FileName;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // 校验是否选择了两张图片
            if (string.IsNullOrEmpty(fname1) || string.IsNullOrEmpty(fname2))
            {
                MessageBox.Show("请先选择两张要对比的图片!");
                return;
            }

            progressBar1.Visible = true;
            int samePixelCount = 0, diffPixelCount = 0;
            bool isSame = true;

            // 使用using自动释放Bitmap资源,避免内存泄漏
            using (Bitmap img1 = new Bitmap(fname1))
            using (Bitmap img2 = new Bitmap(fname2))
            {
                if (img1.Width != img2.Width || img1.Height != img2.Height)
                {
                    MessageBox.Show("两张图片尺寸不一致,无法对比!");
                    progressBar1.Visible = false;
                    return;
                }

                // 创建基于第一张图的差异显示Bitmap
                Bitmap diffBitmap = new Bitmap(img1.Width, img1.Height);
                using (Graphics g = Graphics.FromImage(diffBitmap))
                {
                    g.DrawImage(img1, 0, 0);
                }

                progressBar1.Maximum = img1.Width;
                // 批量模式下存储差异像素坐标
                List<Point> diffPoints = new List<Point>();

                for (int i = 0; i < img1.Width; i++)
                {
                    for (int j = 0; j < img1.Height; j++)
                    {
                        Color color1 = img1.GetPixel(i, j);
                        Color color2 = img2.GetPixel(i, j);

                        // 直接对比RGB值,比转字符串高效
                        if (color1.R != color2.R || color1.G != color2.G || color1.B != color2.B)
                        {
                            diffPixelCount++;
                            isSame = false;

                            if (radioRealTime.Checked)
                            {
                                // 实时标记差异像素为红色
                                diffBitmap.SetPixel(i, j, Color.Red);
                                pictureBox1.Image = diffBitmap;
                                Application.DoEvents(); // 防止界面假死
                            }
                            else
                            {
                                // 批量模式记录坐标
                                diffPoints.Add(new Point(i, j));
                            }
                        }
                        else
                        {
                            samePixelCount++;
                        }
                    }
                    progressBar1.Value = i + 1;
                }

                // 批量模式下一次性标记所有差异
                if (radioBatch.Checked && !isSame)
                {
                    foreach (Point p in diffPoints)
                    {
                        diffBitmap.SetPixel(p.X, p.Y, Color.Red);
                    }
                    pictureBox1.Image = diffBitmap;
                }

                // 显示对比结果
                if (!isSame)
                {
                    pictureBox1.Visible = true;
                    MessageBox.Show($"图片不一致,共发现 {diffPixelCount} 个差异像素,{samePixelCount} 个相同像素");
                }
                else
                {
                    MessageBox.Show($"图片完全相同,共 {samePixelCount} 个相同像素");
                    pictureBox1.Image = img1;
                    pictureBox1.Visible = true;
                }
            }

            progressBar1.Visible = false;
        }
    }
}

额外优化说明

  • 替换原代码中通过ToString()对比像素的逻辑,改为直接对比RGB值,大幅提升效率。
  • 添加文件选择校验,避免空路径报错。
  • 实时显示时用Application.DoEvents()刷新界面,防止程序假死。
  • 差异像素默认用红色标记,可根据需求改为其他颜色(如Color.Yellow)。

内容的提问来源于stack exchange,提问作者jhon last

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 00:05:25