Bootstrap

java生成图片缩略图

前言

下面介绍了两种获取图片缩略图的方式,全都不是一次性压缩,如果没有达到设置的压缩范围,图片会循环压缩,大家根据自己的需求,可以自己调节最大缩略图的大小范围。

经过测试第二种方式效率更高,但是对于压缩率只是初步设置一个大致范围,还需要更精细化的调试

一、使用Base64编码方式

此方式全都需要使用到基本方法,基本方法如下,自行复制

1、基本方法

/**
     * 按照宽高比例压缩
     *
     * @param srcImgData 待压缩图片输入流
     * @param scale      压缩刻度
     * @return
     * @throws IOException
     * @author CY
     * @date 2020年11月18日
     */
    private static byte[] compress(byte[] srcImgData, double scale) throws IOException {
        try {
            BufferedImage bi = ImageIO.read(new ByteArrayInputStream(srcImgData));
            int width = (int) (bi.getWidth() * scale); // 源图宽度
            int height = (int) (bi.getHeight() * scale); // 源图高度
            Image image = bi.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.setColor(Color.RED);
            g.drawImage(image, 0, 0, null); // 绘制处理后的图
            g.dispose();
            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
            ImageIO.write(tag, "JPEG", bOut);
            return bOut.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

2、压缩本地图片保存到本地

/**
     * 压缩本地图片保存到本地
     *
     * @param path          保存文件的路径,精确到最后一个文件夹
     * @param localPhotoUrl 本地图片路径,精确到文件
     * @param fileName      新的文件名
     * @return
     */
    public static String localImageCompress(String path, String localPhotoUrl, String fileName) {
        try {
            // 读取文件并转换成字节数组
            Path filePath = Paths.get(localPhotoUrl);
            byte[] picByte = Files.readAllBytes(filePath);

            // 对图片进行压缩
            byte[] finalCompressPic = compress(picByte, 0.9);
            BigDecimal filesize = new BigDecimal(finalCompressPic.length);
            BigDecimal kilobyte = new BigDecimal(1024);
            float returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();

            // 输出压缩后的图片大小
            System.out.println("图片的字节数:" + finalCompressPic.length + "图片的大小:" + returnValue + "KB");

            // 如果图片大小超过149KB,则继续压缩,直到图片大小小于或等于149KB
            if (returnValue > 150) {
                for (int i = 0; i < 9; i++) {
                    double scale = (i + 1) * 0.1;
                    scale = 0.9 - scale;
                    finalCompressPic = compress(finalCompressPic, scale);
                    filesize = new BigDecimal(finalCompressPic.length);
                    kilobyte = new BigDecimal(1024);
                    returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();
                    System.out.println("继续压缩图片的字节数:" + finalCompressPic.length + "图片的大小:" + returnValue + "KB");
                    if (returnValue > 150) {
                        continue;
                    } else {
                        break;
                    }
                }
            }

            // 对字节数组Base64编码
            Base64.Encoder encoder = Base64.getEncoder();
            String png_base64 = encoder.encodeToString(finalCompressPic);

            // 将Base64编码后的字符串转换成字节数组并保存到文件中
            byte[] decodedBytes = Base64.getDecoder().decode(png_base64);
            File outputFile = new File(path, fileName);
            OutputStream outputStream = new FileOutputStream(outputFile);
            outputStream.write(decodedBytes);

            // 返回生成的缩略图路径
            return outputFile.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

3、压缩网络图片到图片服务器

//压缩网络图片保存到图片服务器
    public static String netImageCompress(String photoUrl) {
        try {
            byte[] picByte = ImgBase64Util.imgToByte(photoUrl);
            byte[] compressPic = compress(picByte, 0.9);
            byte[] finalCompressPic = compressPic;

            BigDecimal filesize = new BigDecimal(compressPic.length);
            BigDecimal kilobyte = new BigDecimal(1024);
            float returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();

            //输出
            System.out.println("图片的字节数:" + compressPic.length + "图片的大小:" + returnValue + "KB");

            if (returnValue > 149) {
                for (int i = 0; i < 10; i++) {
                    double scale = (i + 1) * 0.1;
                    scale = 0.9 - scale;
                    finalCompressPic = compress(finalCompressPic, scale);
                    BigDecimal filesize2 = new BigDecimal(finalCompressPic.length);
                    BigDecimal kilobyte2 = new BigDecimal(1024);
                    float returnValue2 = filesize2.divide(kilobyte2, 2, BigDecimal.ROUND_UP).floatValue();
                    System.out.println("循环i=" + i + "的图片的字节数:" + finalCompressPic.length + "图片的大小:" + returnValue2 + "KB");
                    if (returnValue2 > 149) {
                        continue;
                    } else {
                        break;
                    }
                }
            }

            Base64.Encoder encoder = Base64.getEncoder();
            String png_base64 = encoder.encodeToString(finalCompressPic);

            File file = ImgBase64Util.base64ToFile(png_base64);
            FileInputStream input = new FileInputStream(file);
            MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "text/plain", input);

            Map param = new HashMap();
            param.put("source", "system");
            param.put("type", "img");
            HttpUtils httpUtils = new HttpUtils();
            HttpResult httpResult = httpUtils.doFilePost("https://test.com/upload", multipartFile, param);
            Integer httpCode = httpResult.getCode();
            if (httpCode == 200) {
                JSONObject result = JSONObject.parseObject(httpResult.getBody());
                Integer code = result.getInteger("code");
                if (code == 0) {
                    String url = result.getString("data");
                    System.out.println("compress pic url:" + url);
                    return url;
                }
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

二、使用thumbnailator工具方式

此方式需要导入依赖,依赖如下

1、导入依赖

	<dependency>
	    <groupId>net.coobird</groupId>
	    <artifactId>thumbnailator</artifactId>
	    <version>0.4.19</version>
	</dependency>

2、压缩本地图片保存到本地

/**
     * 压缩本地图片保存到本地
     *
     * @param path          保存文件的路径,精确到最后一个文件夹
     * @param localPhotoUrl 本地图片路径,精确到文件
     * @param fileName      新的文件名
     * @return
     */
    public static String localImageCompress(String path, String localPhotoUrl, String fileName) {
        try {
            File f = new File(localPhotoUrl);
            long sourceImgValue = f.length() / 1024;
            BufferedImage sourceImg = ImageIO.read(new FileInputStream(f));
            int width = sourceImg.getWidth();//原图宽度
            int height = sourceImg.getHeight();//原图高度
            int hightValue = width;//宽度和高度的最大值
            if (height > width) hightValue = height;

            double scale111 = 0.5;
            if (1000 <= hightValue && hightValue < 2000) scale111 = 0.3;
            if (2000 <= hightValue && hightValue < 3000) scale111 = 0.2;
            if (3000 <= hightValue && hightValue < 4000) scale111 = 0.1;
            if (4000 <= hightValue) scale111 = BigDecimal.valueOf(500L)
                    .divide(BigDecimal.valueOf(hightValue), 2, BigDecimal.ROUND_UP).doubleValue();
            System.out.println("最终scale为:" + scale111);

            /**
             * 图片小于5M,压缩图片最大尺寸为512K
             * 大于5M,小于10M,压缩图片最大尺寸为1M
             * 大于10M,压缩图片最大尺寸为2M
             */
            int maxSize = 512;//压缩图片的最大尺寸
            if (sourceImgValue < 5 * 1024) maxSize = 512;
            if (5 * 1024 <= sourceImgValue && sourceImgValue < 10 * 1024) maxSize = 1024;
            if (10 * 1024 <= sourceImgValue) maxSize = 2 * 1024;

            String thumbnailPath = path + fileName;
            Thumbnails.of(localPhotoUrl)
                    .scale(scale111)
                    .outputQuality(0.9)
                    .toFile(thumbnailPath);

            File f1 = new File(thumbnailPath);
            long returnValue = f1.length() / 1024;
            System.out.println("第一次生成图片缩略图,大小为:" + returnValue + "KB");
            // 如果图片大小超过1M,则继续压缩,直到图片大小小于或等于149KB
            if (returnValue > maxSize) {
                for (int i = 0; i < 4; i++) {
                    double scale = (i + 1) * 0.1;
                    double scaleQuality = 0.9 - scale * 2;
                    if (scale111 > scale) scale111 = scale111 - scale;
                    System.out.println("最终scale为:" + scale111);
                    System.out.println("最终scaleQuality为:" + scaleQuality);
                    Thumbnails.of(localPhotoUrl)
                            .scale(scale111)
                            .outputQuality(scaleQuality)
                            .toFile(thumbnailPath);
                    File f2 = new File(thumbnailPath);
                    returnValue = f2.length() / 1024;
                    System.out.println("继续压缩图片大小:" + returnValue + "KB");
                    if (returnValue > maxSize) {
                        continue;
                    } else {
                        break;
                    }
                }
            }
            return thumbnailPath;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;