001package top.cenze.utils.file; 002 003import lombok.extern.slf4j.Slf4j; 004import net.coobird.thumbnailator.Thumbnails; 005import org.apache.commons.lang.StringUtils; 006import sun.misc.BASE64Encoder; 007 008import java.io.ByteArrayInputStream; 009import java.io.ByteArrayOutputStream; 010import java.io.FileInputStream; 011import java.io.InputStream; 012import java.net.HttpURLConnection; 013import java.net.URL; 014 015@Slf4j 016public class ImageUtil { 017 private static final Integer ZERO = 0; 018 private static final Integer ONE_ZERO_TWO_FOUR = 1024; 019 private static final Integer NINE_ZERO_ZERO = 900; 020 private static final Integer THREE_TWO_SEVEN_FIVE = 3275; 021 private static final Integer TWO_ZERO_FOUR_SEVEN = 2047; 022 private static final Double ZERO_EIGHT_FIVE = 0.85; 023 private static final Double ZERO_SIX = 0.6; 024 private static final Double ZERO_FOUR_FOUR = 0.44; 025 private static final Double ZERO_FOUR = 0.4; 026 027 /** 028 * 根据指定大小压缩图片 029 * 030 * @param imageBytes 源图片字节数组 031 * @param desFileSize 指定图片大小,单位kb 032 * @return 压缩质量后的图片字节数组 033 */ 034 public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) { 035 if (imageBytes == null || imageBytes.length <= ZERO || imageBytes.length < desFileSize * ONE_ZERO_TWO_FOUR) { 036 return imageBytes; 037 } 038 039 long srcSize = imageBytes.length; 040 double accuracy = getAccuracy(srcSize / ONE_ZERO_TWO_FOUR); 041 042 try { 043 while (imageBytes.length > desFileSize * ONE_ZERO_TWO_FOUR) { 044 ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes); 045 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length); 046 047 Thumbnails.of(inputStream) 048 .scale(accuracy) 049 .outputQuality(accuracy) 050 .toOutputStream(outputStream); 051 052 imageBytes = outputStream.toByteArray(); 053 } 054 055 log.info("图片原大小={}kb | 压缩后大小={}kb", 056 srcSize / ONE_ZERO_TWO_FOUR, imageBytes.length / ONE_ZERO_TWO_FOUR); 057 } catch (Exception e) { 058 log.error("【图片压缩】msg=图片压缩失败!", e); 059 } 060 061 return imageBytes; 062 } 063 064 /** 065 * 自动调节精度(经验数值) 066 * 067 * @param size 源图片大小 068 * @return 图片压缩质量比 069 */ 070 private static double getAccuracy(long size) { 071 double accuracy; 072 if (size < NINE_ZERO_ZERO) { 073 accuracy = ZERO_EIGHT_FIVE; 074 } else if (size < TWO_ZERO_FOUR_SEVEN) { 075 accuracy = ZERO_SIX; 076 } else if (size < THREE_TWO_SEVEN_FIVE) { 077 accuracy = ZERO_FOUR_FOUR; 078 } else { 079 accuracy = ZERO_FOUR; 080 } 081 return accuracy; 082 } 083 084 /** 085 * 判断是否为网络图片 086 * @param image 087 * @return 088 */ 089 public static boolean isNetImage(String image) { 090 if (StringUtils.isBlank(image)) { 091 return false; 092 } 093 094 String str = image.substring(0, 10).toLowerCase(); 095 if (str.contains("http:") || str.contains("https:")) { 096 return true; 097 } 098 099 return false; 100 } 101 102 /** 103 * 网络图片转byte[] 104 * @param imageUrl 105 * @return 106 */ 107 public static byte[] netImageToByte(String imageUrl) { 108 if (org.apache.commons.lang3.StringUtils.isBlank(imageUrl)) { 109 return null; 110 } 111 112 try { 113 URL url = new URL(imageUrl); 114 byte[] b = new byte[10240]; 115 116 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 117 conn.setRequestMethod("GET"); 118 conn.setConnectTimeout(5000); 119 120 InputStream is = conn.getInputStream(); 121 ByteArrayOutputStream os = new ByteArrayOutputStream(); 122 123 int len = -1; 124 while ((len = is.read(b)) != -1) { 125 os.write(b, 0, len); 126 } 127 128 is.close(); 129 130 return os.toByteArray(); 131 } catch (Exception e) { 132 log.error(e.getMessage()); 133 } 134 135 return null; 136 } 137 138 /** 139 * 网络图片转base64(网络图片地址、图片类型png、不需要base64头信息) 140 * @param imageUrl 141 * @return 142 */ 143 public static String netImage2Base64(String imageUrl) { 144 return netImage2Base64(imageUrl, false); 145 } 146 147 /** 148 * 网络图片转base64(网络图片地址、图片类型png、是否需要base64头信息、不限制图片大小) 149 * @param imageUrl 150 * @param head 是否需要base64头 151 * @return 152 */ 153 public static String netImage2Base64(String imageUrl, boolean head) { 154 return netImage2Base64(imageUrl, head, 0L); 155 } 156 157 /** 158 * 网络图片转base64(网络图片地址、图片类型png、是否需要base64头信息、压缩图片限制压缩后的图片大小) 159 * @param imageUrl 160 * @param head 是否需要base64头 161 * @param desFileSize 压缩图片,限制压缩后的图片大小 162 * @return 163 */ 164 public static String netImage2Base64(String imageUrl, boolean head, long desFileSize) { 165 if (org.apache.commons.lang3.StringUtils.isBlank(imageUrl)) { 166 return null; 167 } 168 169 String[] split = imageUrl.split("."); 170 171 String type = "png"; 172 if (null != split && split.length > 0) { 173 type = split[split.length - 1]; 174 } 175 176 byte[] imageBytes = netImageToByte(imageUrl); 177 178 if (desFileSize > 0) { 179 imageBytes = compressPicForScale(imageBytes, desFileSize); 180 } 181 182 return netImage2Base64(imageBytes, type, head); 183 } 184 185 private static String netImage2Base64(byte[] imageBytes, String type, boolean head) { 186 if (imageBytes == null || imageBytes.length <= ZERO) { 187 return null; 188 } 189 190 try { 191 BASE64Encoder encoder = new BASE64Encoder(); 192 if (head) { 193 return "data:image/" + type + ";base64," + encoder.encode(imageBytes); 194 } else { 195 return encoder.encode(imageBytes); 196 } 197 } catch (Exception e) { 198 log.error(e.getMessage()); 199 } 200 201 return null; 202 } 203 204 /** 205 * 网络图片转base64(网络图片地址、图片类型默认、不需要base64头信息) 206 * @param imageUrl 207 * @return 208 */ 209 public static String NetImage2Base64(String imageUrl) { 210 return NetImage2Base64(imageUrl, null, false); 211 } 212 213 /** 214 * 网络图片转base64(网络图片地址、图片类型png、需要base64头信息) 215 * @param imageUrl 216 * @return 217 */ 218 public static String NetImage2FullBase64(String imageUrl) { 219 return NetImage2Base64(imageUrl, "png", true); 220 } 221 222 /** 223 * 网络图片转base64(网络图片地址、图片类型png/jpg、需要base64头信息) 224 * @param imageUrl 225 * @param type 226 * @return 227 */ 228 public static String NetImage2Base64(String imageUrl, String type) { 229 return NetImage2Base64(imageUrl, type, true); 230 } 231 232 /** 233 * 网络图片转base64(网络图片地址、图片类型png/jpg、是否需要base64头信息) 234 * @param imageUrl 235 * @param type 236 * @param head 237 * @return 238 */ 239 public static String NetImage2Base64(String imageUrl, String type, boolean head) { 240 if (StringUtils.isBlank(imageUrl)) { 241 return null; 242 } 243 244 try { 245 URL url = new URL(imageUrl); 246 byte[] b = new byte[1024]; 247 248 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 249 conn.setRequestMethod("GET"); 250 conn.setConnectTimeout(5000); 251 252 InputStream is = conn.getInputStream(); 253 ByteArrayOutputStream os = new ByteArrayOutputStream(); 254 255 int len = -1; 256 while ((len = is.read(b)) != -1) { 257 os.write(b, 0, len); 258 } 259 260 is.close(); 261 262 BASE64Encoder encoder = new BASE64Encoder(); 263 if (head) { 264 if (StringUtils.isBlank(type)) { 265 type = "png"; 266 } 267 268 return "data:image/" + type + ";base64," + encoder.encode(os.toByteArray()); 269 } else { 270 return encoder.encode(os.toByteArray()); 271 } 272 } catch (Exception e) { 273 log.error(e.getMessage()); 274 } 275 276 return null; 277 } 278 279 /** 280 * 本地图片转base64(本地图片绝对路径) 281 * @param imagePath 282 * @return 283 */ 284 public static String LocalImage2Base64(String imagePath) { 285 if (StringUtils.isBlank(imagePath)) { 286 return null; 287 } 288 289 try { 290 InputStream is = new FileInputStream(imagePath); 291 byte[] b = new byte[is.available()]; 292 is.read(b); 293 294 is.close(); 295 296 BASE64Encoder encoder = new BASE64Encoder(); 297 return encoder.encode(b); 298 } catch (Exception e) { 299 log.error(e.getMessage()); 300 } 301 302 return null; 303 } 304}