The manuscript was completed on May 19, 2020.
text
I hope that the order of the code copied and pasted from word is not disordered, I have been too lazy to check.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ImageCut { public partial class Form1 : Form { Bitmap currentImage; // Bitmap is an object used to process images defined by pixel data Bitmap cutImage; public Form1()//Constructor { InitializeComponent(); } Boolean ifgray = false;/Whether to grayscale, the value will be reset when a new image is opened. private void openFileToolStripMenuItem_Click(object sender, EventArgs e)//Define the ToolStripMenuItem (toolstrip menu item) method to open [File] { OpenFileDialog ofd = new OpenFileDialog();//An instantiation of a class, instance named ofd, which can be used to check if a file exists and open it. ofd.Filter = "Jpeg Files (jpg)|*.jpg; | Bitmap Files (bmp)|*.bmp; | Gif Files (gif)|*.gif; | Png Files (png)|*.png; | All Files (*.*) | *.*;"; //file type filtering string filename; if(ofd.ShowDialog()==DialogResult.OK)//If the user clicks OK in the dialog { filename = ofd.FileName; //The opened file is named as the original file name } else { return; //otherwise return } currentImage = new Bitmap(filename); pictureBox1.Image = currentImage;//Show selected image ifgray = false; cutImage = null; pictureBox2.Image = null; pictureBox3.Image = null; } private void openFolderToolStripMenuItem_Click(object sender, EventArgs e)//Define the ToolStripMenuItem (toolstrip menu item) method to open the [folder] { //roughly the same FolderBrowserDialog fbd = new FolderBrowserDialog(); string path; if (fbd.ShowDialog() == DialogResult.OK) { path = fbd.SelectedPath;//The file path is the path selected by the user } else { return; } DirectoryInfo root = new DirectoryInfo(path);//The DirectoryInfo class is part of the System.IO namespace and is used to create, delete and move directories. //Refers to the user-selected folder path as the root directory foreach (FileInfo f in root.GetFiles()) { string filename = f.FullName; if (f.Extension.ToUpper() == ".BMP" || f.Extension.ToUpper() == ".JPG" || f.Extension.ToUpper() == ".PNG" || f.Extension.ToUpper() == ".GIF" || f.Extension.ToUpper() == ".TIF") { int newrow = dataGridView1.Rows.Add();//Add the files in the obtained folder in the data grid display column, and create a new line for each additional file dataGridView1["image", newrow].Value = new Bitmap(filename);//new Bitmap(filename) dataGridView1["id", newrow].Value = newrow;//The id column value is the row value dataGridView1["filename", newrow].Value = filename;//filename is the original name of the file } } } private void clearAllToolStripMenuItem_Click(object sender, EventArgs e)//delete all added files { dataGridView1.Rows.Clear(); pictureBox1.Image = null; pictureBox2.Image = null; pictureBox3.Image = null; currentImage = null; cutImage = null; } private void clearSelectedToolStripMenuItem_Click(object sender, EventArgs e)//delete selected files { int rowCount; rowCount = dataGridView1.Rows.Count; dataGridView1.ReadOnly = true; for(int i=rowCount-1;i>=0;i--)//data traversal { if(Convert.ToInt16(dataGridView1["selected",i].Value) == 1)//Delete all files marked as selected { //string filename = dataGridView1.CurrentCell.Value.ToString(); //if (pictureBox1.Image. == filename) //{ // pictureBox1.Image = null; // pictureBox2.Image = null; // currentImage = null; // cutImage = null; //} dataGridView1.Rows.RemoveAt(i); } } dataGridView1.ReadOnly = false; rowCount = dataGridView1.Rows.Count;//number of update files for(int i=0;i<rowCount;i++) { dataGridView1["id", i].Value = i;//renumber } } private void dataGridView1_Click(object sender, EventArgs e)//DataGridView class: cell //Display selected picture //Get or set the currently active cell { if (dataGridView1.Rows.Count==0)//fix bug s { MessageBox.Show("list is empty", "Warning"); return; } else { if (dataGridView1.CurrentCell.ColumnIndex == 3)//Clicking the list when the list is empty will appear [System.NullReferenceException: "The object reference is not set to an instance of the object."], the program does not respond { string filename = dataGridView1.CurrentCell.Value.ToString(); currentImage = new Bitmap(filename); pictureBox1.Image = currentImage;//Show current photo ifgray = false; cutImage = null; pictureBox2.Image = null; pictureBox3.Image = null; } else; } } //Initialize key values int start_row = 0, start_col = 0;//start row, column 0 int current_row = 0, current_col = 0;//current row, column 0 int LU_row = 0, LU_col = 0;//The coordinate pair of the upper left corner of the ROI is 0 int rcw = 0, rch = 0;//ROI width and height are 0 Boolean if_draw = false;//This boolean is used to mark whether to draw the ROI in the image private void button1_Click(object sender, EventArgs e)//Set the button for storing subimage folders { FolderBrowserDialog fbd = new FolderBrowserDialog(); if(fbd.ShowDialog() == DialogResult.OK) { string path; path = fbd.SelectedPath;//Set the path to the specified path value textBox1.Text = path;//Display the path selected by the user } } private void button2_Click(object sender, EventArgs e)//save subimage { if(cutImage == null)//Button has no effect if no subimage is created { MessageBox.Show("You have not created a subimage", "Warning");///Error message return; } string path = textBox1.Text; if(path.Length == 0)//If no path is specified, the button has no effect { MessageBox.Show("You have not added the specified path", "Warning");///Error message return; } DirectoryInfo di = new DirectoryInfo(path); int fileCount = di.GetFiles().Length; string filename = path + "\\" + (fileCount + 1).ToString() + ".bmp";//Name the subimage filename cutImage.Save(filename);//Save the subimage to the specified path } private void pictureBox1_MouseDown(object sender, MouseEventArgs e)//The pictureBox control is used to display the picture//This method belongs to the first step of drawing ROI, which is used to configure the right click of the mouse { if (currentImage == null)//This method has no effect when no image is selected { return; } else if (ifgray == false) { MessageBox.Show("It must be grayscaled before it can be selected ROI!"); return; } else; int w, h; w = currentImage.Width; h = pictureBox1.Height; if (e.Y >= 0 && e.Y <= h - 1 && e.X >= 0 && e.X <= w - 1)//Determine if the mouse click position is within the photo size { if_draw = true;//Start drawing ROI start_row = e.Y;//Set the starting coordinate value start_col = e.X; pictureBox1.Cursor = Cursors.Cross;//Mouse changes from arrow to cross } else; } private void pictureBox1_MouseMove(object sender, MouseEventArgs e)//This method belongs to the second step of drawing ROI. After the mouse is right-clicked, it is used to configure the block diagram (ie the ROI area) to move with the mouse { if(if_draw == true)//When the ROI is already being drawn { current_row = e.Y;//Set the current coordinate value current_col = e.X; } pictureBox1.Invalidate();//Redraw the block diagram after releasing the mouse } private void pictureBox1_MouseUp(object sender, MouseEventArgs e)//This method belongs to the third step of drawing ROI. Release the right mouse button, the block diagram is drawn, and the program will record the ROI. { if (if_draw == true && ifgray == true) { if_draw = false;//ROI drawing completed pictureBox1.Cursor = Cursors.Arrow;//Release the right mouse button, the mouse arrow returns if (rcw > 0 && rch > 0)/repair bug { cutImage = new Bitmap(rcw, rch); Graphics g = Graphics.FromImage(cutImage);//Error: If the mouse only clicks on the picture without dragging, the program will be abnormal g.DrawImage(currentImage, 0, 0, new Rectangle(LU_col, LU_row, rcw, rch), GraphicsUnit.Pixel);//Capture ROI pictureBox2.Image = cutImage;//Show the ROI in the picturebox on the left } } else return; } private void pictureBox1_Paint(object sender, PaintEventArgs e)//block diagram for configuration { if (if_draw == true) { Pen pen = new Pen(Color.Red, 1);//Set stroke parameters //set dotted line pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;//draw dashed line //Top left corner of ROI if (start_row <= current_row)//record coordinate pairs { LU_row = start_row; } else { LU_row = current_row; } if (start_col <= current_col) { LU_col = start_col; } else { LU_col = current_col; } rcw = Math.Abs(current_col - start_col) + 1;//Calculate the width and height of the ROI rch = Math.Abs(current_row - start_row) + 1; e.Graphics.DrawRectangle(pen, LU_col, LU_row, rcw, rch);//draw a block diagram } } private void VersionToolStripMenuItem_Click(object sender, EventArgs e)///display version info { MessageBox.Show("fix the following bug: \n 1.Clicking on the blank list program will jump out\n 2.Click the picture program will jump out\n " + "—\n Add the following optimizations:\n 1.Prompt Assistant\n 2.Quick delete&Quick switch&Shortcut menu\n 3.Optimized file filters\n 4.full screen mode\n 5.Automatically clear the screen\n " + "6.add thumbnail\n 7.Add help information\n 8.Other details optimization and window beautification\n " + "—\n Add the following functions:\n 1.Image rotation&mirror\n 2.grayscale image\n 3.Grayscale histogram\n 4.image binarization\n" + "\n by Huang Yihao\n", "About"); } private void hotkey_Click(object sender, EventArgs e) { MessageBox.Show("Currently available shortcuts:\n \n 1.Select the picture in the list, press the arrow keys to switch pictures\n 2.Double-click the checkbox to delete the picture; to delete a group of photos," + "You can tick the photos to be deleted, and double-click in the checkbox of the last photo to delete this group of photos;\n","Shortcuts"); } ///Grayscale private void button5_click(object sender, EventArgs e) { if (currentImage == null)//Button has no effect if no subimage is created { MessageBox.Show("You have not selected an image yet!\n \n Image binarization operation steps:\n Open the picture - click [Grayscale] - select ROI-Click [Binarization]\n"); return; } else { //MessageBox.Show("Grayscale takes a long time, please wait patiently\n \n Click OK to continue"); for (int i = 0; i < currentImage.Width; i++) { for (int j = 0; j < currentImage.Height; j++) { //Get the RGB color of the pixel at this point Color color = currentImage.GetPixel(i, j); //Calculate the gray value using the formula int gray = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11); Color newColor = Color.FromArgb(gray, gray, gray); currentImage.SetPixel(i, j, newColor); } } pictureBox1.Image = currentImage; ifgray = true; //MessageBox.Show("Complete."); } } private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) { } //Binarization //Based on the limitations of the binarization algorithm, only ROI can be selected first private void button6_Click(object sender, EventArgs e) { if (currentImage == null)//Button has no effect if no subimage is created { MessageBox.Show("Image binarization operation steps:\n Open the picture - click [Grayscale] - select ROI-Click [Binarization]\n"); return; } else if (cutImage == null)//Button has no effect if no subimage is created { if (ifgray == true) { MessageBox.Show("must be selected first ROI!\n \n Image binarization operation steps:\n Open the picture - click [Grayscale] - select ROI-Click [Binarization]\n"); return; } else { MessageBox.Show("Grayscale must be done first!\n \n Image binarization operation steps:\n Open the picture - click [Grayscale] - select ROI-Click [Binarization]\n"); return; } } else { if (ifgray == true) { //MessageBox.Show("Binarization takes a long time, please be patient\n \n Click OK to continue"); int average = 0; //Take the average grayscale of the image as the threshold, all values below this value are 0, and all values above this value are 255 for (int i = 0; i < cutImage.Width; i++) { for (int j = 0; j < cutImage.Height; j++) { Color color = cutImage.GetPixel(i, j); average += color.B;//After grayscale, just take any value in RGB } } average = (int)average / (cutImage.Width * cutImage.Height);//adaptive threshold //average = 127;//fixed threshold for (int i = 0; i < cutImage.Width; i++) { for (int j = 0; j < cutImage.Height; j++) { //Get the RGB color of the pixel at this point Color color = cutImage.GetPixel(i, j); int value = 255 - color.B;//reverse color Color newColor = value > average ? Color.FromArgb(0, 0, 0) : Color.FromArgb(255, 255, 255); cutImage.SetPixel(i, j, newColor);//update color } } pictureBox2.Image = cutImage; // MessageBox.Show("Complete."); } else { MessageBox.Show("Before binarization, grayscale must be performed!\n \n Image binarization operation steps:\n Open the picture - click [Grayscale] - select ROI-Click [Binarization]\n"); } } } //keyboard shortcuts private void dataGridView1_Press(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) { if (dataGridView1.Rows.Count == 0)//fix bug s { return; } else { if (dataGridView1.CurrentCell.ColumnIndex == 3) { string filename = dataGridView1.CurrentCell.Value.ToString(); currentImage = new Bitmap(filename); pictureBox1.Image = currentImage; } } } } //Grayscale histogram private void pictureBox2_Click(object sender, EventArgs e) { if (ifgray == false) { MessageBox.Show("Grayscale must be performed first\n", "Do you wish to display a grayscale histogram?"); return; } else { if (cutImage == null) { MessageBox.Show("must be selected roi\n", "Do you wish to display a grayscale histogram?"); } else { int[] values = new int[256];//create array for (int i = 0; i < 256; i++) values[i] = 0;//initialize the array for (int i = 0; i < cutImage.Width; i++) { for (int j = 0; j < cutImage.Height; j++) { Color color = cutImage.GetPixel(i, j); int value = color.B;//Get the gray value of each point and store it in an array values[value]++; } } //Find the highest value of the data in the image to be drawn int max = 0; foreach (int i in values) max = max > i ? max : i; Image grayImage = null; //drawing, referencing method draw(ref values, max, out grayImage); } } } //draw a histogram private bool draw(ref int[] datas, int Height, out Image grayImage) { grayImage = new Bitmap(256, Height + 10); //The maximum value of the y-axis of the image is higher than the maximum value of the data Graphics g = Graphics.FromImage(grayImage); Pen pen = new Pen(Color.Black);//pen color for (int i = 0; i <= 255; i++) { g.DrawLine(pen, i, Height - datas[i] + 10, i, Height + 10);//Draw a straight line, the grayscale histogram consists of straight lines } pictureBox3.Image = grayImage; return true; } private void label3_Click(object sender, EventArgs e) { MessageBox.Show("The grayscale histogram is to count all the pixels in the digital image, according to the size of the grayscale value, to count the frequency of their occurrence.\n \n" + "Operations to display grayscale histograms:\n [Grayscale]-[select ROI]-[click roi]\n","Grayscale histogram display teaching"); } // Rotate the picture 90 degrees clockwise private void btnRotate_Click(object sender, EventArgs e) { if (currentImage == null)//Button has no effect if no subimage is created { return; } else { pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize; currentImage.RotateFlip(RotateFlipType.Rotate90FlipNone); pictureBox1.Image = currentImage; } } // Rotate 90 degrees counterclockwise private void btncounterclockwiseRotate_Click(object sender, EventArgs e) { if (currentImage == null)//Button has no effect if no subimage is created { return; } else { pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize; // An additional implementation of a 90 degree counterclockwise rotation currentImage.RotateFlip(RotateFlipType.Rotate270FlipNone); pictureBox1.Image = currentImage; } } //mirror private void Button7_Click(object sender, EventArgs e) { if (currentImage == null)//Button has no effect if no subimage is created { return; } else { pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize; currentImage.RotateFlip(RotateFlipType.Rotate180FlipY); pictureBox1.Image = currentImage; } } } }
postscript
In the past few years, I have learned C (C51), assembly, python, C# and VBS in sequence in college. It sounds amazing. In fact, the best one is C (relatively speaking); assembly can only be read but not written. I don't remember how much now; Python and VBS both use which knowledge points to learn, and there is no general concept.
C# is the last language I learned in a formal course, I learned it very seriously, and I feel very good about myself (although it's all self-taught and I haven't watched the video seriously). Because of the epidemic, before I returned to school, I had already started to work on this final project, and the addition of functions was addicting. Every day I wondered how I could make a foolish operation. I think it's too watery, can I add another one? In the end, I worked on the project for 20 days before and after, and it was considered a good level in the class (I think). Frankly speaking, after finishing this project, I never touched C# again (in fact, I made a semi-finished product for another project, and I always wondered if I could use C# to compile a small tool in other projects, and only make a semi-finished product The reason is that the amount of knowledge required to complete it is beyond my level at that time), I don't know what the level of this project is, but for a beginner, I am relatively satisfied with the knowledge I have.
One of the very important purposes of learning C# at the beginning was to understand the difference between object-oriented and process-oriented, even though I had taught myself mircoPython at that time, it was only the degree of library adjustment.
2020/8/19/20:20