用java imageio调整图片DPI,例如从96调整为300
因项目需求把图片的DPI值提升到300,否则OCR识别产生错乱:直接上源码:
1、图片处理接口:
package util.image.dpi; import java.awt.image.BufferedImage; import java.io.IOException; /** * 图片处理接口设计 * @author jffan * */ public interface ImageDPIProcessor { /** * 根据文件后缀扩展名判断是否能进行处理 * @param fileName * @return */ public boolean canHandle(String fileName); /** * 处理图片,设置图片DPI值 * @param path * @param dpi dot per inch * @return * @throws IOException */ public byte[] process(final BufferedImage srcimage, final int dpi) throws Exception; }
2、JEPG图片的实现类
package util.image.dpi; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Iterator; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.stream.ImageOutputStream; import org.w3c.dom.Element; /** * JPEG 处理方式 * @author jffan * */ public class JpegDPIProcessor implements ImageDPIProcessor { private String formatName = "jpeg"; /** * 处理图片,设置图片DPI值 * @param path * @param dpi dot per inch * @return * @throws IOException */ @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; } /** * 根据文件后缀扩展名判断是否能进行处理 * @param fileName * @return */ @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"); } }
3、PNG图片的实现类
package util.image.dpi; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.util.Iterator; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.stream.ImageOutputStream; /** * PNG图片的实现类 * @author jffan * */ public class PngDPIProcessor implements ImageDPIProcessor { /** * 1英寸是2.54里面 */ private static final double INCH_2_CM = 2.54d; /** * 根据文件后缀扩展名判断是否能进行处理 * @param fileName * @return */ @Override public boolean canHandle(String fileName) { assert fileName != null : "fileName should not be null"; return fileName.endsWith("png") || fileName.endsWith("PNG"); } /** * 处理图片,设置图片DPI值 * @param path * @param dpi dot per inch * @return * @throws IOException */ @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; } /** * 设置图片的DPI值 * @param metadata * @param dpi * @throws IIOInvalidTreeException * @author 范继峰 * @date 2019年7月30日上午10:53:18 * @return void */ 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); } }