1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015 |
- package org.springblade.common.utils;
- import cn.hutool.core.io.FileUtil;
- import cn.hutool.core.lang.func.Func;
- import cn.hutool.core.util.URLUtil;
- import cn.hutool.http.HttpUtil;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.aliyuncs.utils.IOUtils;
- import com.drew.imaging.ImageMetadataReader;
- import com.drew.imaging.ImageProcessingException;
- import com.drew.metadata.Metadata;
- import com.drew.metadata.exif.ExifIFD0Directory;
- import com.google.common.collect.Lists;
- import com.google.common.collect.Maps;
- import org.apache.commons.imaging.ImageReadException;
- import org.apache.commons.imaging.Imaging;
- import org.apache.commons.lang.StringUtils;
- import org.springframework.util.CollectionUtils;
- import java.awt.*;
- import java.awt.color.ColorSpace;
- import java.awt.color.ICC_ColorSpace;
- import java.awt.geom.AffineTransform;
- import java.awt.image.AffineTransformOp;
- import java.awt.image.BufferedImage;
- import java.awt.image.ColorConvertOp;
- import java.io.*;
- import java.math.BigDecimal;
- import java.net.*;
- import java.time.LocalDate;
- import java.util.*;
- import java.util.List;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
- import java.util.zip.ZipEntry;
- import java.util.zip.ZipOutputStream;
- import com.drew.metadata.MetadataException;
- import javax.imageio.IIOImage;
- import javax.imageio.ImageIO;
- import javax.imageio.ImageWriteParam;
- import javax.imageio.ImageWriter;
- import net.coobird.thumbnailator.Thumbnails;
- /**
- * 通用工具类
- *
- * @author Chill
- */
- public class CommonUtil {
- private static final double INCH_TO_CM = 2.54;
- public static Boolean checkBigDecimal(Object value) {
- try {
- if (value != null && StringUtils.isNotEmpty(value.toString())) {
- new BigDecimal(value.toString());
- return true;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return false;
- }
- public static void removeFile(List<String> removeList) {
- for (String fileUrl : removeList) {
- try {
- FileUtil.del(new File(fileUrl));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- public static String handleNull(Object obj) {
- if (null == obj) {
- return "";
- } else {
- return obj.toString().trim();
- }
- }
- public static String join(Object... args) {
- if (args != null) {
- if (args.length > 2) {
- List<String> list = Arrays.stream(args).limit(args.length - 1).map(CommonUtil::handleNull).collect(Collectors.toList());
- String split = handleNull(args[args.length - 1]);
- return join(list, split);
- } else {
- return handleNull(args[0]);
- }
- } else {
- return "";
- }
- }
- public static String join(List<String> list, String split) {
- StringBuilder sb = new StringBuilder();
- if (list != null && list.size() > 0) {
- for (String str : list) {
- if (StringUtils.isNotEmpty(str)) {
- sb.append(str).append(split);
- }
- }
- if (sb.length() > 0 && StringUtils.isNotEmpty(split)) {
- sb.delete(sb.length() - split.length(), sb.length());
- }
- }
- return sb.toString();
- }
- public static Matcher matcher(String regex, String value) {
- Pattern pattern = Pattern.compile(regex);
- return pattern.matcher(value);
- }
- /**
- * 文件流转化为File
- */
- public static void convert(InputStream inputStream, String targetFile) throws IOException {
- // 创建文件输出流
- FileOutputStream outputStream = new FileOutputStream(targetFile);
- // 创建缓冲区
- byte[] buffer = new byte[1024];
- int bytesRead;
- // 从输入流读取数据并写入输出流
- while ((bytesRead = inputStream.read(buffer)) != -1) {
- outputStream.write(buffer, 0, bytesRead);
- }
- // 关闭流
- outputStream.close();
- inputStream.close();
- }
- /**
- * 根据OSS文件路径获取文件输入流
- */
- public static InputStream getOSSInputStream(String urlStr) {
- try {
- System.out.println("----前-------"+urlStr);
- urlStr = replaceOssUrl(urlStr);
- int lastIndex = urlStr.lastIndexOf("/") + 1;
- String fileName = urlStr.substring(lastIndex);
- urlStr = urlStr.substring(0, lastIndex) + URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
- //获取OSS文件流
- URL url = new URL(urlStr);
- URLConnection conn = url.openConnection();
- conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
- return conn.getInputStream();
- } catch (Exception e) {
- System.out.println("-----后------"+urlStr);
- return null;
- }
- }
- /**
- * 根据OSS文件路径获取文件输入流
- */
- public static InputStream getOSSInputStreamTow(String urlStr) throws Exception {
- //获取OSS文件流
- urlStr = replaceOssUrl(urlStr);
- URL imageUrl = new URL(urlStr);
- HttpURLConnection conn = null;
- try {
- conn = (HttpURLConnection) imageUrl.openConnection();
- conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
- return conn.getInputStream();
- } catch (IOException e) {
- e.printStackTrace();
- if (conn != null) {
- conn.disconnect(); //关闭网络连接
- }
- throw new Exception("获取图片输入流失败!URL:" + urlStr, e);
- }
- }
- /**
- * 获取字节数组
- */
- public static synchronized byte[] InputStreamToBytes(InputStream is) {
- BufferedInputStream bis = new BufferedInputStream(is);
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- int date = -1;
- while (true) {
- try {
- if (!((date = bis.read()) != -1)) break;
- os.write(date);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- return os.toByteArray();
- }
- /**
- * 随机生成短信验证码
- *
- * @param length 生成长度
- */
- public static String getCharAndNumber(int length) {
- StringBuilder val = new StringBuilder();
- Random random = new Random();
- for (int i = 0; i < length; i++) {
- String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
- if ("char".equalsIgnoreCase(charOrNum)) {
- int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
- val.append((char) (choice + random.nextInt(26)));
- } else {
- val.append(random.nextInt(10));
- }
- }
- return val.toString();
- }
- /**
- * 判断参数是否是数字
- *
- * @param value 需要判断数据
- * @return 判断结果,数字则为true,反之false
- */
- public static boolean checkIsBigDecimal(Object value) {
- try {
- if (value != null && StringUtils.isNotEmpty(String.valueOf(value))) {
- new BigDecimal(String.valueOf(value));
- return true;
- } else {
- return false;
- }
- } catch (Exception e) {
- return false;
- }
- }
- /**
- * 根据每页信息分组
- */
- public static <T> List<List<T>> getBatchSize(List<T> allIds, int size) {
- List<List<T>> batchIds = new ArrayList<>();
- if (allIds == null || allIds.size() == 0 || size <= 0) {
- return batchIds;
- }
- int i = 0;
- List<T> tmp = new ArrayList<>();
- for (T map : allIds) {
- tmp.add(map);
- i++;
- if (i % size == 0 || i == allIds.size()) {
- batchIds.add(tmp);
- tmp = new ArrayList<>();
- }
- }
- return batchIds;
- }
- /**
- * @param src
- * @throws IOException
- * @throws ClassNotFoundException
- */
- public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {
- ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
- ObjectOutputStream out = new ObjectOutputStream(byteOut);
- out.writeObject(src);
- ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
- ObjectInputStream in = new ObjectInputStream(byteIn);
- @SuppressWarnings("unchecked")
- List<T> dest = (List<T>) in.readObject();
- return dest;
- }
- /**
- * Description: Java8 Stream分割list集合
- *
- * @param list 集合数据
- * @param splitSize 几个分割一组
- * @return 集合分割后的集合
- */
- public static <T> List<List<T>> splitList(List<T> list, int splitSize) {
- //判断集合是否为空
- if (CollectionUtils.isEmpty(list))
- return Collections.emptyList();
- //计算分割后的大小
- int maxSize = (list.size() + splitSize - 1) / splitSize;
- //开始分割
- return Stream.iterate(0, n -> n + 1)
- .limit(maxSize)
- .parallel()
- .map(a -> list.parallelStream().skip(a * splitSize).limit(splitSize).collect(Collectors.toList()))
- .filter(b -> !b.isEmpty())
- .collect(Collectors.toList());
- }
- /**
- * Map拆分 (指定分组大小)
- *
- * @param map Map
- * @param chunkSize 每个分组的大小 (>=1)
- * @param <K> Key
- * @param <V> Value
- * @return 子Map列表
- */
- public static <K, V> List<Map<K, V>> splitByChunkSize(Map<K, V> map, int chunkSize) {
- if (Objects.isNull(map) || map.isEmpty() || chunkSize < 1) {
- //空map或者分组大小<1,无法拆分
- return Collections.emptyList();
- }
- int mapSize = map.size(); //键值对总数
- int groupSize = mapSize / chunkSize + (mapSize % chunkSize == 0 ? 0 : 1); //计算分组个数
- List<Map<K, V>> list = Lists.newArrayListWithCapacity(groupSize); //子Map列表
- if (chunkSize >= mapSize) { //只能分1组的情况
- list.add(map);
- return list;
- }
- int count = 0; //每个分组的组内计数
- Map<K, V> subMap = Maps.newHashMapWithExpectedSize(chunkSize); //子Map
- for (Map.Entry<K, V> entry : map.entrySet()) {
- if (count < chunkSize) {
- //给每个分组放chunkSize个键值对,最后一个分组可能会装不满
- subMap.put(entry.getKey(), entry.getValue());
- count++; //组内计数+1
- } else {
- //结束上一个分组
- list.add(subMap); //当前分组装满了->加入列表
- //开始下一个分组
- subMap = Maps.newHashMapWithExpectedSize(chunkSize); //新的分组
- subMap.put(entry.getKey(), entry.getValue()); //添加当前键值对
- count = 1; //组内计数重置为1
- }
- }
- list.add(subMap); //添加最后一个分组
- return list;
- }
- /**
- * Map拆分(指定分组个数)
- *
- * @param map Map
- * @param groupSize 分组个数 (>=1)
- * @param <K> Key
- * @param <V> Value
- * @return 子Map列表
- */
- public static <K, V> List<Map<K, V>> splitByGroupSize(Map<K, V> map, int groupSize) {
- if (Objects.isNull(map) || map.isEmpty() || groupSize < 1) {
- //空map或者分组数<1,无法拆分
- return Collections.emptyList();
- }
- List<Map<K, V>> list = Lists.newArrayListWithCapacity(groupSize);
- if (groupSize == 1) { //只有1个分组的情况
- list.add(map);
- return list;
- }
- int mapSize = map.size(); //键值对总数
- int chunkIndex = 0; //当前分组的下标,[0, groupSize-1]
- int restCount = mapSize % groupSize; //平均后剩余的键值对数
- int chunkSize0 = mapSize / groupSize; //每个分组键值对数量
- int chunkSize1 = chunkSize0 + 1; //多分一个
- int chunkSize = chunkIndex < restCount ? chunkSize1 : chunkSize0; //实际每组的大小(前面的部分分组可能会多分1个)
- int count = 0; //每个分组的组内计数
- Map<K, V> subMap = Maps.newHashMapWithExpectedSize(chunkSize);//子Map
- for (Map.Entry<K, V> entry : map.entrySet()) {
- if (count < chunkSize) {
- //每个分组按实际分组大小(chunkSize)加入键值对
- subMap.put(entry.getKey(), entry.getValue());
- count++; //组内计数+1
- } else {
- //结束上一个分组
- list.add(subMap); //当前分组装满了->加入列表
- chunkIndex++; //分组个数+1
- //开始下一个分组
- chunkSize = chunkIndex < restCount ? chunkSize1 : chunkSize0; //重新计算分组大小
- subMap = Maps.newHashMapWithExpectedSize(chunkSize); //新的分组
- subMap.put(entry.getKey(), entry.getValue()); //添加当前键值对
- count = 1; //组内计数重置为1
- }
- }
- list.add(subMap); //添加最后一个分组
- return list;
- }
- /**
- * 流写入文件
- *
- * @param inputStream 文件输入流
- * @param file 输出文件
- */
- public static void inputStreamToFile(InputStream inputStream, File file) {
- try {
- OutputStream os = new FileOutputStream(file);
- int bytesRead = 0;
- byte[] buffer = new byte[8192];
- while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
- os.write(buffer, 0, bytesRead);
- }
- os.close();
- inputStream.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 删除文件夹下所有文件
- *
- * @param path
- * @return
- */
- public static boolean deleteDir(String path) {
- File file = new File(path);
- if (!file.exists()) {//判断是否待删除目录是否存在
- System.err.println("The dir are not exists!");
- return false;
- }
- String[] content = file.list();//取得当前目录下所有文件和文件夹
- for (String name : content) {
- File temp = new File(path, name);
- if (temp.isDirectory()) {//判断是否是目录
- deleteDir(temp.getAbsolutePath());//递归调用,删除目录里的内容
- temp.delete();//删除空目录
- } else {
- if (!temp.delete()) {//直接删除文件
- System.err.println("Failed to delete " + name);
- }
- }
- }
- return true;
- }
- /**
- * 压缩指定路径下的文件夹
- *
- * @param filesPath
- * @throws Exception
- */
- public static void packageZip(String filesPath, String zipUrl) throws Exception {
- // 要被压缩的文件夹
- File file = new File(filesPath); //需要压缩的文件夹
- File folder = new File(zipUrl);
- if (!folder.exists() && !folder.isDirectory()) {
- folder.mkdirs();
- }
- File zipFile = new File(zipUrl + "/" + "localArchive.zip"); //放于和需要压缩的文件夹同级目录
- ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
- isDirectory(file, zipOut, "", true); //判断是否为文件夹
- zipOut.close();
- }
- public static void isDirectory(File file, ZipOutputStream zipOutputStream, String filePath, boolean flag) throws IOException {
- //判断是否为问加减
- if (file.isDirectory()) {
- File[] files = file.listFiles(); //获取该文件夹下所有文件(包含文件夹)
- filePath = flag == true ? file.getName() : filePath + File.separator + file.getName(); //首次为选中的文件夹,即根目录,之后递归实现拼接目录
- for (int i = 0; i < files.length; ++i) {
- //判断子文件是否为文件夹
- if (files[i].isDirectory()) {
- //进入递归,flag置false 即当前文件夹下仍包含文件夹
- isDirectory(files[i], zipOutputStream, filePath, false);
- } else {
- //不为文件夹则进行压缩
- InputStream input = new FileInputStream(files[i]);
- zipOutputStream.putNextEntry(new ZipEntry(filePath + File.separator + files[i].getName()));
- int temp = 0;
- while ((temp = input.read()) != -1) {
- zipOutputStream.write(temp);
- }
- input.close();
- }
- }
- } else {
- //将子文件夹下的文件进行压缩
- InputStream input = new FileInputStream(file);
- zipOutputStream.putNextEntry(new ZipEntry(file.getPath()));
- int temp = 0;
- while ((temp = input.read()) != -1) {
- zipOutputStream.write(temp);
- }
- input.close();
- }
- }
- /**
- * @param urlStr
- * @return 返回Url资源大小
- * @throws IOException
- */
- public static long getResourceLength(String urlStr) throws IOException {
- urlStr = replaceOssUrl(urlStr);
- URL url = new URL(urlStr);
- URLConnection urlConnection = url.openConnection();
- urlConnection.connect();
- //返回响应报文头字段Content-Length的值
- return urlConnection.getContentLength();
- }
- public static long getFileContentLength(String urlStr) {
- try {
- urlStr = replaceOssUrl(urlStr);
- System.out.println("获取文件大小:"+urlStr);
- URL url = new URL(urlStr);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- // 设置 HEAD 请求(只获取头部信息,不下载文件)
- conn.setRequestMethod("HEAD");
- // 设置超时(避免线上卡死)
- conn.setConnectTimeout(5000); // 5秒连接超时
- conn.setReadTimeout(5000); // 5秒读取超时
- // 发起请求
- conn.connect();
- // 获取 Content-Length
- long contentLength = conn.getContentLengthLong();
- // 关闭连接
- conn.disconnect();
- return contentLength;
- } catch (Exception e) {
- return 0L;
- }
- }
- public static long getFileSize(String fileUrl) throws IOException {
- URL url = new URL(fileUrl);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- // 使用 HEAD 请求(只获取文件信息,不下载内容)
- conn.setRequestMethod("HEAD");
- // 设置超时(避免卡死)
- conn.setConnectTimeout(5000); // 5秒连接超时
- conn.setReadTimeout(5000); // 5秒读取超时
- // 发起请求
- conn.connect();
- // 获取 Content-Length(文件大小)
- long fileSize = conn.getContentLengthLong();
- // 关闭连接
- conn.disconnect();
- return fileSize;
- }
- /**
- * 图片缩放、压缩、旋转处理
- *
- * @return
- * @throws IOException
- * @throws ImageProcessingException
- * @throws MetadataException
- */
- /* public static void main(String[] args) throws IOException, ImageProcessingException, MetadataException {
- // String imgurl = "/Users/hongchuangyanfa/Desktop/excel/432123.jpg";
- // String imgurl = "/Users/hongchuangyanfa/Desktop/excel/123.jpg";
- // String imgurl = "/Users/hongchuangyanfa/Downloads/03c1994653c4d59ab596e683a109e247 (1).jpg";
- String imgurl = "http://183.247.216.148:9000/minio-oss-chongqing/upload/20250414/03c1994653c4d59ab596e683a109e247.jpg";
- compressImage(imgurl);
- System.out.println("图片转换并保存成功!");
- }*/
- public static byte[] compressImage(String url) {
- // 读取原始图像(处理旋转问题)
- InputStream file = CommonUtil.getOSSInputStream(url);
- InputStream file2 = CommonUtil.getOSSInputStream(url);
- InputStream file3 = CommonUtil.getOSSInputStream(url);
- byte[] imageData = InputStreamToBytes(file);
- long sizeLimit = 1024 * 1024 * 5; //5M 1920 ×1080
- if (imageData.length <= sizeLimit) {
- return imageData;
- }
- try {
- Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
- if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
- ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
- if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
- // 获取 Orientation 标签的值
- int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
- // 需要旋转图片
- // 1 无需纠正 2 水平翻转(镜像)3 垂直翻转(旋转180°) 4 水平翻转+垂直翻转 5 水平翻转+旋转90°
- // 6 旋转90° 7 水平翻转+旋转270° 8 +旋转270°
- if (orientation > 1) {
- ImageIO.scanForPlugins();
- BufferedImage originalImage = Imaging.getBufferedImage(file2);
- AffineTransform transform = new AffineTransform();
- if (orientation == 3) {
- transform.rotate(Math.PI, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
- } else if (orientation == 6) {
- transform.rotate(Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
- } else if (orientation == 8) {
- transform.rotate(-Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
- }
- AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
- originalImage = op.filter(originalImage, null);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ImageIO.write(originalImage, "jpg", baos);
- imageData = baos.toByteArray();
- }
- }
- }
- // 缩放图像
- String formatName = "JPEG";
- ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
- String[] formats = ImageIO.getReaderFormatNames();
- System.out.println("----支持的格式-----: " + Arrays.toString(formats));
- // BufferedImage originalImage = ImageIO.read(file2);
- BufferedImage originalImage = Imaging.getBufferedImage(imageData); //.getBufferedImage(file3);
- int width = 1080;
- int height = 1920;
- Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
- BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
- resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
- // 压缩图像
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ImageIO.write(resizedImage, formatName, baos);
- if (baos.size() <= sizeLimit) {
- // 图片大小已经小于等于目标大小,直接返回原始数据
- return baos.toByteArray();
- }
- float quality = 0.9f; // 初始化压缩质量
- int retries = 10; // 最多尝试 10 次
- while (baos.size() > sizeLimit && retries > 0) {
- // 压缩图像并重新计算压缩质量
- byte[] data = baos.toByteArray();
- bais = new ByteArrayInputStream(data);
- BufferedImage compressedImage = ImageIO.read(bais);
- baos.reset();
- ImageWriter writer = null;
- Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
- if (writers.hasNext()) {
- writer = writers.next();
- } else {
- throw new IllegalArgumentException("Unsupported image format: " + formatName);
- }
- ImageWriteParam writeParam = writer.getDefaultWriteParam();
- writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
- writeParam.setCompressionQuality(1);
- writer.setOutput(ImageIO.createImageOutputStream(baos));
- writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
- writer.dispose();
- float ratio = sizeLimit * 1.0f / baos.size();
- quality *= Math.sqrt(ratio);
- retries--;
- }
- return baos.toByteArray();
- } catch (Exception e) {
- return imageData;
- }
- }
- public static byte[] compressImage(byte[] imageData) throws IOException, ImageProcessingException, MetadataException{
- // 读取原始图像(处理旋转问题)
- Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
- if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
- ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
- if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
- // 获取 Orientation 标签的值
- int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
- // 需要旋转图片
- // 1 无需纠正 2 水平翻转(镜像)3 垂直翻转(旋转180°) 4 水平翻转+垂直翻转 5 水平翻转+旋转90°
- // 6 旋转90° 7 水平翻转+旋转270° 8 +旋转270°
- if (orientation > 1) {
- BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(imageData));
- AffineTransform transform = new AffineTransform();
- if (orientation == 3) {
- transform.rotate(Math.PI, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
- } else if (orientation == 6) {
- transform.rotate(Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
- } else if (orientation == 8) {
- transform.rotate(-Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
- }
- AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
- originalImage = op.filter(originalImage, null);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ImageIO.write(originalImage, "jpg", baos);
- imageData = baos.toByteArray();
- }
- }
- }
- // 缩放图像
- String formatName = "JPEG";
- ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
- BufferedImage originalImage = null;
- try {
- originalImage = Imaging.getBufferedImage(imageData);
- } catch (ImageReadException e) {
- e.printStackTrace();
- }
- long sizeLimit = 1024*1024*5; //5M 1920 ×1080
- int width = 1080;
- int height = 1920;
- Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
- BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
- resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
- // 压缩图像
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ImageIO.write(resizedImage, formatName, baos);
- if (baos.size() <= sizeLimit) {
- // 图片大小已经小于等于目标大小,直接返回原始数据
- return baos.toByteArray();
- }
- float quality = 0.9f; // 初始化压缩质量
- int retries = 10; // 最多尝试 10 次
- while (baos.size() > sizeLimit && retries > 0) {
- // 压缩图像并重新计算压缩质量
- byte[] data = baos.toByteArray();
- bais = new ByteArrayInputStream(data);
- BufferedImage compressedImage = ImageIO.read(bais);
- baos.reset();
- ImageWriter writer = null;
- Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
- if (writers.hasNext()) {
- writer = writers.next();
- } else {
- throw new IllegalArgumentException("Unsupported image format: " + formatName);
- }
- ImageWriteParam writeParam = writer.getDefaultWriteParam();
- writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
- writeParam.setCompressionQuality(1);
- writer.setOutput(ImageIO.createImageOutputStream(baos));
- writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
- writer.dispose();
- float ratio = sizeLimit * 1.0f / baos.size();
- quality *= Math.sqrt(ratio);
- retries--;
- }
- return baos.toByteArray();
- }
- /**
- * 图片压缩
- *
- * @param imageData
- * @return
- * @throws IOException
- * @throws ImageProcessingException
- * @throws MetadataException
- */
- public static byte[] compressImage2(byte[] imageData) throws IOException {
- // 缩放图像
- String formatName = "JPEG";
- ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
- BufferedImage originalImage = ImageIO.read(bais);
- long sizeLimit = 512000; //358KB
- int width = originalImage.getWidth();
- int height = originalImage.getHeight();
- Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
- BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
- // 压缩图像
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ImageIO.write(resizedImage, formatName, baos);
- if (baos.size() <= sizeLimit) {
- // 图片大小已经小于等于目标大小,直接返回原始数据
- return baos.toByteArray();
- }
- float quality = 0.7f; // 初始化压缩质量
- int retries = 10; // 最多尝试 10 次
- while (baos.size() > sizeLimit && retries > 0) {
- // 压缩图像并重新计算压缩质量
- bais = new ByteArrayInputStream(imageData);
- originalImage = ImageIO.read(bais);
- float width2 = originalImage.getWidth() * quality;
- float height2 = originalImage.getHeight() * quality;
- scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
- resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
- // 压缩图像
- baos = new ByteArrayOutputStream();
- ImageIO.write(resizedImage, formatName, baos);
- if (baos.size() <= sizeLimit) {
- // 图片大小已经小于等于目标大小,直接返回原始数据
- return baos.toByteArray();
- }
- byte[] data = baos.toByteArray();
- bais = new ByteArrayInputStream(data);
- BufferedImage compressedImage = ImageIO.read(bais);
- baos.reset();
- ImageWriter writer = null;
- Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
- if (writers.hasNext()) {
- writer = writers.next();
- } else {
- throw new IllegalArgumentException("Unsupported image format: " + formatName);
- }
- ImageWriteParam writeParam = writer.getDefaultWriteParam();
- writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
- writeParam.setCompressionQuality(quality);
- writer.setOutput(ImageIO.createImageOutputStream(baos));
- writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
- writer.dispose();
- float ratio = sizeLimit * 1.0f / baos.size();
- quality *= Math.sqrt(ratio);
- retries--;
- }
- return baos.toByteArray();
- }
- public static byte[] compressImage3(String url) throws IOException, ImageProcessingException, MetadataException {
- try(InputStream file = CommonUtil.getOSSInputStream(url)) {
- byte[] imageData = InputStreamToBytes(file);
- String extension = url.substring(url.lastIndexOf(".") + 1).toUpperCase();
- if ("JPG".equals(extension) || "JPEG".equals(extension)) {
- extension = "JPEG";
- }
- return compressImage3(imageData, extension);
- }
- }
- public static byte[] compressImage3(byte[] imageData, String formatName) throws ImageProcessingException, IOException, MetadataException {
- // 读取原始图像(处理旋转问题)
- int orientation = 1;
- Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
- if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
- ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
- if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
- // 获取 Orientation 标签的值
- orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
- }
- }
- // 缩放图像
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- long sizeLimit = 1024*1024*5; //5M 1920 ×1080
- int width = 1080;
- int height = 1920;
- // 需要旋转图片
- // 1 无需纠正 2 水平翻转(镜像)3 垂直翻转(旋转180°) 4 水平翻转+垂直翻转 5 水平翻转+旋转90°
- // 6 旋转90° 7 水平翻转+旋转270° 8 +旋转270°
- float quality = 0.99f; // 初始化压缩质量
- int retries = 10; // 最多尝试 10 次
- double rotate = 0;
- if (orientation > 1) {
- if (orientation == 3) {
- rotate = 180;
- } else if (orientation == 6) {
- rotate = 90;
- } else if (orientation == 8) {
- rotate = 270;
- }
- }
- rotateAndScaleImageByThumbnails(new ByteArrayInputStream(imageData),baos, rotate, formatName, quality, width, height, true);
- if (baos.size() <= sizeLimit) {
- // 图片大小已经小于等于目标大小,直接返回原始数据
- return baos.toByteArray();
- }
- ByteArrayInputStream bais;
- while (baos.size() > sizeLimit && retries > 0) {
- // 压缩图像并重新计算压缩质量
- byte[] data = baos.toByteArray();
- bais = new ByteArrayInputStream(data);
- rotateAndScaleImageByThumbnails(bais,baos, 0, formatName, quality, width, height, true);
- float ratio = sizeLimit * 1.0f / baos.size();
- quality *= Math.sqrt(ratio);
- retries--;
- }
- return baos.toByteArray();
- }
- /**
- * @param is URL InputStream File BufferedImage path
- * @param os 输出流
- * @param rotate 旋转角度(正数顺时针,负数逆时针)
- * @param format 输出格式,jpg,jpeg,png等
- * @param quality 输出质量(0.0-1.0)
- * @param width 宽
- * @param height 高
- * @param keepAspectRatio 是否保持原比例
- */
- public static void rotateAndScaleImageByThumbnails(InputStream is, OutputStream os, double rotate, String format, double quality, int width, int height, boolean keepAspectRatio) throws IOException {
- Thumbnails.of(is)
- .size(width, height)
- .keepAspectRatio(keepAspectRatio)
- .rotate(rotate)
- .outputFormat(format)
- .outputQuality(quality)
- .toOutputStream(os);
- }
- /**
- * 根据起止日期获取工作日
- *
- * @return
- */
- public static int getWorkDays(LocalDate startTime, LocalDate endTime) {
- if (startTime.compareTo(endTime) > 0) {
- return -1;
- }
- // if (startTime.compareTo(endTime) == 0){
- // return 1;
- // }
- StringBuilder str = new StringBuilder();
- List<String> list = new ArrayList<>();
- while (!startTime.equals(endTime)) {
- str.append("d=" + startTime + "&");
- list.add(startTime.toString());
- startTime = startTime.plusDays(1L);
- }
- str.append("d=" + endTime + "&");
- list.add(endTime.toString());
- str.append("type=Y");
- String post = HttpUtil.get("http://timor.tech/api/holiday/batch?" + str.toString());
- JSONObject jsonObject = JSON.parseObject(post).getJSONObject("type");
- System.out.println(jsonObject);
- int workDays = 0;
- for (String s : list) {
- Map map = JSONObject.parseObject(jsonObject.get(s).toString(), Map.class);
- int type = (int) map.get("type");
- if (type == 0 || type == 3) {
- workDays++;
- }
- }
- return workDays;
- }
- public static String replaceOssUrl(String url) {
- //本地部署- 甬台温
- if (url.indexOf("183.247.216.148") >= 0 || url.indexOf("152.168.2.15") >= 0) {
- // 如果当前环境变量不包含linuxtesttest,则替换URL中的oss路径
- if (SystemUtils.isMacOs() || SystemUtils.isWindows()) {
- url = url.replace("https://", "http://").replace(":9000//", ":9000/");
- } else {
- url = url.replace("https://", "http://").replace("183.247.216.148", "152.168.2.15").replace(":9000//", ":9000/");
- }
- }
- return url;
- }
- /**
- * webp文件转字节数组
- *
- * @param
- * @return
- */
- public static byte[] webpToPngBytes(InputStream inputStream) {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- try {
- BufferedImage webpImage = ImageIO.read(inputStream);
- ImageIO.write(webpImage, "png", bos);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return bos.toByteArray();
- }
- // 图片厘米转像素
- public static int cmToPx(double cm) {
- double pixelsPerCm = 90 / INCH_TO_CM;
- return (int) Math.round(cm * pixelsPerCm);
- }
- // 图片厘米转像素
- public static double pxToCm(int px) {
- double cmPerPixel = INCH_TO_CM / 90;
- //保留两位小数
- return Math.round(px * cmPerPixel * 100) / 100.0;
- }
- }
|