可根据实际情况进行修改

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Iterator;

/**
 * 有关图片的工具类
 *
 * @author johnniang
 */
public class ImageUtils {

    private ImageUtils() {
    }

    /**
     * 合并图片,默认从右下角开始堆叠
     *
     * @param fgImage 前景图片,不能为空
     * @param bgImage 背景图片,不能为空
     * @param margin  边距,单位:px
     * @return 合并后的图片
     */
    public static BufferedImage overlay(BufferedImage fgImage, BufferedImage bgImage, int margin) {
        Assert.notNull(fgImage, "foreground image must not be null");
        Assert.notNull(bgImage, "background image must not be null");

        int x = bgImage.getWidth() - fgImage.getWidth() - margin;
        int y = bgImage.getHeight() - fgImage.getWidth() - margin;

        return overlay(fgImage, bgImage, x, y);
    }


    /**
     * 合并图片,默认从右下角开始堆叠
     *
     * @param fgImage 前景图片,不能为空
     * @param bgImage 背景图片,不能为空
     * @return 合并后的图片
     */
    public static BufferedImage overlay(BufferedImage fgImage, BufferedImage bgImage) {
        return overlay(fgImage, bgImage, 0);
    }

    /**
     * 合并图片
     *
     * @param fgImage 前景图片,不能为空
     * @param bgImage 背景图片,不能为空
     * @return 返回合并后的图片
     */
    public static BufferedImage overlay(BufferedImage fgImage, BufferedImage bgImage, int x, int y) {
        Assert.notNull(fgImage, "foreground image must not be null");
        Assert.notNull(bgImage, "background image must not be null");
        Assert.isTrue(fgImage.getWidth() < bgImage.getWidth(),
                "foreground image's width must less than background image");
        Assert.isTrue(fgImage.getHeight() < bgImage.getHeight(),
                "forground image's height must less than background image");

        Graphics2D g = bgImage.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // draw background image
        g.drawImage(bgImage, 0, 0, null);

        // draw foreground image
        g.drawImage(fgImage, x, y, null);
        g.dispose();

        return bgImage;
    }

    /**
     * 缩放图片
     *
     * @param image     原图片,不能为空
     * @param zoomLevel 缩放倍数,不能小于0
     * @return 返回缩放后的图片
     */
    public static BufferedImage zoom(BufferedImage image, float zoomLevel) {
        Assert.notNull(image, "image must not be null");
        Assert.isTrue(zoomLevel > 0, "zoom level must not be less than 0");

        int newImageWidth = (int) (image.getWidth() * zoomLevel);
        int newImageHeight = (int) (image.getHeight() * zoomLevel);

        BufferedImage newImage = new BufferedImage(newImageWidth, newImageHeight, image.getType());
        Graphics2D g = newImage.createGraphics();
        g.drawImage(image, 0, 0, newImageWidth, newImageHeight, null);
        g.dispose();

        return newImage;
    }

    /**
     * 写入图片到指定位置
     *
     * @param image
     * @param filepath
     * @param extension
     * @throws IOException
     */
    public static void writeImage(BufferedImage image, String filepath, String extension) throws IOException {
        File file = new File(filepath);

        ImageIO.write(image, extension, file);
    }

    public static void writeImage(BufferedImage image, String formatName, OutputStream output) throws IOException {
        ImageIO.write(image, formatName, output);
    }

    public static BufferedImage readImage(File file) throws IOException {
        Assert.notNull(file, "file must not be null");

        return ImageIO.read(file);
    }

    public static BufferedImage readImage(InputStream inputStream) throws IOException {
        Assert.notNull(inputStream, "input stream must not be null");

        return ImageIO.read(inputStream);
    }

    public static BufferedImage readImage(byte[] buf) throws IOException {
        Assert.notNull(buf, "image byte array must not be null");

        return ImageIO.read(new ByteArrayInputStream(buf));
    }

    /**
     * 压缩图片
     *
     * @param originalImage 原始图片
     * @param quantity      压缩质量(0-1),越小质量越差
     * @return 返回新的图片
     * @throws IOException 最后写入图片的时候可能出现异常
     */
    public static BufferedImage compress(BufferedImage originalImage, float quantity) throws IOException {
        Assert.notNull(originalImage, "original image must not be null");

        Iterator<ImageWriter> imageWriterIterator = ImageIO.getImageWritersByFormatName("jpg");

        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
             ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputStream)) {

            // 获取图片写入器
            ImageWriter imageWriter = imageWriterIterator.next();

            // 设置输出流
            imageWriter.setOutput(imageOutputStream);

            // 获取图片写入参数
            ImageWriteParam param = imageWriter.getDefaultWriteParam();

            if (param.canWriteCompressed()) {
                // 设置压缩参数
                param.setCompressionMode((ImageWriteParam.MODE_EXPLICIT));
                param.setCompressionQuality(quantity);
            }

            // 正式写入压缩内容到输出流
            imageWriter.write(null, new IIOImage(originalImage, null, null), param);

            // 销毁图片写入器
            imageWriter.dispose();

            // 读取输出流到图片
            return readImage(outputStream.toByteArray());
        }
    }
}