Problem background:
When uploading pictures on the mobile phone and printing watermarks in the background, it was found that the pictures were flipped 90 degrees, and the picture upload in the window was indeed displayed normally.
Solution:
1. Reference dependencies:
<dependency> <groupId>com.drewnoakes</groupId> <artifactId>metadata-extractor</artifactId> <version>2.7.2</version> </dependency>
2. Obtain the flip angle of the image, correct it, add a watermark, and upload it to the file server
/** * Get the image rotation angle (photos uploaded on the mobile phone) * * @param inputStream image stream * @return */ private static int getAngle(InputStream inputStream) throws Exception { Metadata metadata = ImageMetadataReader.readMetadata(inputStream); for (Directory directory : metadata.getDirectories()) { for (Tag tag : directory.getTags()) { if ("Orientation".equals(tag.getTagName())) { String orientation = tag.getDescription(); if (orientation.contains("90")) { return 90; } else if (orientation.contains("180")) { return 180; } else if (orientation.contains("270")) { return 270; } } } } return 0; }@Override public String setWaterMarkAndUpload(MultipartFile file, String type, String address) throws IOException, NoSuchAlgorithmException { if (ObjectUtils.isEmpty(type)) { throw new BusinessException("Type cannot be null!"); } // Get redis watermark configuration information String key = RedisKeyConstant.wx_citizen_watermark_key + ":" + type; WxCitizenSettingWatermarkVO settingWatermarkVO = BeanUtil.toBean(JSONUtil.parse(redisService.get(key)), WxCitizenSettingWatermarkVO.class); if (ObjectUtils.isEmpty(settingWatermarkVO)) { throw new BusinessException("System watermark setting not found!"); } if (settingWatermarkVO.getDbStatus().equals("2")) { String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf(".")); String url = this.upload(file, fileName, "1", null); return url; } if (ObjectUtil.isNotEmpty(settingWatermarkVO.getWmWord()) & amp; & amp; settingWatermarkVO.getWmWord().equals("1")) { if (ObjectUtil.isEmpty(address)) { throw new BusinessException("Address cannot be empty!"); } } BufferedImage bufImg = null; try { //File full name + suffix String originalFileName = file.getOriginalFilename(); String fileName = originalFileName.substring(0, originalFileName.lastIndexOf(".")); //Suffix name String suffix = originalFileName.substring(originalFileName.lastIndexOf(".") + 1); //Determine whether the file type is an image String[] imgType = {"bmp", "jpg", "jpeg", "png", "gif"}; List<String> stringList = Arrays.asList(imgType); if (!stringList.contains(suffix.toLowerCase())) { throw new BusinessException("Wrong file type, please select a picture type file"); } //Data flow conversion storage (to prevent flow failure) InputStream inputStream = file.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024 * 1024]; int len; while ((len = inputStream.read(buffer)) > -1) { baos.write(buffer, 0, len); } baos.flush(); // Get the image rotation angle InputStream metadataInputStream = new ByteArrayInputStream(baos.toByteArray()); int angle = getAngle(metadataInputStream); //Get the source image bytes (for use when watermark is not turned on) byte[] imgBuffer = baos.toByteArray(); InputStream stream = new ByteArrayInputStream(baos.toByteArray()); //Get the source image (for use when turning on watermark) Image srcImg = ImageIO.read(stream); //Whether the wrong picture needs to be corrected boolean isCorrectImg = false; //Source image width and height int imgWidth = 0; int imgHeight = 0; if (angle == 90 || angle == 270) { isCorrectImg = true; imgWidth = srcImg.getHeight(null); imgHeight = srcImg.getWidth(null); } else { isCorrectImg = false; imgWidth = srcImg.getWidth(null); imgHeight = srcImg.getHeight(null); } // horizontal offset int devLevel = 0; // vertical offset int devVertical = 0; // watermark transparency float alpha = 1f; //Watermark horizontal position int positionWidth = 10; //Watermark vertical position int positionHeight = 20; //Watermark text color String colorText = settingWatermarkVO.getColor(); final String[] colors = colorText.replace("rgb", "").replace("(", "").replace(")", "").replace(" ", "").split(" ,"); List<String> strings = Arrays.asList(colors); List<Integer> collect = strings.stream().map(p -> Integer.valueOf(p)).collect(Collectors.toList()); Color color = new Color(collect.get(0), collect.get(1), collect.get(2)); //Format time SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time = simpleDateFormat.format(new Date()); //Text to be printed List<String> texts = new ArrayList<>(); //watermark text switch (settingWatermarkVO.getWmWord()) { case "1": // address + time //Remove the address and ignore the content if (ObjectUtil.isNotEmpty(settingWatermarkVO.getAddressIgnoreText())) { address = address.replace(settingWatermarkVO.getAddressIgnoreText(), ""); } texts.add(address); texts.add(time); break; case "2": // time texts.add(time); break; default: throw new BusinessException("Wrong text type"); } bufImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB); //Watermark text font Font font = new Font("宋体", Font.BOLD, settingWatermarkVO.getSize()); //Add text watermark mark(bufImg, srcImg, texts, font, color, imgWidth, imgHeight, settingWatermarkVO.getImgPosition(), isCorrectImg, angle); //Image flow byte stream ByteArrayOutputStream out = new ByteArrayOutputStream(); ImageIO.write(bufImg, suffix, out); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(out.toByteArray()); out.close(); //Upload to file server String url = this.upload(byteArrayInputStream, file.getContentType(), suffix, fileName, "0"); System.out.println("url:" + url); return url; } catch (Exception ex) { ex.printStackTrace(); throw new BusinessException(ex.getMessage()); } finally { if (bufImg != null) { bufImg.getGraphics().dispose(); } } }/** * Add text watermark * @param bufImg * @param img * @param texts * @param font * @param color * @param x * @param y */ public static void mark(BufferedImage bufImg, Image img, List<String> texts, Font font, Color color, int x, int y, String position, boolean isCorrectImg, int angle) { Graphics2D g = bufImg.createGraphics(); //Create a FontMetrics object FontMetrics fm = g.getFontMetrics(font); int textHeight = fm.getHeight(); //Find the longest character in the watermark String longest = texts.stream() .max(Comparator.comparingInt(String::length)) .orElse(""); int textWidth = fm.stringWidth(longest); int positionWidth = textWidth; int positionHeight = textHeight; //Set the location to print switch (position) { case "upper left": positionWidth = 0; positionHeight = 0 + textHeight; break; case "upper right": positionWidth = x - textWidth; positionHeight = textHeight; break; case "upper middle": positionWidth = (x - textWidth) / 2; positionHeight = textHeight; break; case "center": positionWidth = (x - textWidth) / 2; positionHeight = (y + textHeight) / 2; break; case "left center": positionWidth = 0; positionHeight = (y + textHeight) / 2; break; case "right center": positionWidth = x - textWidth; positionHeight = (y + textHeight) / 2; break; case "lower left": positionWidth = 0; positionHeight = y - textHeight; break; case "lower middle": positionWidth = (x - textWidth) / 2; positionHeight = y - textHeight; break; case "lower right": positionWidth = x - textWidth; positionHeight = y - textHeight; break; default: positionWidth = x - textWidth; positionHeight = y - textHeight; break; } //When there is a flipping problem in the image uploaded on the mobile phone, correct the position if (isCorrectImg) { // Center point position double centerWidth = ((double) x) / 2; double centerHeight = ((double) y) / 2; g.rotate(Math.toRadians(angle), centerWidth, centerHeight); g.drawImage(img, (x - img.getWidth(null)) / 2, (y-img.getHeight(null)) / 2, null); g.rotate(Math.toRadians(-angle), centerWidth, centerHeight); } else { g.drawImage(img, 0, 0, bufImg.getWidth(), bufImg.getHeight(), null); } g.setColor(color); g.setFont(font); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1f)); int size = font.getSize(); for (int i = 0; i < texts.size(); i + + ) { g.drawString(texts.get(i), positionWidth, positionHeight-size*i); } g.dispose(); }