C#:小项目-用单元格控件(像素点级别)修改图片
0.
无聊的时候,就想自己想象做一些东西,这不,就想到了这个东西。
准备如下:
- 一张图片
- 一个窗体应用项目 (visual studio WF)
- 主要控件 DataGrideView的使用
- 怎么想怎么来
想法是这样的:
一张图片的每个像素点,对应到每个单元格(这里使用 DataGrideView控件),想法来源于看到某 ERP系统中的芯片测试数据精确到每个测试点(以万计数)画图且可以查看修改,所以就想知道如何做,虽然不知道它们是用的什么方法,但是下面我就用我的方法来达到类似效果,之后可以举一反三。
1.代码如下:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace btmpToDie {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
Bitmap old; //原来的
Bitmap bmp; //单元格显示用的
//按钮选取一张图
private void button1_Click(object sender, System.EventArgs e) {
var ofd = new OpenFileDialog();
ofd.Filter = "png|*.png|jpg|*.jpg|bmp|*.bmp";
if (ofd.ShowDialog() == DialogResult.OK) {
old = (Bitmap)Bitmap.FromFile(ofd.FileName);
//太大的话,控件显示延迟太高
bmp = new Bitmap(100,100);
Graphics.FromImage(bmp).DrawImage(old, 0, 0, bmp.Width, bmp.Height);
MessageBox.Show("图片选取成功!");
}
}
//按钮-显示到单元格
private void button2_Click(object sender, System.EventArgs e) {
//单元格行,列数
dataGridView1.RowCount = bmp.Height;
dataGridView1.ColumnCount = bmp.Width;
//单元格的宽高设置
for (int x = 0; x < dataGridView1.Columns.Count; x++) {
dataGridView1.Columns[x].HeaderText = x+"";
dataGridView1.Columns[x].Width = 10;
dataGridView1.Columns[x].DividerWidth = 1;
}
for (int y = 0; y < dataGridView1.Rows.Count; y++) {
dataGridView1.Rows[y].HeaderCell.Value = y + "";
dataGridView1.Rows[y].Height = 10;
dataGridView1.Rows[y].DividerHeight = 1;
}
//行标题列,因为显示不全,所以宽度稍宽
//dataGridView1.RowHeadersWidth = 50;
//禁止用户改变单元格宽,高(下面四句都要)
dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;
dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
dataGridView1.AllowUserToResizeColumns = false;
dataGridView1.AllowUserToResizeRows = false;
//自定义标题头单元格的样式
//dataGridView1.EnableHeadersVisualStyles = false;//这句必要
//DataGridViewCellStyle headers = new DataGridViewCellStyle {
// BackColor = Color.Black,
// ForeColor = Color.White,
// SelectionBackColor = Color.Blue,
// Alignment = DataGridViewContentAlignment.MiddleCenter,
//};
//dataGridView1.RowHeadersDefaultCellStyle = headers;
//dataGridView1.ColumnHeadersDefaultCellStyle = headers;
//隐藏标题头 所以上面的注释了
dataGridView1.RowHeadersVisible = false;
dataGridView1.ColumnHeadersVisible = false;
//数据区单元格样式 背景灰色
dataGridView1.DefaultCellStyle = new DataGridViewCellStyle {
BackColor = Color.Gray
};
//设置无法直接编辑单元格内容
dataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically;
//一次一个像素点操控,不可选择多个单元格(像素)
//dataGridView1.MultiSelect = false; //false单个的话,下面双击标签时用current不用select
//显示图片像素点
for (int y = 0; y < dataGridView1.Rows.Count; y++) {
for (int x = 0; x < dataGridView1.Columns.Count; x++) {
dataGridView1.Rows[y].Cells[x].Style = new DataGridViewCellStyle {
BackColor = bmp.GetPixel(x,y)
};
}
}
}
//双击标签 ---- 同步保存单元格(像素点)和图片颜色
int xs = 0; //选中的第一个点的坐标
int ys = 0;
int xe = 0; //选中的最后一个点坐标
int ye = 0;
private void label1_DoubleClick(object sender, System.EventArgs e) {
var cd = new ColorDialog();
if (cd.ShowDialog() == DialogResult.OK) {
//dataGridView1.CurrentCell.Style.BackColor = cd.Color; //dataGridView1.MultiSelect = false时,用这个
for (int d = 0; d < dataGridView1.SelectedCells.Count; d++) {
DataGridViewCell cell = dataGridView1.SelectedCells[d];
cell.Style.BackColor = cd.Color;
//按比例修改原图 //注意:直接这样写,那在原图中修改的点不是连续的,所以要手动连续修改
int x = cell.ColumnIndex * (old.Width / bmp.Width);
int y = cell.RowIndex * (old.Height / bmp.Height);
//old.SetPixel(x,y,cd.Color);
//连续修改如下:
//注意:开始不是 d==0
if (d == dataGridView1.SelectedCells.Count - 1) { //开始
xs = x;
ys = y;
}
if (d == 0) { //结束
xe = x;
ye = y;
}
}
MessageBox.Show(xs +" "+ys + " "+xe+" "+ye);
//连续修改整遍选中区域 (进阶:可以在此区域插入其它图片)
for (int y = ys; y <= ye; y++) {
for (int x = xs; x <= xe; x++) {
old.SetPixel(x, y, cd.Color);
}
}
MessageBox.Show("修改完成");
}
}
//同步显示单元格(像素点)颜色 ----单元格点击事件
private void dataGridView1_CurrentCellChanged(object sender, System.EventArgs e) {
//标签显示颜色
label1.BackColor = dataGridView1.CurrentCell.Style.BackColor;
}
//保存按钮
//保存用单元格修改好的图片,不用缩放的,而是用原来的old,是因为缩放的bmp清晰度变得模糊了
private void button3_Click(object sender, System.EventArgs e) {
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
old.Save(path+"\\"+"your.png");
MessageBox.Show("保存成功");
}
}
}
效果如下:
1)原图
2)正修改时
3)保存后
4)如果不是用的连续修改解决方案,则效果如下-不理想
所以我们要记录单元格选中的第一个和最后一个,然后转换x,y的值,连续修改原图的像素点。
2.其它问题
我感觉用这个DataGrideView控件 鼠标拖动延迟有点高,不知道如何解决。。。。。。希望有人告知