Java生成圖片默認分辨率是72dpi,由於需要打印生成圖片,要求圖片分辨率至少300dpi,這個問題整了將近一天時間,最終得到解決,感謝網友的分享。在這里記錄一下,已備后面使用。以下代碼摘抄至https://my.oschina.net/osgit/blog/530283
/** * 接口設計 */ public interface ImageDPIProcessor { /** * 根據文件后綴擴展名判斷是否能進行處理 * * @param fileName * @return */ public boolean canHandle(String fileName); /** * * @param path * @param dpi * dot per inch * @return * @throws IOException * @throws MalformedURLException */ public byte[] process(final BufferedImage srcimage, final int dpi) throws Exception;
PNG處理方式:
public class PngDPIProcessor implements ImageDPIProcessor { //1英寸是2.54里面 private static final double INCH_2_CM = 2.54d; @Override public boolean canHandle(String fileName) { assert fileName != null : "fileName should not be null"; return fileName.endsWith("png") || fileName.endsWith("PNG"); } @Override public byte[] process(BufferedImage image, int dpi) throws MalformedURLException, IOException { for (Iterator<ImageWriter> iw = ImageIO.getImageWritersByFormatName("png"); iw.hasNext();) { ImageWriter writer = iw.next(); ImageWriteParam writeParam = writer.getDefaultWriteParam(); ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB); IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam); if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) { continue; } ByteArrayOutputStream output = new ByteArrayOutputStream(); ImageOutputStream stream = null; try { setDPI(metadata, dpi); stream = ImageIO.createImageOutputStream(output); writer.setOutput(stream); writer.write(metadata, new IIOImage(image, null, metadata), writeParam); } finally { try { stream.close(); } catch (IOException e) { } } return output.toByteArray(); } return null; } private void setDPI(IIOMetadata metadata, int dpi) throws IIOInvalidTreeException { // for PMG, it's dots per millimeter double dotsPerMilli = 1.0 * dpi / 10 / INCH_2_CM; IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize"); horiz.setAttribute("value", Double.toString(dotsPerMilli)); IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize"); vert.setAttribute("value", Double.toString(dotsPerMilli)); IIOMetadataNode dim = new IIOMetadataNode("Dimension"); dim.appendChild(horiz); dim.appendChild(vert); IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0"); root.appendChild(dim); metadata.mergeTree("javax_imageio_1.0", root); } 主要參考文章: https://my.oschina.net/osgit/blog/530283 http://stackoverflow.com/questions/321736/how-to-set-dpi-information-in-an-image
JPEG 處理方式
public class JpegDPIProcessor implements ImageDPIProcessor { private String formatName = "jpeg"; @Override public byte[] process(BufferedImage image, int dpi) throws IOException { for (Iterator<ImageWriter> iw = ImageIO.getImageWritersByFormatName(formatName); iw.hasNext();) { ImageWriter writer = iw.next(); ImageWriteParam writeParams = writer.getDefaultWriteParam(); writeParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); //調整圖片質量 writeParams.setCompressionQuality(1f); IIOMetadata data = writer.getDefaultImageMetadata(new ImageTypeSpecifier(image), writeParams); Element tree = (Element) data.getAsTree("javax_imageio_jpeg_image_1.0"); Element jfif = (Element) tree.getElementsByTagName("app0JFIF").item(0); jfif.setAttribute("Xdensity", dpi + ""); jfif.setAttribute("Ydensity", dpi + ""); jfif.setAttribute("resUnits", "1"); // density is dots per inch ByteArrayOutputStream out = new ByteArrayOutputStream(); ImageOutputStream stream = null; try { stream = ImageIO.createImageOutputStream(out); writer.setOutput(stream); writer.write(data, new IIOImage(image, null, null), writeParams); } finally { stream.close(); } return out.toByteArray(); } return null; } @Override public boolean canHandle(String fileName) { assert fileName != null : "fileName should not be null"; return fileName.endsWith("jpg") || fileName.endsWith("jpeg") || fileName.endsWith("JPG") || fileName.endsWith("JPEG"); } }