2012年8月30日 星期四

Java-image 高解析縮圖

很多時候會用到縮圖的功能, 自己寫, 說真的我還真不會, 找了很多 library, 這套算是最好用的, 畫質也很好. java-image-scaling 有興趣的人可以下載回來玩看看, 這裡也順便分享一下自己寫的一些程式.
程式中, 存檔時只支援 .jpg or .jpeg.
另外, 有其它需求再自己改一下囉, 基本上支援, 依寬,高, 或最長的寬或高去縮圖.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Locale;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.mortennobel.imagescaling.AdvancedResizeOp;
import com.mortennobel.imagescaling.ResampleOp;

/**
 * image 的工具, 主要提供縮放的功能
 * 
 * @author MarkYeh
 * 
 */
public class ImageUtil {

  private static final Log log = LogFactory.getLog(ImageUtil.class);
  
  /**
   * 判斷原來圖片的寬,有沒有比要縮的寬度還寬
   * 
   * @param srcImage
   * @param width
   * @return
   * @throws IOException
   */
  public boolean checkResizeByWidth(String srcImage, int width)
      throws IOException {
    return checkResizeByWidth(new File(srcImage), width);
  }

  public boolean checkResizeByWidth(File srcImageFile, int width)
      throws IOException {
    BufferedImage bf = ImageIO.read(srcImageFile);
    int oriWidth = bf.getWidth();
    if (oriWidth <= width) {
      return false;
    }
    return true;
  }
  
  /**
   * 判斷原來圖片的高,有沒有比要縮的高度還高
   * 
   * @param srcImage
   * @param width
   * @return
   * @throws IOException
   */
  public boolean checkResizeByHeight(String srcImage, int height)
      throws IOException {
    return checkResizeByHeight(new File(srcImage), height);
  }

  public boolean checkResizeByHeight(File srcImageFile, int height)
      throws IOException {
    BufferedImage bf = ImageIO.read(srcImageFile);
    int oriHeight = bf.getHeight();
    if (oriHeight <= height) {
      return false;
    }
    return true;
  }

  /**
   * 將最長寬或高縮放成 width的設定
   * 
   * @param imgName
   * @param type
   * @param width
   * @return
   */
  public static void resizeImage(String imgName, int width, String toFileName)
      throws IOException {
    try {
      resizeImage(ImageIO.read(new File(imgName)), width, toFileName);
    } catch (IOException e) {
      log.error(e.getMessage(), e);
    }
  }

  /**
   * 將最長寬或高縮放成 width 的設定
   * 
   * @param imgName
   * @param type
   * @param width
   * @return
   * 
   */
  public static void resizeImage(BufferedImage image, int newWidth,
      String toFileName) throws IOException {

    // Original size
    int imageWidth = image.getWidth(null);
    int imageHeight = image.getHeight(null);

    if (imageWidth > imageHeight) {
      imageWidth = newWidth;
      imageHeight = (newWidth * imageHeight) / imageWidth;
    } else {
      imageWidth = (newWidth * imageWidth) / imageHeight;
      imageHeight = newWidth;
    }

    reSizeAndSave(image, imageWidth, imageHeight, toFileName);
  }

  public static void resizeImageWithNewWidth(URL url, int newWidth,
      String toFileName) {
    try {
      resizeImageWithNewWidth(ImageIO.read(url), newWidth, toFileName);
    } catch (IOException e) {
      log.error(e.getMessage(), e);
    }
  }

  public static void resizeImageWithNewWidth(String imgName, int newWidth,
      String toFileName) {
    try {
      resizeImageWithNewWidth(ImageIO.read(new File(imgName)), newWidth, toFileName);
    } catch (IOException e) {
      log.error(e.getMessage(), e);
    }
  }

  public static void resizeImageWithNewWidth(BufferedImage image, int newWidth,
      String toFileName) throws IOException {
    resizeImageWithNewWidth(image, newWidth, toFileName, false);
  }

