Java corrects the problem of automatic rotation and mirroring of uploaded images
When you encounter a picture, it looks like the direction is positive, but it automatically rotates and mirrors after you open it with a specific tool.
After checking out this article: https://www.cnblogs.com/csonezp/p/5564809.html.
A sentence in the original text:It turns out that the camera adds an Orientation to the exif information of the picture, and then the picture browser will make compatibility with this attribute, so that the picture will be displayed in the form of a vertical picture. Let me give some explanations about the Orientation attribute.
Why do we see it correct on some software or browsers? It’s because these software and browsers automatically correct the picture.
However, our Java does not automatically correct this picture for us. When we useBufferImage
to draw a picture, we find that the height is actually the opposite.
How to solve it?
Introduction
<dependency> <groupId>com.drewnoakes</groupId> <artifactId>metadata-extractor</artifactId> <version>2.7.0</version> </dependency>
This package can help me get the exif information of the image.
///1. Get the metadata of the image Metadata metadata = ImageMetadataReader.readMetadata(file); // 2. The direction of image metadata processing int orientation = 0; for (Directory directory : metadata.getDirectories()) {<!-- --> // 3. Only the data of TAG_ORIENTATION is needed. if(directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)){<!-- --> for (Tag tag : directory.getTags()) {<!-- --> System.out.println(tag); } orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION); } } // Output [Exif IFD0] Orientation - Right side, top (Rotate 90 CW)
Understanding
EXIF Orientation Value | Row #0 is: | Column #0 is: | The corresponding direction should How to correct |
---|---|---|---|
1 | Top | Left side | No need to correct |
2 | Top | Right side | Flip horizontally (mirror) |
3 | Bottom | Right side | Vertical flip (rotate 180°) |
4 | Bottom | Left side | Flip horizontally + flip vertically |
5 | Left side | Top | Flip horizontally + rotate 90° |
6 | Right side | Top | Rotate 90° |
7 | Right side | Bottom | Flip horizontally + rotate 270° |
8 | Left side | Bottom | + rotate 270° |
You can refer to the figure below to understand
Implementation
public class ImageRotate {<!-- --> /** * How to correct pictures * * @param srcImgPath */ /** * Correct image rotation * * @param srcImgPath */ public static void correctImg(String srcImgPath) {<!-- --> FileOutputStream fos = null; try {<!-- --> // Original Image File srcFile = new File(srcImgPath); // 1. Get correction RectifyDirection rotateAngle = getRectifyDirection(srcFile); // 2. Return directly without correction if(rotateAngle == null){<!-- --> return; } System.out.println(rotateAngle.angel + ":" + rotateAngle.isMirror); // original image cache BufferedImage srcImg = ImageIO. read(srcFile); // original width int imgWidth = srcImg. getWidth(); // original height int imgHeight = srcImg. getHeight(); // 3. If it is not vertical, it means that their width and height need to be swapped if (rotateAngle. angel != 180) {<!-- --> int temp = imgWidth; imgWidth = imgHeight; imgHeight = temp; } // Center point position double centerWidth = ((double) imgWidth) / 2; double centerHeight = ((double) imgHeight) / 2; //Image cache BufferedImage targetImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB); // Rotate the corresponding angle Graphics2D g = targetImg.createGraphics(); // 4. Rotate to the left based on the center point position g.rotate(Math.toRadians(rotateAngle.angel), centerWidth, centerHeight); // 5. After rotation, the width and height of the image will be replaced again. System.out.println(srcImg.getWidth()); System.out.println(srcImg.getHeight()); // 6. Here you need to find the original width and height after replacement and the existing width and height, and draw the picture from this coordinate int x = (imgWidth - srcImg.getWidth()) / 2; int y = (imgHeight - srcImg.getHeight()) / 2; g.drawImage(srcImg, x, y, null); g.dispose(); // 7. Do you need to flip horizontally? if (rotateAngle.isMirror){<!-- --> BufferedImage tempImage = new BufferedImage(targetImg.getWidth(), targetImg.getHeight(), BufferedImage.TYPE_INT_RGB); g = tempImage.createGraphics(); // Use AffineTransform for horizontal flipping AffineTransform transform = new AffineTransform(); // 8. After panning the width of the current picture transform.translate(targetImg.getWidth() , 0); // 9. Zoom // Because the abscissa scale is -1, it is flipped horizontally // See the horizontal flipping picture for the flipping process. transform. scale(-1, 1); g.setTransform(transform); g.drawImage(targetImg,0, 0, null); g. dispose(); targetImg = tempImage; } // output image fos = new FileOutputStream(new File(srcFile.getAbsolutePath() + "." + srcImgPath.substring(srcImgPath.lastIndexOf(".") + 1))); ImageIO.write(targetImg, srcImgPath.substring(srcImgPath.lastIndexOf(".") + 1), fos); } catch (Exception e) {<!-- --> e.printStackTrace(); } finally {<!-- --> if (fos != null) {<!-- --> try {<!-- --> fos. flush(); fos. close(); } catch (Exception e) {<!-- --> e.printStackTrace(); } } } } /** * Get correct direction * @param file * @return * @throwsException */ public static RectifyDirection getRectifyDirection(File file) throws Exception {<!-- --> // 1. Get the metadata of the image Metadata metadata = ImageMetadataReader.readMetadata(file); // 2. The direction of image metadata processing int orientation = 0; for (Directory directory : metadata.getDirectories()) {<!-- --> // 3. Only the data of TAG_ORIENTATION is needed. if(directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)){<!-- --> for (Tag tag : directory.getTags()) {<!-- --> System.out.println(tag); } orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION); } } // 4. Create different processing methods according to different orientations switch (orientation){<!-- --> case 2: return new RectifyDirection(0,true); case 3: return new RectifyDirection(180,false); case 4: return new RectifyDirection(180, true); case 5: return new RectifyDirection(90,true); case 6: return new RectifyDirection(90,false); case 7: return new RectifyDirection(270,true); case 8: return new RectifyDirection(270,false); default: return null; } } \t static class RectifyDirection{<!-- --> /** * angle */ public int angel; /** * Whether to mirror */ public boolean isMirror; public RectifyDirection(int angel, boolean isMirror) {<!-- --> this.angel = angel; this.isMirror = isMirror; } } }