thumbnailator压缩图片添加水印cmyk格式图片转换,图片位深度,gif图片

发布时间:2023年12月26日

Thumbnailator官网

https://mvnrepository.com/artifact/net.coobird/thumbnailator

thumbnailator 简介

humbnailator 是一个开源的 Java 项目,它提供了非常简单的 API 来对图片进行缩放、旋转以及加水印的处理。

POM文件

  <!--处理水印和图片缩放-->
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.17</version>
        </dependency>
        <!-- java gif 添加水印功能 library -->
        <dependency>
            <groupId>com.madgag</groupId>
            <artifactId>animated-gif-lib</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- cmyk格式图片转换 -->
        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-jpeg</artifactId>
            <version>3.9.4</version>
        </dependency>
        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-tiff</artifactId>
            <version>3.9.4</version>
        </dependency>

创建 ImagesUtil 处理图片压缩和添加水印

import com.zkjw.cms.common.utils.token.Base64;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/***
 * 对图片进行操作
 * @author liuhongrong
 * @since 2011/7/29
 *
 */
public class ImagesUtil {

    private static Logger logger= LoggerFactory.getLogger(ImagesUtil.class);

    /**
     * 允许上传图片格式
     */
    public static String[] ImagesType=new String[] {"png", "jpg", "jpeg", "bmp", "gif","svg"};

    /**
     * 根据扩展名判断是否为图片
     */
    public static boolean extCheckImages(String fileNamefix){
        if(StringUtils.isNotEmpty(fileNamefix)){
            return ArrayUtil.contains(ImagesType,fileNamefix);
        }else{
            return false;
        }
    }

    /**
     * 添加水印
     * @param originImgPath  路径
     * @param positions 水印位置
     * @param markImgPath 水印图片
     */
    public static boolean markWater(String originImgPath,Positions positions,String markImgPath){
        //准备画板
        BufferedImage originImg = null; //判断原图是否存在
        BufferedImage markImg = null; //判断水印是否存在
        try {
            originImg = ImageIO.read(new File(originImgPath));
            markImg = ImageIO.read(new File(markImgPath));
            Thumbnails.of(originImgPath).size(originImg.getWidth(),originImg.getHeight()).watermark(positions, markImg, 0.8f)
                    .outputQuality(1f).toFile(originImgPath);
            return true;
        } catch (IOException e) {
            logger.error("图片添加水印",e);
            return false;
        }
    }

    /***
     * 将图片缩放到指定的高度或者宽度
     * @param sourceImagePath 图片源地址
     * @param destinationPath 压缩完图片的地址
     * @param width 缩放后的宽度
     * @param fileType 图片类型
     */
    public static void scaleImageWithParams(String sourceImagePath,String destinationPath, Integer width, String fileType){

        if(("gif").equals(fileType)) {
            /**
             * gif压缩图片,压缩gif越来越大不做处理
             */
//            ImagesGifOperatorUtil.scaleImageWithParams(new File(sourceImagePath),new File(destinationPath), width);
        }else {
            try {
                sourceImagePath = FileUtil.getpathurl(sourceImagePath, 1);
                //判断是否为图片文件
                if (getispic(sourceImagePath)) {
                    BufferedImage bufferedImage = ImageIO.read(new File(sourceImagePath));
                    int height = bufferedImage.getHeight();
                    if (width == null) {
                        width = bufferedImage.getWidth();
                    }
                    //获取位深度
                    ColorModel color = bufferedImage.getColorModel();
                    if (color.getPixelSize() <= 16) {
                        zoomImageScale(sourceImagePath, destinationPath, width);
                    } else {
                        /*
                         * size(width,height) 若图片横比200小,高比300小,不变
                         * 若图片横比200小,高比300大,高缩小到300,图片比例不变 若图片横比200大,高比300小,横缩小到200,图片比例不变
                         * 若图片横比200大,高比300大,图片按比例缩小,横为200或高为300
                         *  outputQuality: 输出的图片质量,范围:0.0~1.0,1为最高质量.
                         */
                        Thumbnails.of(sourceImagePath).size(width, height).outputQuality(1.0f).toFile(destinationPath);
                    }
                } else {
                    logger.error(sourceImagePath + "不是一张有效图片");
                }
            } catch (Exception e) {
                logger.error("发布时:将图片缩放到指定的高度或者宽度报错", e);
            }
        }
    }