  public static void resizeImageWithNewWidth(BufferedImage image, int newWidth,
      String toFileName, boolean checkWidth) throws IOException {

    // Original size
    int imageWidth = image.getWidth(null);
    int imageHeight = image.getHeight(null);

    if (checkWidth && imageWidth < newWidth) {
      reSizeAndSave(image, imageWidth, (imageWidth * imageHeight) / imageWidth,
          toFileName);
    } else {
      reSizeAndSave(image, newWidth, (newWidth * imageHeight) / imageWidth,
          toFileName);
    }
  }

  /**
   * 依高縮放
   * 
   * @param image
   * @param imageUtilType
   * @param maxWidth
   * @return
   */
  public static void resizeImageWithNewHeight(String imgName, int newHeight,
      String toFileName) throws IOException {
    try {
      resizeImageWithNewHeight(ImageIO.read(new File(imgName)), newHeight,
          toFileName);
    } catch (IOException e) {
      log.error(e.getMessage(), e);
    }
  }

  public static void resizeImageWithNewHeight(BufferedImage image,
      int newHeight, String toFileName) throws IOException {

    // Original size
    int imageWidth = image.getWidth(null);
    int imageHeight = image.getHeight(null);

    reSizeAndSave(image, (newHeight * imageWidth) / imageHeight, newHeight,
        toFileName);
  }

  /**
   * 縮放與存檔, gif and png 不能壓縮, jpg 則壓縮後存檔
   * 
   * @param source
   * @param width
   * @param height
   * @param toFileName
   * @throws IOException
   */
  private static void reSizeAndSave(BufferedImage source, int width,
      int height, String toFileName) throws IOException {
    
    if (!toFileName.toLowerCase().matches("(.*\\.jpe?g)")) {
      throw new IllegalArgumentException("存儲的附檔名只能是 jpg 或 jpeg : " + toFileName);
    }
    
    ResampleOp resampleOp = new ResampleOp(width, height);
    resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
    BufferedImage dest = resampleOp.filter(source, null);

    // 檢查圖檔儲存的資料夾是否已存在, 不存在則建立資料夾
    String path = toFileName;
    
    File containerDir = new File(path);
    if (!containerDir.getParentFile().isDirectory()) {
      containerDir.getParentFile().mkdirs();
    }

    if (source.getType() == BufferedImage.TYPE_CUSTOM) { // png
      String format = "png";
      ImageIO.write(dest, format, new File(toFileName));
    } else if (source.getType() == BufferedImage.TYPE_BYTE_INDEXED) { // gif
      String format = "png";
      ImageIO.write(dest, format, new File(toFileName));
    } else {
      ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
      ImageOutputStream ios = ImageIO.createImageOutputStream(new File(toFileName));
      writer.setOutput(ios);
      ImageWriteParam iwparam = new JPEGImageWriteParam(Locale.getDefault());
      iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
      iwparam.setCompressionQuality(0.95F);
      try {
        writer.write(null, new IIOImage(dest, null, null), iwparam);
        ios.flush();
        writer.abort();
        writer.dispose();
      } finally {
        if (ios != null) {
          ios.close();
        }
        if (writer != null) {
        }
      }
    }
  }

  public static void main(String[] args) throws Exception {
    ImageUtil.resizeImage("D:\\222.jpg", 200, "D:\\200_wh.jpg");
    ImageUtil.resizeImageWithNewWidth("D:\\222.jpg", 200, "D:\\aa\\200_w.jpg");
    ImageUtil.resizeImageWithNewHeight("D:\\222.jpg", 200, "D:\\aa\\200_h.jpg");
    System.out.println("done");
  }

}

1 則留言:

  1. 小胖
    你有個地方錯囉


    if (imageWidth > imageHeight) {
    imageHeight = (newWidth * imageHeight) / imageWidth;
    } else {

    這裡
    imageWidth = newWidth;
    應該放在後面吧

    回覆刪除