java 压缩图片大小并保持精度quality方法

发布于 / 随记 / 0条评论 / Tags: java / 1 次浏览

参考帖子https://stackoverflow.com/questions/7951290/re-sizing-an-image-without-losing-quality/16859589

1.代码如下

package com.tddlmj.rstar.util;


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import static java.awt.RenderingHints.VALUE_INTERPOLATION_BICUBIC; 

/**
 * 封面是674/1000
 * s---103
 * b----182
 */
public class ImgUtil {
    public static void convertToWidth(float width, String path) {

    }

    /**
     * Resizes an image to a absolute width and height (the image may not be
     * proportional)
     *
     * @param inputImagePath  Path of the original image
     * @param outputImagePath Path to save the resized image
     * @param scaledWidth     absolute width in pixels
     * @param scaledHeight    absolute height in pixels
     * @throws IOException
     */
    public static void resize(String inputImagePath,
                              String outputImagePath, int scaledWidth, int scaledHeight)
            throws IOException {
        // reads input image
        File inputFile = new File(inputImagePath);
        BufferedImage inputImage = ImageIO.read(inputFile);

        // creates output image
//        BufferedImage outputImage = new BufferedImage(scaledWidth,
//                scaledHeight, inputImage.getType());
        BufferedImage outputImage =  getScaledInstance(inputImage,scaledWidth,scaledHeight, VALUE_INTERPOLATION_BICUBIC,true);
        // scales the input image to the output image
        Graphics2D g2d = outputImage.createGraphics();
        g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
        g2d.dispose();

        // extracts extension of output file
        String formatName = outputImagePath.substring(outputImagePath
                .lastIndexOf(".") + 1);

        // writes to output file
        ImageIO.write(outputImage, formatName, new File(outputImagePath));
    }

    /**
     * Resizes an image by a percentage of original size (proportional).
     *
     * @param inputImagePath  Path of the original image
     * @param outputImagePath Path to save the resized image
     * @param percent         a double number specifies percentage of the output image
     *                        over the input image.
     * @throws IOException
     */
    public static void resize(String inputImagePath,
                              String outputImagePath, double percent) throws IOException {
        File inputFile = new File(inputImagePath);
        BufferedImage inputImage = ImageIO.read(inputFile);
        int scaledWidth = (int) (inputImage.getWidth() * percent);
        int scaledHeight = (int) (inputImage.getHeight() * percent);
        resize(inputImagePath, outputImagePath, scaledWidth, scaledHeight);
    }

    /**
     * Resizes an image by a percentage of original size (proportional).
     *
     * @param inputImagePath  Path of the original image
     * @param outputImagePath Path to save the resized image
     * @param width           a fixed width
     *                        over the input image.
     * @throws IOException
     */
    public static void resizeFixWidth(String inputImagePath,
                              String outputImagePath, int width) throws IOException {
        File inputFile = new File(inputImagePath);
        BufferedImage inputImage = ImageIO.read(inputFile);
        int scaledWidth = width;
        float percent = (float)width /inputImage.getWidth();
        int scaledHeight = (int) (inputImage.getHeight() * percent);
        resize(inputImagePath, outputImagePath, scaledWidth, scaledHeight);
    }

    //https://stackoverflow.com/questions/7951290/re-sizing-an-image-without-losing-quality/16859589
    public static BufferedImage getScaledInstance(BufferedImage img,
                                                  int targetWidth,
                                                  int targetHeight,
                                                  Object hint,
                                                  boolean higherQuality) {
        int type = (img.getTransparency() == Transparency.OPAQUE) ?
                BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage ret = (BufferedImage) img;
        int w, h;
        if (higherQuality) {
            // Use multi-step technique: start with original size, then
            // scale down in multiple passes with drawImage()
            // until the target size is reached
            w = img.getWidth();
            h = img.getHeight();
        } else {
            // Use one-step technique: scale directly from original
            // size to target size with a single drawImage() call
            w = targetWidth;
            h = targetHeight;
        }

        do {
            if (higherQuality && w > targetWidth) {
                w /= 2;
                if (w < targetWidth) {
                    w = targetWidth;
                }
            }

            if (higherQuality && h > targetHeight) {
                h /= 2;
                if (h < targetHeight) {
                    h = targetHeight;
                }
            }

            BufferedImage tmp = new BufferedImage(w, h, type);
            Graphics2D g2 = tmp.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            g2.drawImage(ret, 0, 0, w, h, null);
            g2.dispose();

            ret = tmp;
        } while (w != targetWidth || h != targetHeight);

        return ret;
    }

    /**
     * Test resizing images
     */
    public static void main(String[] args) {
        String inputImagePath = "/home/shenfeng/Downloads/3434s.jpg";
        String outputImagePath1 = "D:/Photo/Puppy_Fixed.jpg";
        String outputImagePath2 = "/home/shenfeng/Downloads/333.jpg";
        String outputImagePath3 = "D:/Photo/Puppy_Bigger.jpg";

        try {
            // resize to a fixed width (not proportional)
//            int scaledWidth = 1024;
//            int scaledHeight = 768;
//            ImgUtil.resize(inputImagePath, outputImagePath1, scaledWidth, scaledHeight);

            // resize smaller by 50%
            ImgUtil.resizeFixWidth(inputImagePath, outputImagePath2, 103);

            // resize bigger by 50%
//            percent = 1.5;
//            ImgUtil.resize(inputImagePath, outputImagePath3, percent);

        } catch (IOException ex) {
            System.out.println("Error resizing the image.");
            ex.printStackTrace();
        }
    }
}

2.传值解释如下:


    VALUE_INTERPOLATION_NEAREST_NEIGHBOR: Specific hint that provides higher performance, but lower-quality, "blocky" results.
    VALUE_INTERPOLATION_BILINEAR: Specific hint that is typically a bit slower, but provides higher-quality, "filtered" results.
    VALUE_INTERPOLATION_BICUBIC: Specific hint that is similar to BILINEAR except that it uses more samples when filtering and therefore has generally higher quality than BILINEAR. (Note: this hint constant has been available since JDK 1.2, but was not implemented by Sun until the JDK 5 release; prior to that release, this hint was synonymous with BILINEAR.)

    评论区(暂无评论)