    /***
     * 将图片缩放到指定的高度或者宽度
     * @param sourceImagePath 图片源地址
     * @param destinationPath 压缩完图片的地址
     * @param width 缩放后的宽度
     * @param fileType 图片类型
     */
    public static void scaleImageWithParams(File sourceImagePath,File destinationPath, Integer width, String fileType){

        if(("gif").equals(fileType)) {
            /**
             * gif压缩图片,压缩gif越来越大不做处理
             */
//            ImagesGifOperatorUtil.scaleImageWithParams(sourceImagePath,destinationPath, width);
        }else{
            boolean f = false;
            BufferedImage bufferedImage=null;
            //判断是否为图片文件
            try {
                bufferedImage= ImageIO.read(sourceImagePath);
                if(bufferedImage == null){
                    f = false;
                }else {
                    f = true;
                }
            } catch (IOException e) {
                logger.error(sourceImagePath+"不是一张有效图片",e);
            }
            try{
                if(f){
                    int height=bufferedImage.getHeight();
                    if(width == null){
                        width=bufferedImage.getWidth();
                    }
                    //获取位深度
                    ColorModel color = bufferedImage.getColorModel();
                    if(color.getPixelSize() <= 16){
                        zoomImageScale(sourceImagePath.getPath(), destinationPath.getPath(), width);
                    }else{
                        /*
                         * size(width,height) 若图片横比200小,高比300小,不变
                         * 若图片横比200小,高比300大,高缩小到300,图片比例不变 若图片横比200大,高比300小,横缩小到200,图片比例不变
                         * 若图片横比200大,高比300大,图片按比例缩小,横为200或高为300
                         *  outputQuality: 输出的图片质量,范围:0.0~1.0,1为最高质量.
                         */
                        Thumbnails.of(sourceImagePath).size(width,height).outputQuality(1.0f).toFile(destinationPath);
                    }
                }
            }catch (Exception e){
                logger.error("发布时:将图片缩放到指定的高度或者宽度报错",e);
            }
        }
    }

    /**
     * 判断是否为图片文件
     * @param filePath
     * @return
     */
    public static boolean getispic(String filePath){
        boolean f = false;
        File file = new File(filePath);
        try {
            BufferedImage bi = ImageIO.read(file);
            if(bi == null){
                f = false;
            }else {
                f = true;
            }
        } catch (IOException e) {
            f = false;
        }
        return f;
    }


    /**
     * 处理 图片位深度:8位的图片,会自动压缩成32位深度的图片
     * 按指定宽度 等比例缩放图片
     * @param oldPath  需要压缩图片的路径
     * @param newPath  新路径
     * @param newWidth  新图的宽度
     * @throws IOException
     */
    public static void zoomImageScale(String oldPath, String newPath, int newWidth) throws IOException {
        File imageFile =new File(oldPath);
        if (!imageFile.canRead()){
            return;
        }
        BufferedImage bufferedImage = ImageIO.read(imageFile);
        if (null == bufferedImage){
            return;
        }
        int originalWidth = bufferedImage.getWidth();
        int originalHeight = bufferedImage.getHeight();
        double scale = (double) originalWidth / (double) newWidth; // 缩放的比例
        int newHeight = (int) (originalHeight / scale);
        zoomImageUtils(imageFile, newPath, bufferedImage, newWidth, newHeight);
    }

    private static void zoomImageUtils(File imageFile, String newPath, BufferedImage bufferedImage, int width, int height) throws IOException {

        String suffix = StringUtils.substringAfterLast(imageFile.getName(), ".");

        // 处理 png 背景变黑的问题
        if (suffix != null && (suffix.trim().toLowerCase().endsWith("png") || suffix.trim().toLowerCase().endsWith("gif"))) {
            BufferedImage to = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = to.createGraphics();
            to = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
            g2d.dispose();

            g2d = to.createGraphics();
            Image from = bufferedImage.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING);
            g2d.drawImage(from, 0, 0, null);
            g2d.dispose();

            ImageIO.write(to, suffix, new File(newPath));
        } else {

            BufferedImage newImage = new BufferedImage(width, height, bufferedImage.getType());
            Graphics g = newImage.getGraphics();
            g.drawImage(bufferedImage, 0, 0, width, height, null);
            g.dispose();
            ImageIO.write(newImage, suffix, new File(newPath));
        }
    }






//--------------------------------------------图片生成Base64字符串----------------------------------------------------------------


    /**
     * 将图片生成Base64字符串,可以直接在网页展示
     * @return boolean
     * @throws null
     */
    public static String base64ImageHtml(String base64Data,String ext){
        StringBuffer sb=new StringBuffer(1000);
        sb.append("data:image/").append(ext);
        sb.append(";base64,").append(base64Data);
        return sb.toString();
    }

    /**
     * 转换base64
     * @param srcImagePath 要进行压缩的文件全路径
     * @return 返回压缩后的文件的全路径
     * @throws IOException
     */
    public static String reduceWidthHeightImageAndToBase64(String srcImagePath){
        try {
            File file=new File(srcImagePath);
            if(file.exists()){
                BufferedImage bi=ImageIO.read(file);
                byte[] bytes=null;
                ByteArrayOutputStream out=new ByteArrayOutputStream();
                bytes = out.toByteArray();
                return Base64.encode(bytes);
            }else{
                logger.info("找不到文件:"+srcImagePath);
                return StringUtil.EMPTY;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

}

处理GIF ImagesGifOperatorUtil

import com.madgag.gif.fmsware.AnimatedGifEncoder;
import com.madgag.gif.fmsware.GifDecoder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
 * @author liuhongrong
 * @description 压缩GIF
 * @desc 压缩GIF
 * @since 2023/4/10 10:20
 */
public class ImagesGifOperatorUtil {

    public static void main(String[] args) throws IOException {

        String outputPath = "/home/lab/test/001.gif";
        String imagePath = "/home/lab/test/33.gif";
        reverseGif(imagePath,outputPath, 1280,760);
    }

    /**
     * 4096异常。在过去的几年里,处理GIF图像时可能遇到过这个问题
     * @param sourceImagePath
     * @param destinationPath
     * @param width
     */
    public static void scaleImageWithParams(File sourceImagePath,File destinationPath, Integer width) {
        /**
         * gif压缩图片
         */
        try {
            //使用hutool工具类GifDecoder读取gif获取上传图片的宽和高
            GifDecoder gifDecoder = new GifDecoder();
            InputStream inputStream=new FileInputStream(sourceImagePath);
            gifDecoder.read(inputStream);
            BufferedImage sourceImage = gifDecoder.getImage();
            int height=sourceImage.getHeight();
            if(width == null){
                width=sourceImage.getWidth();
            }
            ImagesGifOperatorUtil.reverseGif(sourceImagePath.getPath(),destinationPath.getPath(),width,height);
        }catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    

    /**
     * 压缩GIF
     * @param imagePath
     * @param outputPath
     * @throws IOException
     */
    public static void reverseGif(String imagePath,String outputPath, Integer width, Integer height) throws IOException {
        GifDecoder decoder = new GifDecoder();
        int status = decoder.read(imagePath);
        if (status != GifDecoder.STATUS_OK) {
            throw new IOException("read image " + imagePath + " error!");
        }
        // 拆分一帧一帧的压缩之后合成
        AnimatedGifEncoder encoder = new AnimatedGifEncoder();
        encoder.start(outputPath);
        encoder.setRepeat(decoder.getLoopCount());
        for (int i = 0 ; i < decoder.getFrameCount(); i++) {
            encoder.setDelay(decoder.getDelay(i));// 设置播放延迟时间
            BufferedImage bufferedImage = decoder.getFrame(i);// 获取每帧BufferedImage流
//            int height = bufferedImage.getHeight();
            int widthsrc = bufferedImage.getWidth(); //原图片宽度
            if(widthsrc <= width){ //原图片宽度小于指定的宽度
                width=widthsrc;
            }
            BufferedImage zoomImage = new BufferedImage(width, height, bufferedImage.getType());
            Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            Graphics gc = zoomImage.getGraphics();
            gc.setColor(Color.WHITE);
            gc.drawImage(image, 0, 0, null);
            encoder.addFrame(zoomImage);
        }
        encoder.finish();
        File outFile = new File(outputPath);
        BufferedImage image = ImageIO.read(outFile);
        ImageIO.write(image, outFile.getName(), outFile);
    }


    /**
     * 多图片转gif
     * @param imageList
     * @param outputPath
     * @throws IOException
     */
    static void imagesToGif(List<BufferedImage> imageList, String outputPath) throws IOException {
        // 拆分一帧一帧的压缩之后合成
        AnimatedGifEncoder encoder = new AnimatedGifEncoder();
        encoder.start(outputPath);
        encoder.setRepeat(0);
        for (BufferedImage bufferedImage :
                imageList) {
            encoder.setDelay(100);
            int height = bufferedImage.getHeight();
            int width = bufferedImage.getWidth();
            BufferedImage zoomImage = new BufferedImage(width, height, 3);
            Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            Graphics gc = zoomImage.getGraphics();
            gc.setColor(Color.WHITE);
            gc.drawImage(image, 0, 0, null);
            encoder.addFrame(zoomImage);
        }
        encoder.finish();
        File outFile = new File(outputPath);
        BufferedImage image = ImageIO.read(outFile);
        ImageIO.write(image, outFile.getName(), outFile);
    }

    /**
     * Gif转图片集
     * @param imagePath
     * @param outputDirPath
     * @throws IOException
     */
    static void gifToImages(String imagePath,String outputDirPath) throws IOException {
        GifDecoder decoder = new GifDecoder();
        int status = decoder.read(imagePath);
        if (status != GifDecoder.STATUS_OK) {
            throw new IOException("read image " + imagePath + " error!");
        }
        for (int i = 0; i < decoder.getFrameCount();i++) {
            BufferedImage bufferedImage = decoder.getFrame(i);// 获取每帧BufferedImage流
            File outFile = new File(outputDirPath + i + ".png");
            ImageIO.write(bufferedImage, "png", outFile);
        }
    }


}
文章来源:https://blog.csdn.net/qq_20025777/article/details/135213492
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。