[JAVA] Image processing: Let's play with the image

Introduction

Last time I looked at how the program saves the image and displays it with the actual code. This time, let's actually bully (?) The image based on it.

Advance preparation

** Image used this time ** image.png

** Basic JAVA code **

ImageProcessing02.java


package ImageProcessing;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImageProcessing02 {
	public static void main(String[] args) {
		BufferedImage original = null;
		try {
			original = ImageIO.read(new File("image.png ")); //Bring the image to edit
		} catch (IOException e) {
			e.printStackTrace();
		}
		int iWidth = original.getWidth();				//Image width
		int iHeight = original.getHeight();				//Vertical width of the image
		int[] iColor = new int[iWidth * iHeight];		//Create an array that saves color information based on the width and height
		int[] iChangeColor = new int[iWidth * iHeight]; //Array for storing modified data of the same size
		
		//Create a BufferedImage variable to modify in advance.
		BufferedImage img = new BufferedImage(iWidth, iHeight, BufferedImage.TYPE_4BYTE_ABGR);
		
		//Bring the color information of the image with getRGB
		original.getRGB(0, 0, iWidth, iHeight, iColor, 0, iWidth);
		
		/**********************
		 *Write the code here.*
		 **********************/

		//Set the modified color information in the Buffered Image for modification
		img.setRGB(0, 0, iWidth, iHeight, iChangeColor, 0, iWidth);
		
		try {
			ImageIO.write(img, "png", new File("Path of image file to save")); //Save image
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

There are cases where the declaration statement in the middle is changed, but the basics are like this.

Image rotation

This time, we will only rotate at right angles (90 °), not 360 ° free rotation. (Because trigonometric functions are absolutely necessary to rotate freely)

** * Leave a comment only where it has changed **

ImageProcessing02_1.java


package ImageProcessing;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImageProcessing02_1 {
	public static void main(String[] args) {
		BufferedImage original = null;
		try {
			original = ImageIO.read(new File("image.png "));
		} catch (IOException e) {
			e.printStackTrace();
		}
		int iWidth = original.getWidth();
		int iHeight = original.getHeight();
		int[] iColor = new int[iWidth * iHeight];
		int[] iChangeColor = new int[iWidth * iHeight];
		
		original.getRGB(0, 0, iWidth, iHeight, iColor, 0, iWidth);

		//Since the width and height change depending on the situation, just declare it for the time being
		BufferedImage img = null;
		
		/**Image Rotate(Rotate 90)**/
		int iRotate = 90;                                                      //Set the turning angle
		int iRotateS = iRotate / 90;
		int iChangeWidth = 0, iChangeHeight = 0;

		//Width and height settings(0, 180,360 degrees= 0 / 90,270 degrees= 1)
		switch(iRotateS % 2) {
		case 0:
			iChangeWidth = iWidth;
			iChangeHeight = iHeight;
			break;
		case 1:
			iChangeWidth = iHeight;
			iChangeHeight = iWidth;
			break;
		}
		img = new BufferedImage(iChangeWidth, iChangeHeight, BufferedImage.TYPE_4BYTE_ABGR);
		int iTargetRow = 0, iTargetCol = 0;
		for(int i = 0; i < iChangeHeight; i++) {
			for(int j = 0; j < iChangeWidth; j++) {
				//Check the rest so that it can handle 360 ° or more
				switch(iRotateS % 4) {
				case 0: //As it is
					iTargetRow = i;
					iTargetCol = j;
					break;
				case 1: //90 °, from bottom left to top of the image
					iTargetRow = iChangeWidth - (j + 1);
					iTargetCol = i;
					break;
				case 2: //180 °, from bottom right to left of the image
					iTargetRow = iChangeHeight - (i + 1);
					iTargetCol = iChangeWidth - (j + 1);
					break;
				case 3: //270 °, from top right to bottom of the image
					iTargetRow = j;
					iTargetCol = iChangeHeight - (i + 1);
					break;
				}
				
				int iTargetIndex = (iTargetRow * iWidth) + iTargetCol;
				int iChangeIndex = (i * iChangeWidth) + j;
				iChangeColor[iChangeIndex] = iColor[iTargetIndex]; 
			}
		}

		img.setRGB(0, 0, iWidth, iHeight, iChangeColor, 0, iWidth);
		
		try {
			ImageIO.write(img, "png", new File("ImageRotate.png "));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

The coordinate indexing formula is the same as in the previous article. The most important thing in this article is coordinate calculation. It is important which color of the original image is placed where. In the case of rotation at a right angle, it is important to start from where and in which direction to read. Let's see the actual image.

** Original image ** image.png

** 90 ° rotation ** ImageRotate.png

The original image and the image rotated 90 °. The important thing here is where the 0th color in the image comes from. At 90 °, the colors from the lower right to the upper right are lined up in a straight line.

Other angles are the same, but the coordinates of the color when the angle changes in this way are calculated. It is OK if you put it according to the coordinates to be changed.

Image inversion

ImageProcessing02_2.java


package ImageProcessing;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImageProcessing02_2 {
	public static void main(String[] args) {
		BufferedImage original = null;
		try {
			original = ImageIO.read(new File("image.png "));
		} catch (IOException e) {
			e.printStackTrace();
		}
		int iWidth = original.getWidth();		
		int iHeight = original.getHeight();		
		int[] iColor = new int[iWidth * iHeight];	
		int[] iChangeColor = new int[iWidth * iHeight]; 
		
		BufferedImage img = new BufferedImage(iWidth, iHeight, BufferedImage.TYPE_4BYTE_ABGR);
		original.getRGB(0, 0, iWidth, iHeight, iColor, 0, iWidth);
		
		boolean isVerticalChange = true; //flip upside down
		boolean isHorizonChange = true; //Flip horizontal
		for(int i = 0; i < iHeight; i++) {
			for(int j = 0; j < iWidth; j++) {
				int iChangeRow = (isVerticalChange) ? iHeight - ( i + 1 ) : i; //Upside down from bottom to top
				int iChangeCol = (isHorizonChange) ? iWidth - ( j + 1 ) : j;  //Left-right reversal from rightmost to left
				int iChangeIndex = (iChangeRow * iWidth) + iChangeCol;
				
				int iTargetIndex = (i * iWidth) + j;
				
				iChangeColor[iChangeIndex] = iColor[iTargetIndex];
			}
		}
		img.setRGB(0, 0, iWidth, iHeight, iChangeColor, 0, iWidth);
		
		try {
			ImageIO.write(img, "png", new File("ImageReverse.png "));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

It's almost the same as before. Check whether it is flipped vertically or horizontally with Boolean, and change the coordinates accordingly. If both are set to true, 180 ° rotation and operation are the same.

Cut out a part of the image

ImageProcessing02_3.java


package ImageProcessing;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImageProcessing02_3 {
	public static void main(String[] args) {
		BufferedImage original = null;
		try {
			original = ImageIO.read(new File("image.png "));
		} catch (IOException e) {
			e.printStackTrace();
		}
		int iWidth = original.getWidth();		
		int iHeight = original.getHeight();		
		int[] iColor = new int[iWidth * iHeight];	
		original.getRGB(0, 0, iWidth, iHeight, iColor, 0, iWidth);
		
		//Coordinates to start cutting
		int iChangeY = 50;
		int iChangeX = 50;
		//Cut size
		int iChangeWidth = 100;
		int iChangeHeight = 100;

		//Declare an array and a BufferedImage variable based on the size to cut.
		int[] iChangeColor = new int[iChangeWidth * iChangeHeight]; 
		BufferedImage img = new BufferedImage(iChangeWidth, iChangeHeight, BufferedImage.TYPE_4BYTE_ABGR);

		//Loop based on the size to cut
		for(int i = 0; i < iChangeHeight; i++) {
			for(int j = 0; j < iChangeWidth; j++) {
				//Determine the coordinates of the color information from the coordinates where you start cutting.
				int iTargetRow = iChangeY + i;
				int iTargetCol = iChangeX + j;
				int iTargetIndex = (iTargetRow * iWidth) + iTargetCol;
				
				int iChangeIndex = (i * iChangeWidth) + j;
				
				iChangeColor[iChangeIndex] = iColor[iTargetIndex];
			}
		}

		img.setRGB(0, 0, iWidth, iHeight, iChangeColor, 0, iWidth);
		
		try {
			ImageIO.write(img, "png", new File("ImageSlice.png "));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

If you want to cut a part of the image, start from the upper left of the place where you want to cut the starting coordinates It's OK if you mix it with the size to cut out. However, if this is left as it is, the loop may go beyond the size of the image, so please try to fix it.

Divide like a puzzle

ImageProcessing02_4.java


package ImageProcessing;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImageProcessing02_4 {
	public static void main(String[] args) {
		BufferedImage original = null;
		try {
			original = ImageIO.read(new File("image.png "));
		} catch (IOException e) {
			e.printStackTrace();
		}
		int iWidth = original.getWidth();		
		int iHeight = original.getHeight();		
		int[] iColor = new int[iWidth * iHeight];	
		original.getRGB(0, 0, iWidth, iHeight, iColor, 0, iWidth);

		int iPieceW = 3; //Number of horizontal pieces
		int iPieceH = 4; //Number of vertical pieces

		//Size setting based on the number of pieces
		int iChangeWidth = iWidth / iPieceW;
		int iChangeHeight = iHeight / iPieceH;

		//Declare an array for color information as a two-dimensional array based on the size and the number of pieces
		int[][] iChangeColor = new int[iPieceW * iPieceH][iChangeWidth * iChangeHeight];

		//BufferedImage is also declared as an array
		BufferedImage[] img = new BufferedImage[iPieceW * iPieceH];
		for(int i = 0; i < img.length; i++) {
			img[i] = new BufferedImage(iChangeWidth, iChangeHeight, BufferedImage.TYPE_4BYTE_ABGR);
		}

		for(int i = 0; i < iHeight; i++) {
			int iNowY = i / iChangeHeight; //What line is the piece
			if(iNowY >= iPieceH) break;     //Exit when there is a rest and the coordinates exceed the set number
			for(int j = 0; j < iWidth; j++) {
				int iNowX = j / iChangeWidth; //How many rows are the pieces
				if(iNowX >= iPieceW) continue;     //Ignore when there is a rest and the coordinates exceed the set number

				int iChangeRow = i % iChangeHeight;
				int iChangeCol = j % iChangeWidth;
				
				int iTargetIndex = (i * iWidth) + j;
				int iChangeIndex = (iChangeRow * iChangeWidth) + iChangeCol;
				int iChangeKey = iNowY * iPieceW + iNowX;
				
				iChangeColor[iChangeKey][iChangeIndex] = iColor[iTargetIndex];
			}
		}

		img.setRGB(0, 0, iWidth, iHeight, iChangeColor, 0, iWidth);
		
		try {
			for(int i = 0; i < img.length; i++) {
				ImageIO.write(img[i], "png", new File("ImageSlice" + String.format("%03d", i) + ".png "));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

A code that divides an image evenly like an image puzzle. Declare BufferedImage as an array and divide the coordinates once more to fit the size to divide It would be easy if we could change the Key.

Image editing using getGraphics ()

ImageProcessing02_5.java


package ImageProcessing;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImageProcessing02_5 {
	public static void main(String[] args) {
		BufferedImage original = null;
		try {
			original = ImageIO.read(new File("image.png "));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//Bring the graphics of the image
		Graphics g = original.getGraphics();
		
		//Draw circles of various colors on the image.
		g.setColor(Color.RED);
		g.fillOval(70, 70, 100, 100);
		g.setColor(Color.GREEN);
		g.fillOval(20, 120, 100, 100);
		g.setColor(Color.BLUE);
		g.fillOval(70, 170, 100, 100);
		g.setColor(Color.BLACK);
		g.fillOval(120, 120, 100, 100);
		
		try {
			ImageIO.write(original, "png", new File("ImageEdit.png "));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

result ImageEdit.png

Using the Graphics library supported by JAVA Code that modifies the image using the methods in the library. You don't have to think about RGB code or coordinates so hard.

However, it does not have complicated image processing functions. Graphics alone is not enough. So, like the previous method, there are many functions that can be created just by switching the RGB code and coordinates. Please try to make it directly.

At the end

This time it's the most difficult to understand I wrote in the previous article, I've introduced some codes that use RGB code coordinate indexing, but how was it? This is one of the basics in image processing, but the basics are the most important. Let's master it well and let's enter the world of image processing!

Recommended Posts

Image processing: Let's play with the image
Play with the Processing libraries "ControlP5", "Fisica"
Let's verify the image search filter
Yes, let's preview the image. ~ part5 ~
Let's roughly implement the image preview function with Rails + refile + jQuery.
Let's make a Christmas card with Processing!
[Swift5] Round the acquired image with UIImagePicker
Check the processing contents with [rails] binding.pry
Implement the box ball system with Processing
Christmas with Processing
[LeJOS] Let's control the EV3 motor with Java
Use the Mac menu bar with Processing 3 apps
Let's play with Minishift! Easy experience of kubernetes
Image processing: The basic structure of the image read by the program
Let's understand the function!
Let's do cryptographic processing!
Background image transparency (layering the image with your favorite color)
[LeJOS] Let's remotely control the EV3 motor with Java
Control the processing flow of Spring Batch with JavaConfig.
I tried to increase the processing speed with spiritual engineering
Create a Docker image with the Oracle JDK installed (yum
Let's grasp the operation image (atmosphere) of the DI container of Spring
[Java] [Play Framework] Until the project is started with Gradle
Let's rewrite the C language assignment of the university with Node.js
Getting Started with Doma-Annotation Processing
Play with Jersey OAuth 2 client
Let's experiment with Java inlining
Java to play with Function
Let's make the app better
Change the port with SpringBoot
[Form_with] Let's unify form with form_with.
Let's operate Excel with Java! !!
The play of instantiating java.lang.Void
Spring with Kotorin --6 Asynchronous processing
Let's understand the if statement!
Let's try the S2Struts tutorial (# 3_180425)
Let's solve the roman numerals
Asynchronous processing with Shoryuken + SQS
Let's try the S2Struts tutorial (# 5_180526)
Let's try the S2Struts tutorial (# 4_180505)
Let's solve the FizzBuzz problem!
Let's understand the for-in statement!
Let's try the S2Struts tutorial (# 2_180424)
Presentation slides made with Processing
With the error Cordova-> Looper.prepare ()
Monitor the clipboard with JNA
JavaFX-Load Image in the background
I tried to implement the image preview function with Rails / jQuery
Play with the classic NGS simulation software wgsim ~ Mysterious creature Pooh ~