用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);
    }
}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM