
DPI
维基
(英语:Dots Per Inch,每英寸点数)是一个量度单位,用于点阵数位影像,意思是指每一英寸长度中,取样或可显示或输出点的数目。
单位转换
1 英寸=2.54 厘米
1点 = 1/72英寸
1点 = 1/300英寸
问题
印刷业定制的图片剪辑功能,需要以 40 * 40 CM 或其他宽高规格来处理原始图片。请问应该怎么做?
解答
首先,印刷的通常分辨率为300dpi,就是一英寸300像素。即 DPI = 300;
所以,
假设宽度为 width,高度为 height,单位: CM;
得到,图片缩放后的最终宽高,
宽: width / 2.54 *DPI
高: height / 2.54 * DPI
代码
原图需要按指定宽高比例,配合页面选框进行裁剪。
裁剪后的图片,再进行以下步骤处理。
获取图片对象
1
File file = new File(filePath.toString());
转换获取 BufferedImage 对象
1
BufferedImage img = ImageIO.read(file)
获取图片宽高
1
2
double sourceW = img.getWidth();
double sourceH = img.getHeight();
最终的宽高
1
2
3
4
5
int DPI = 300,
width = 30, // cm
height = 30; // cm
double targetW = width / 2.54 * DPI;
double targetH = height / 2.54 * DPI;
计算压缩比(等比压缩)
1
2
3
4
5
6
7
8
9
10
double sx = (double) targetW / sourceW;
double sy = (double) targetH / sourceH;
if (sx > sy) {
sx = sy;
targetW = (int) (sx * source.getWidth());
} else if (sx < sy) {
sy = sx;
targetH = (int) (sy * source.getHeight());
}
空白画布
1
2
String type = "PNG";
BufferedImage target = new BufferedImage(targetW, targetH, type);
绘制图片
1
2
3
Graphics2D g = target.createGraphics(); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
g.dispose();
转换 byte[]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
byte[] result = null;
ByteArrayOutputStream outStream = null;
try {
if (image != null) {
outStream = new ByteArrayOutputStream();
ImageIO.write(image,format,outStream);
result = outStream.toByteArray();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outStream != null) {
try {
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
存放新图片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
BufferedOutputStream stream = null;
try {
File file = new File(outputFile);
if (file.exists() && !isCover) {
return Boolean.FALSE; // 源文件已经存在
}
FileOutputStream out = new FileOutputStream(file);
stream = new BufferedOutputStream(out);
stream.write(b);
} catch (Exception e) {
String fullStackTrace = ExceptionUtils.getStackTrace(e);
LOGGER.error(fullStackTrace);
return Boolean.FALSE;
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
String fullStackTrace = ExceptionUtils.getStackTrace(e);
LOGGER.error(fullStackTrace);
return Boolean.FALSE;
}
}
}
return Boolean.TRUE;
PS. 遇到新问题时,不要害怕,先分析再 Coding。