Image processing in Java-like cameras (on)
\qquad 1. Create the form
\qquad 2. Action Listener
\qquad 3. Get the pixel value of the image file
\qquad 4. Draw the original painting
\qquad 5. Draw grayscale images
\qquad 6. Draw a black and white binary image
\qquad 7. Draw a mosaic
1. Introduction
\qquad The last article introduced the principle of images, RGB tricolor values are stored in int values and then split into tricolor values, displacement operators in Java and hexadecimal numbers. In this article, I will put these into practice, Make a few simple image processing functions.
2. Project process
1. Create the form
First, we need a form to display images, so we use the JFrame we learned before, and add an action listener ImageListener for each button to implement the functions separately.
public class ImagePad { String[] strs = {"Open","save","original image","grayscale","Binarization","mosaic","dot mosaic", "nostalgic","contour","sketch","sharpen","zoom out","enlarge", };// This article is not fully implemented, but a complete project will be made later // Create a listener object ImageListener img1 = new ImageListener(); public void showUI(){ JFrame jf = new JFrame("Image Processing V1.0"); jf.setSize(800,600);//size jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//close directly jf.setLocationRelativeTo(null);//Center popup jf.setLayout(new FlowLayout());//Flow layout // Create button object | set properties (text size background color font size listener) Font font = new Font("black body",Font.BOLD,16); for (int i = 0; i < strs.length; i++) { JButton btn = new JButton(strs[i]); btn.setBackground(Color.WHITE); btn.setFont(font); btn.addActionListener(img1);//Add action listener jf.add(btn); } jf.setVisible(true); // After visualization, get a Graphics img1.g = jf.getGraphics();//The listener gets the brush in the form } public static void main(String[] args) { new ImagePad().showUI(); } }
2. Action Listener
Before talking about the action listener, let me list the new knowledge used in this action listener.
-
Code block: {}:
-
In the program, use a pair of square brackets to include some code statements, which means that the object is executed when the object is created, which means initialization.
-
You can put some functions that often need the same call in the program, which can save time and avoid unnecessary overhead.
-
-
switch(a) case statement:
-
The switch-case statement can easily enumerate the situation, which is much simpler than the usual if else if.... According to the value of a and case, the corresponding code is run.
-
Don't forget to break; to jump out of the loop, you can also write a default statement to facilitate execution when it is not satisfied.
-
Below is the code of the action listener ImageListener
public class ImageListener implements ActionListener { ImageTools imgtools = new ImageTools(); Graphics g; int[][] imageArr; {// The code block executes the initialized method call when the object is created String path = "D:\\OneDrive\\desktop\\xinhai.jpg"; // Pass in the image path to get the pixel moment two-dimensional array of the image imageArr = imgtools.getImagePiexArray (path);//I'll talk about it later, don't worry } @Override public void actionPerformed(ActionEvent e) { // get the string on the button String btnStr = e.getActionCommand(); System.out.println("Clicked:"+ btnStr); // Draw a picture based on the clicked string action switch (btnStr){ case "original image": // draw pictures System.out.println("original image"); imgtools.drawImage(imageArr,g); break; case "grayscale": imgtools.drawGrayImage(imageArr,g); break; case "Binarization": imgtools.drawBinaryImage(imageArr,g); break; case "mosaic": imgtools.drawMosaicImage(imageArr,g); break; } } }
3. Get the pixel value of the image file
This basic framework is ready, let's now learn the implementation of the drawing function.
First popularize a little knowledge, enter /** in front of the method that has been written in the idea and press Enter, a new comment will appear, called a document comment. For example
/** Documentation Notes * Get a two-dimensional pixel array of an image based on a path * @param path Parameters: image path * @return two-digit array of pictures */
We first consider how to draw the original image
First, we need to create a method to get the pixels in the image. Since the image is a two-dimensional matrix, our return value should also be a two-dimensional array.
We need to get the pixels in the image file first, so naturally we need to use file operations,
/** Documentation Notes * Get a two-dimensional pixel array of an image based on a path * @param path Parameters: image path * @return two-digit array of pictures */ public int[][] getImagePiexArray(String path){ File file = new File(path);//path is the path to the file }
Then we use the BufferedImage class to create an image buffer, which is used to load the image into memory, and the image can be easily manipulated through the image buffer.
BufferedImage buffimg = null;
Read the image file object file created above through the read method in ImageIO and load it in buffimg
buffimg = ImageIO.read(file);
But if you write it like this, you will find an error
prompts us to try catch around, then click and do as it says
Now there is no error
Now that the data of this image has been stored in buffimg, we can proceed further.
The essence of the picture is a two-dimensional matrix of pixel values. The same is true for buffimg. We obtain the length and width of this two-dimensional matrix respectively.
//buffimg width height pixel value int width = buffimg.getWidth(); int height = buffimg.getHeight();
Now we create a two-dimensional array imgArr with the same length and width, in order to store the pixel value of each position of the image below.
int[][] imgArr = new int[width][height];
Next we traverse this two-dimensional array and store the pixel RGB values in bufferimg into imgArr. The getRGB(int x,int y) method in BufferedImage is used to get the pixel at a certain position
for (int i = 0; i < imgArr.length; i++) { for (int j = 0; j < imgArr[i].length; j++) { imgArr[i][j] = buffimg.getRGB(i,j); } } return imgArr;
The method for obtaining the pixel value of the image is finished, and we can call it in other methods to quickly obtain the image pixel.
The complete code is as follows
public int[][] getImagePiexArray(String path){ File file = new File(path); BufferedImage buffimg = null; try { buffimg = ImageIO.read(file); } catch (IOException e) { e.printStackTrace(); } //buffimg width height pixel value int width = buffimg.getWidth(); int height = buffimg.getHeight(); // Create a two-dimensional array based on width and height int[][] imgArr = new int[width][height]; // Traverse the loop and store all the pixel values in the array // Traverse from the beginning to the end, take out all for (int i = 0; i < imgArr.length; i++) { for (int j = 0; j < imgArr[i].length; j++) { imgArr[i][j] = buffimg.getRGB(i,j); } } return imgArr; }
4. Draw the original image
Now let's draw the original image. The idea is very simple, that is to draw the obtained imgArr array intact, because our imgArr is originally the pixel of the stored image file, then directly traversing the array and drawing it is the original image.
For drawing, we definitely need the brush object Graphics. We can draw each pixel value in the way we like, such as drawing according to rectangle, drawing according to circle and so on.
/** * original image * @param imgArr * @param g */ public void drawImage(int[][] imgArr, Graphics g){ for (int i = 0; i < imgArr.length; i++) { for (int j = 0; j < imgArr[i].length; j++) { int pixnum = imgArr[i][j];//Get the current pixel color, expressed as an int value Color color = new Color(pixnum); g.setColor(color); X Y Set the position of the image for a predefined offset value g.fillRect(X + i, Y + j, 1, 1);//Drawing in a rectangle, the original image pixel is also a 1*1 rectangle, so there will be no gaps } } }
5. Draw grayscale images
The drawing method of the grayscale image is similar to the original image, except that the color value cannot be directly used imgArr[i][j], but three primary colors must be split and mixed in a certain proportion.
6 ways to draw grayscale images:
1. Floating point method: Gray=R0.3+G0.59+B*0.11
2. Integer method: Gray=(R30+G59+B*11)/100
3. Shift method: Gray =(R77+G151+B*28)>>8;
4. Average method: Gray=(R+G+B)/3;
5. Only take green: Gray=G;
6.Gamma correction algorithm:
Here I use the fourth method of averaging:
used the int value of the previous lesson to split into RGB
/** * Grayscale * @param imgArr * @param g */ public void drawGrayImage(int[][] imgArr, Graphics g){ for (int i = 0; i < imgArr.length; i++) { for (int j = 0; j < imgArr[i].length; j++) { int pixnum = imgArr[i][j]; // Split pixel value to RGB int red = (pixnum >> 16) & 255; int green = (pixnum >> 8) & 255; int blue = (pixnum >> 0) & 255; // The principle of grayscale R=G=B // mean method int gray = (red + green + blue)/3; Color color = new Color(gray,gray,gray); g.setColor(color); g.fillRect(X + i, Y + j,1 ,1); } } }
6. Draw a black and white binary image
The principle of is similar, that is, the gray value is divided again, and the gray value greater than or equal to 127 is set to white, and the value less than 127 is set to black, and a simple binarization is completed.
/** * black and white * @param imgArr * @param g */ public void drawBinaryImage(int[][] imgArr, Graphics g){ for (int i = 0; i < imgArr.length; i++) { for (int j = 0; j < imgArr[i].length; j++) { int pixnum = imgArr[i][j]; // Split pixel value to RGB int red = (pixnum >> 16) & 255; int green = (pixnum >> 8) & 255; int blue = (pixnum >> 0) & 255; // The principle of grayscale R=G=B // mean method int gray = (red + green + blue)/3; // Use gray value to do bisection if(gray < 127){ g.setColor(Color.BLACK); }else { g.setColor(Color.WHITE); } g.fillRect(X + i, Y + j,1 ,1); } } }
7. Draw a mosaic
We used to draw the rectangular frame according to 1 * 1. If we change it to 10 * 10, and change the convenient step size of the array to 10, then a simple mosaic effect is achieved, because the pixel block becomes larger. .
/** * mosaic * @param imgArr * @param g */ public void drawMosaicImage(int[][] imgArr, Graphics g){ for (int i = 0; i < imgArr.length; i+=10) { for (int j = 0; j < imgArr[i].length; j+=10) { int pixnum = imgArr[i][j]; // interval sampling Color color = new Color(pixnum); g.setColor(color); g.fillRect(X+i,Y+j,10,10); } } }
Three, renderings (using the popular heart sea expression pack)
original image
Grayscale
Black and white binary image
mosaic map