java指定图片的dpi和存储大小kb
-
公司需求,将文件夹下面的所有图片dpi设置为300,存储大小为90到150kb,折磨了我4天,今天终于解决了,写成本地直接能跑的代码记录一下。
-
注意要将png(32位深度)格式的图片转换成jpg(24位深度)格式,只改变图片的后缀是不行的。
-
查看图片修改后的dpi,在 FSViewer 里面查看,鼠标右键属性那里看到的值不准。
-
需要引入 Thumbnailator 到 maven 项目里面的 pom.xml,或者直接去 官网下载.jar包导入项目。
google图片处理插件
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.11</version>
</dependency>
java代码(只需要修改下文件路径往里面存图片就行了)
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import net.coobird.thumbnailator.Thumbnails;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.FileImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
//需求,将文件夹下面的所有图片dpi设置为300,存储大小为90到150kb
public class ImgDemo {
public static void main(String[] args) throws IOException {
//文件夹路径
String path = "C:\\Users\\Administrator\\Desktop\\zy\\";
File[] allFiles = new File(path).listFiles();
for (int i = 0; i < allFiles.length; i++) {
File allFile = allFiles[i];
//文件夹下的文件路径
String filepath = allFile.getPath();
//将所有图片转成jpg格式
pngToJpg(filepath);
//设置图片的dpi
makeDpi(filepath, 300);
//将文件转成字节数组
byte[] bytesByFile = getBytesByFile(filepath);
//设置文件的存储大小,dpi不变
byte[] bytes = scaleRange(bytesByFile, 90 * 1024, 150 * 1024);
//文件输出流写入文件
try {
FileOutputStream outstream = new FileOutputStream(filepath);
assert bytesByFile != null;
outstream.write(bytes); // 写入文件
outstream.close(); // 关闭资源
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
//png转jpg格式
public static void pngToJpg(String filepath) {
BufferedImage bufferedImage;
try {
bufferedImage = ImageIO.read(new File(filepath));
BufferedImage newBufferedImage = new BufferedImage(
bufferedImage.getWidth(), bufferedImage.getHeight(),
BufferedImage.TYPE_INT_RGB);
// TYPE_INT_RGB:创建一个RBG图像,24位深度,成功将32位图转化成24位
newBufferedImage.createGraphics().drawImage(bufferedImage, 0, 0,
Color.WHITE, null);
ImageIO.write(newBufferedImage, "jpg", new File(filepath));
} catch (IOException e) {
e.printStackTrace();
}
}
//设置dpi
public static void makeDpi(String filepath, int dpi) throws IOException {
ImageReader reader = ImageIO.getImageReadersByFormatName("jpeg").next();
reader.setInput(new FileImageInputStream(new File(filepath)), true, false);
BufferedImage image = ImageIO.read(new File(filepath));
int w = 2550, h = -1;
FileOutputStream fos = new FileOutputStream(filepath);
JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(fos);
JPEGEncodeParam jpegEncodeParam = jpegEncoder.getDefaultJPEGEncodeParam(image);
jpegEncodeParam.setDensityUnit(JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
jpegEncodeParam.setXDensity(dpi);
jpegEncodeParam.setYDensity(dpi);
jpegEncoder.encode(image, jpegEncodeParam);
fos.close();
}
//将文件转换成Byte数组
public static byte[] getBytesByFile(String pathStr) {
File file = new File(pathStr);
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
byte[] data = bos.toByteArray();
bos.close();
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//此部分为git上其他大佬写的插件,我把里面的核心代码拔出来直接用了
//设置文件的存储大小,单位kb
public static byte[] scaleRange(byte[] sourceBytes, long minSize, long maxSize) {
if (sourceBytes != null && sourceBytes.length > 0 && ((long) sourceBytes.length > maxSize || (long) sourceBytes.length < minSize) && minSize <= maxSize) {
byte[] desImageBytes = new byte[0];
double startAccuracy = 0.0D;
double endAccuracy = 0.0D;
double currentAccuracy = 1.0D;
try {
Object var16;
ByteArrayInputStream inputStream;
ByteArrayOutputStream outputStream;
byte[] currentImageBytes;
if ((long) sourceBytes.length > maxSize) {
startAccuracy = 0.0D;
endAccuracy = 1.0D;
} else {
for (; desImageBytes.length == 0; var16 = null) {
currentAccuracy *= 2.0D;
inputStream = new ByteArrayInputStream(sourceBytes);
outputStream = new ByteArrayOutputStream(sourceBytes.length);
Thumbnails.of(new InputStream[]{inputStream}).scale(currentAccuracy).toOutputStream(outputStream);
currentImageBytes = outputStream.toByteArray();
if ((long) currentImageBytes.length <= maxSize && (long) currentImageBytes.length >= minSize) {
desImageBytes = currentImageBytes;
} else if ((long) currentImageBytes.length > maxSize) {
startAccuracy = currentAccuracy / 2.0D;
endAccuracy = currentAccuracy;
break;
}
}
}
for (; desImageBytes.length == 0; var16 = null) {
currentAccuracy = (startAccuracy + endAccuracy) / 2.0D;
inputStream = new ByteArrayInputStream(sourceBytes);
outputStream = new ByteArrayOutputStream(sourceBytes.length);
Thumbnails.of(new InputStream[]{inputStream}).scale(currentAccuracy).toOutputStream(outputStream);
currentImageBytes = outputStream.toByteArray();
if ((long) currentImageBytes.length > maxSize) {
endAccuracy = currentAccuracy;
} else if ((long) currentImageBytes.length < minSize) {
startAccuracy = currentAccuracy;
} else {
desImageBytes = currentImageBytes;
}
}
} catch (Exception var15) {
desImageBytes = sourceBytes;
}
return desImageBytes;
} else {
return sourceBytes;
}
}
}