2017-03-08 11 views
0

私のJava Spring MVC Web Applicationには、任意のサイズの画像をアップロードするオプションがあります。現在、指定された幅を超えるアップロードされた画像のサイズを縮小するAPIがあります。私はそのために、次のコードを使用します。アップロード中の画像をJavaで圧縮する

import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.image.BufferedImage; 
import java.awt.image.renderable.ParameterBlock; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.Properties; 
import javax.imageio.ImageIO; 
import javax.media.jai.JAI; 
import javax.media.jai.PlanarImage; 
import javax.media.jai.RenderedOp; 

public class ImageRescale 
{ 
    private static RenderingHints hints; 

    static 
    { 
     hints = new RenderingHints(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); 
     hints.put(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
     hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 

     /* 
     * this block is to silence the warning that we're not using JAI 
     * native acceleration but are using the pure java implementation. 
     */ 
     Properties p = new Properties(System.getProperties()); 
     p.put("com.sun.media.jai.disableMediaLib", "true"); 
     System.setProperties(p); 
    } 


    public static byte[] getScaledInstance(byte[] image, int maxWidth) 
    { 
     InputStream in = new ByteArrayInputStream(image); 
     BufferedImage img = null; 
     try 
     { 
      img = ImageIO.read(in); 

     double scale = (double) maxWidth/img.getWidth(); 
     if (scale > 1.0d) 
     { 
      return image; 
     } 
     else if (scale > 0.5d && scale < 1.0d) 
     { 
      return getByteArray(getScaledDownByGraphics(img, scale)); 
     } 
     else if (scale <= 0.5d) 
     { 
      return getByteArray(getScaledDownByJAI(img, scale)); 
     } 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
     return image; 
    } 

    public static byte[] getByteArray(BufferedImage img) 
    { 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     byte[] imageInByte = null; 
     try 
     { 
      ImageIO.write(img, "jpg", baos); 
      baos.flush(); 
      imageInByte = baos.toByteArray(); 
      baos.close(); 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
     return imageInByte; 
    } 

    /** 
    * See http://www.digitalsanctuary.com/tech-blog/java/how-to-resize-uploaded-images-using-java-better-way.html 
    * This instance seems to produce quality images ONLY when you are 
    * scaling down to something less than 50% of the original size. 
    * @param img 
    * @param scale 
    * @return the scaled image 
    */ 
    private static BufferedImage getScaledDownByJAI(BufferedImage img, double scale) 
    { 
     if(scale > 1.0d) 
     { 
      throw new RuntimeException("Can't scale according to " + scale + " : This method only scales down."); 
     } 
     PlanarImage originalImage = PlanarImage.wrapRenderedImage(img); 
     // now resize the image 
     ParameterBlock paramBlock = new ParameterBlock(); 
     paramBlock.addSource(originalImage); // The source image 
     paramBlock.add(scale); // The xScale 
     paramBlock.add(scale); // The yScale 
     paramBlock.add(0.0); // The x translation 
     paramBlock.add(0.0); // The y translation 
     RenderedOp resizedImage = JAI.create("SubsampleAverage", paramBlock, hints); 
     return resizedImage.getAsBufferedImage();  
    } 

    /** 
    * This method produces high quality images when target scale is greater 
    * than 50% of the original. 
    * @param img 
    * @param scale 
    * @return the scaled image 
    */ 
    private static BufferedImage getScaledDownByGraphics(BufferedImage img, double scale) 
    { 
     final float scaleFactor = 0.8f; 

       BufferedImage ret = (BufferedImage)img; 
       int w = img.getWidth(); 
       int h = img.getHeight(); 

       int targetWidth = (int)(img.getWidth() * scale); 
       int targetHeight = (int)(img.getHeight() * scale); 

       int loopCount = 0; 
       int maxLoopCount = 20; 
       BufferedImage tmp; 
       do { 
         if (w > targetWidth) { 
           w *= scaleFactor; 
           if (w < targetWidth) { 
             w = targetWidth; 
           } 
         } 
         if (h > targetHeight) { 
           h *= scaleFactor; 
           if (h < targetHeight) { 
             h = targetHeight; 
           } 
         } 
         tmp = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
         Graphics2D g2 = tmp.createGraphics(); 

         g2.addRenderingHints(hints); 
         g2.drawImage(ret, 0, 0, w, h, null); 
         g2.dispose(); 

         ret = tmp; 
         if(++loopCount > maxLoopCount) { 
           throw new RuntimeException("Hit maximum loop count " + maxLoopCount); 
         } 
       } while (w != targetWidth || h != targetHeight); 
       return ret;  
    } 
} 

は、しかし、私は今したいことはすべてアップロードされた画像を圧縮して、私がイメージのためのWeb標準であると信じて周り72 dpiにその解像度をダウンさせるAPIです。私がこれを達成できる方法はありますか?

+1

「圧縮」と書いたときに「サイズ変更」を意味しますか?画像の大きさをmmまたはインチで測定するか、または画像のdpiを知っているかを知ると、そのことができます。この情報は、画像ファイルのメタデータに埋め込むことも、別々に渡すこともできます。 – Henry

+0

すべての画像の解像度を約72dpiにします。幅と高さを減らさずに。 –

答えて

0

これが役立つかどうか確認できますか?

/** 
* 
* @param bi image 
* @param mimeType type 
* @param quality quality 
* @return compressed image 
* @throws IOException on error 
*/ 
private static BufferedImage compressImage(BufferedImage bi, String mimeType 
     , float quality) throws IOException { 
    // converting buffered image to byte array 

    // do not compress GIFs 
    if (mimeType.equalsIgnoreCase("image/gif")) { 
     return bi; 
    } 

    ImageWriter writer = ImageIO.getImageWritersByMIMEType(mimeType).next(); 
    ImageWriteParam iwp = writer.getDefaultWriteParam(); 

    if (!mimeType.equalsIgnoreCase("image/png") && !mimeType.equalsIgnoreCase("image/bmp")) { 
     iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 
     iwp.setCompressionQuality(quality); 
    } 

    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    BufferedOutputStream bos = new java.io.BufferedOutputStream(baos); 
    ImageOutputStream ios = ImageIO.createImageOutputStream(bos); 
    writer.setOutput(ios); 

    IIOImage optimizedImage = new IIOImage(bi, null, null); 
    writer.write(null, optimizedImage, iwp); 
    writer.dispose(); 
    baos.flush(); 

    ByteArrayInputStream in = new ByteArrayInputStream(baos.toByteArray()); 
    return ImageIO.read(in); 
} 
関連する問題