JAVA 实现对图片的压缩、拼接功能

Java
211
0
0
2023-12-14

上周刚做好一个大头贴功能,使用的腾讯AI平台对图片的处理API接口,实现一张照片根据四张模板生成四张处理的特效照片,然后后台处理拼接成一张图片,可以用照片打印机打印出6寸的照片,效果还不错。坑爹的是今天调试发现接口调用不通了,腾讯AI平台不提供该接口了,好几天的工作量白费了。不过还是把最近写的一些代码整理一下,把一些功能放上来,以后用得上。

功能实现的逻辑:由于接口限制图片大小,所以先对上传的图片进行压缩,然后将四张图片拼接成一张图片保存(效果图如下);

JAVA 实现对图片的压缩、拼接功能


图片处理工具类:

 package org.plusgroup.modules.admin.service;

import net.coobird.thumbnailator.Thumbnails;
import org.slfj.Logger;
import org.slfj.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.*;
import java.util.UUID;

/**
 * @author Administrator
 * @desc  图片操作类
 * @date/7/12 09:00
 */public class ImageUtils {

    private static Logger logger = LoggerFactory.getLogger(org.plusgroup.common.utils.ImageUtils.class);

    /**
     * 文件转byte []
     * @param filePath 文件地址
     * @return byte[]
     */    public static byte[] getBytesByFile(String filePath) {
        try {
            File file=new File(filePath);
            //获取输入流
            FileInputStream fis = new FileInputStream(file);

            //新的 byte 数组输出流,缓冲区容量byte
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            //缓存
            byte[] b = new byte[];
            int n;
            while ((n = fis.read(b)) != -) {
                bos.write(b,, n);
            }
            fis.close();
            //改变为byte[]
            byte[] data = bos.toByteArray();
            //
            bos.close();
            return data;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据指定大小压缩图片
     * @param imageBytes  源图片字节数组
     * @param desFileSize 指定图片大小,单位kb
     * @return 压缩质量后的图片字节数组
     */    public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) {
        if (imageBytes == null || imageBytes.length <= || imageBytes.length < desFileSize * 1024) {
            return imageBytes;
        }
        long srcSize = imageBytes.length;
        double accuracy = getAccuracy(srcSize /);
        try {
            while (imageBytes.length > desFileSize *) {
                ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
                Thumbnails.of(inputStream).scale(.99).outputQuality(0.99).toOutputStream(outputStream);
                imageBytes = outputStream.toByteArray();
            }
            logger.info(" 图片原大小={}kb | 压缩后大小={}kb", srcSize /, imageBytes.length / 1024);
        } catch (Exception e) {
            logger.error("【图片压缩】msg=图片压缩失败!", e);
        }
        return imageBytes;
    }

    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */    private static double getAccuracy(long size) {
        double accuracy;
        if (size <) {
            accuracy =.85;
        } else if (size <) {
            accuracy =.6;
        } else if (size <) {
            accuracy =.44;
        } else {
            accuracy =.4;
        }
        return accuracy;
    }

    /**
     * 保存图片到本地
     * @param path 地址
     * @param bfile 文件流
     */    public static void uploadLocal(String path, byte[] bfile) {
        String fileName = UUID.randomUUID().toString().trim().replaceAll("-", "") + ".png";
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(path);
            boolean isDir = dir.isDirectory();
            if (!isDir) {// 目录不存在则先建目录
                try {
                    dir.mkdirs();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            file = new File(path + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bfile);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 四张同高度宽度的图片合成。
     * mergeImage方法不做判断,自己判断。
     *
     * @param imgByte     第一张图
     * @param imgByte     第二张图
     * @param imgByte     第三张图
     * @param imgByte     第四张图
     * @return 返回合并后的BufferedImage对象
     */    public static byte[] mergeFourImage(byte[] imgByte, byte[] imgByte2,byte[] imgByte3,byte[] imgByte4, String imgFormat) throws IOException {
        BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgByte1));
        BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgByte2));
        BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgByte3));
        BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgByte4));
        //获取图片的宽高
        int w = img1.getWidth(null);
        int h = img1.getHeight(null);

        int w = img2.getWidth(null);
        int h = img2.getHeight(null);

        int w = img3.getWidth(null);
        int h = img3.getHeight(null);

        int w = img4.getWidth(null);
        int h = img4.getHeight(null);

        // 从图片中读取RGB
        int[] ImageArrayOne = new int[w * h1];
        // 逐行扫描图像中各个像素的RGB到数组中
        ImageArrayOne = img.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1);

        int[] ImageArrayTwo = new int[w * h2];
        ImageArrayTwo = img.getRGB(0, 0, w2, h2, ImageArrayTwo, 0, w2);

        int[] ImageArray = new int[w3 * h3];
        ImageArray = img3.getRGB(0, 0, w3, h3, ImageArray3, 0, w3);

        int[] ImageArray = new int[w4 * h4];
        ImageArray = img4.getRGB(0, 0, w4, h4, ImageArray4, 0, w4);

        // 生成新图片
        BufferedImage destImg = new BufferedImage(w + w2 + 5, h1 + h2 + 5, BufferedImage.TYPE_INT_RGB);
        destImg.setRGB(, 0, w1, h1, ImageArrayOne, 0, w1);
        destImg.setRGB(w + 5, 0, w2, h2, ImageArrayTwo, 0, w2);

        destImg.setRGB(, h1 + 5, w3, h3, ImageArray3, 0, w3);
        destImg.setRGB(w + 5, h1 +5, w4, h4, ImageArray4, 0, w4);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(destImg, imgFormat, out);
        return out.toByteArray();
    }


    /**
     * 图片缩放  (压缩不理想可选)宽高选择 560  (优先选择)等比例缩放 720 960
     * @param srcImg     原图片
     * @param destImg    目标位置
     * @param width      期望宽
     * @param height     期望高
     * @param equalScale 是否等比例缩放
     * @return long 返回文件的大小
     */    public static long reSize(File srcImg, File destImg, int width, int height, boolean equalScale) {
        String type = getImageType(srcImg);
        if (type == null) {
            return;
        }
        if (width < || height < 0) {
            return;
        }

        BufferedImage srcImage = null;
        try {
            srcImage = ImageIO.read(srcImg);
            System.out.println("srcImg size=" + srcImage.getWidth() + "X" + srcImage.getHeight());
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        // targetW,targetH分别表示目标长和宽
        BufferedImage target = null;
        double sx = (double) width / srcImage.getWidth();
        double sy = (double) height / srcImage.getHeight();
        // 等比缩放
        if (equalScale) {
            if (sx > sy) {
                sx = sy;
                width = (int) (sx * srcImage.getWidth());
            } else {
                sy = sx;
                height = (int) (sy * srcImage.getHeight());
            }
        }
        System.out.println("destImg size=" + width + "X" + height);
        ColorModel cm = srcImage.getColorModel();
        WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
        boolean alphaPremultiplied = cm.isAlphaPremultiplied();

        target = new BufferedImage(cm, raster, alphaPremultiplied, null);
        GraphicsD g = target.createGraphics();

        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.drawRenderedImage(srcImage, AffineTransform.getScaleInstance(sx, sy));
        g.dispose();

        // 将转换后的图片保存
        try {
            ByteArrayOutputStream baas = new ByteArrayOutputStream();
            ImageIO.write(target, type, baas);
            FileOutputStream fos = new FileOutputStream(destImg);
            fos.write(baas.toByteArray());

            fos.flush();
            fos.close();

            System.out.println("图片大小:"+destImg.length());
            return destImg.length();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return;
    }
    /**
     * 获取文件后缀不带.
     * @param file 文件后缀名
     * @return String
     */    private static String getImageType(File file) {
        if (file != null && file.exists() && file.isFile()) {
            String fileName = file.getName();
            int index = fileName.lastIndexOf(".");
            if (index != - && index < fileName.length() - 1) {
                return fileName.substring(index +);
            }
        }
        return null;
    }

}

测试类:

 package org.plusgroup.modules.admin.service;



import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author Administrator
 * @desc   生成大头贴
 * @date/7/12 09:41
 */public class ImageTest {


    public static void main(String[] args) throws Exception {
        //等比例缩小图片
        reSizePhoto();
        //拼接四张图片
        margeFourPhoto();
    }
    /**
     * 压缩图片至指定大小之下
     */    public static void zipPic(){
        byte[] imgByte = ImageUtils.getBytesByFile("C:/Users/Public/Pictures/Sample Pictures/temp/temp101.png");
        byte[] destImg = ImageUtils.compressPicForScale(imgByte,500);
        //图片保存至本地
        ImageUtils.uploadLocal("C:/Users/Public/Pictures/Sample Pictures/temp/temp.png",destImg);
    }
    /**
     * 等比例缩小图片
     */    public static void reSizePhoto(){
        File srcImg = new File("C:/Users/Public/Pictures/Sample Pictures/temp/temp.png");
        File destImg = null;
        for(int i=;i<=2;i++){
            destImg = new File("C:/Users/Public/Pictures/Sample Pictures/temp/temp"+i+".png");
            //宽高选择 560 等比例缩放 720 960
            ImageUtils.reSize(srcImg,destImg,,960,true);
        }
    }

    /**
     * 拼接四张图片(寸照片)
     */    public static void margeFourPhoto() throws IOException {
        byte[] imgByte = ImageUtils.getBytesByFile("C:/Users/Public/Pictures/Sample Pictures/temp/temp101.png");
        byte[] imgByte = ImageUtils.getBytesByFile("C:/Users/Public/Pictures/Sample Pictures/temp/temp102.png");
        byte[] imgByte = ImageUtils.getBytesByFile("C:/Users/Public/Pictures/Sample Pictures/temp/temp103.png");
        byte[] imgByte = ImageUtils.getBytesByFile("C:/Users/Public/Pictures/Sample Pictures/temp/temp104.png");

        byte[] destImg = ImageUtils.mergeFourImage(imgByte,imgByte2,imgByte3,imgByte4,"png");

        ImageUtils.uploadLocal("C:/Users/Public/Pictures/Sample Pictures/temp/temp.png",destImg);
    }
}

等腾讯接口恢复了,在把调用接口生成大头贴的代码发上来!