package com.java.app.image;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.media.jai.JAI;
import javax.media.jai.OpImage;
import javax.media.jai.RenderedOp;
import javax.media.jai.operator.SubsampleAverageDescriptor;
import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.media.jai.codec.SeekableStream;
/**
* Utility to resize image or create image thumbnail
* @author [email protected]
* @required: Java Advanced Imaging API (JAI) library
*/
public class ImageThumbnail {
public static void main(String[] args) throws Exception {
ImageThumbnail it = new ImageThumbnail();
JPanel p = new JPanel(new GridLayout(1,1,1,1));
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss.S");
String fileName = "view.jpg";
System.out.println("Begin "+sdf.format(new Date()));
InputStream inputStream = new FileInputStream(fileName);
BufferedImage bimg = it.getThumbnail(inputStream, 128);
//Image image = ImageIO.read(new File(fileName));
//BufferedImage bimg = it.getThumbnail((BufferedImage)image, 128, 96);
it.saveJpeg("temp.jpg", bimg, 0.7f);
System.out.println("Finish "+sdf.format(new Date()));
ImageIcon icon = new ImageIcon(bimg);
p.add(new JLabel(icon));
JFrame f = new JFrame("Image File");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JScrollPane(p));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public ImageThumbnail() {
}
/**
* Create the image thumbnail, resize the image
* @param imageInputStream as InputStream
* @param targetWidth as int
* @return BufferedImage
* @throws IOException
*/
public BufferedImage getThumbnail(InputStream imageInputStream, int targetWidth) throws IOException {
SeekableStream seekableImageStream;
RenderedOp originalImage, resizedImage;
RenderedImage image;
RenderingHints hints;
BufferedImage bufferedImage;
System.setProperty("com.sun.media.jai.disableMediaLib", "true"); //get rid of exception for not using native acceleration
seekableImageStream = SeekableStream.wrapInputStream(imageInputStream, true);
originalImage = JAI.create("stream", seekableImageStream);
((OpImage) originalImage.getRendering()).setTileCache(null);
image = originalImage;
int imageWidth = originalImage.getWidth();
double scale = (targetWidth > 0 && imageWidth > targetWidth) ? (double) targetWidth / imageWidth : 1.0;
hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
resizedImage = SubsampleAverageDescriptor.create(image, new Double(scale), new Double(scale), hints);
bufferedImage = resizedImage.getAsBufferedImage();
return bufferedImage;
}
/**
* Here is another method but seems to be slower than above for some JPG image file
* Create and get the image thumbnail
* @param image as BufferedImage
* @param thWidth
* @param thHeight
*/
public BufferedImage getThumbnail(BufferedImage image, int thWidth, int thHeight) throws Exception {
int w = image.getWidth();
int h = image.getHeight();
BufferedImage thumbnail = new BufferedImage(thWidth, thHeight, BufferedImage.TYPE_INT_RGB);
float scalex = ((float)w) / ((float) thWidth);
float scaley = ((float)h) / ((float) thHeight);
float scale = Math.min(scalex, scaley);
if (scale < 1) scale = 1;
BufferedImage scaled = createResizedImage(image, Math.round(w/scale), Math.round(h/scale));
Graphics2D g = thumbnail.createGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, thWidth, thHeight);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(scaled, (thWidth - scaled.getWidth()) / 2, (thHeight - scaled.getHeight()) / 2, null);
g.dispose();
return thumbnail;
}
/**
* Resize the image
* @param img as BufferedImage
* @param targetWidth
* @param targetHeight
*/
private BufferedImage createResizedImage(BufferedImage img, int targetWidth, int targetHeight) {
if (img.getWidth() == targetHeight && img.getHeight() == targetHeight) return img;
boolean higherQuality = true;
boolean isIndexColorModel = img.getColorModel() instanceof IndexColorModel;
int type;
if (!isIndexColorModel){
type = (img.getColorModel().hasAlpha()) ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;
}
else {type = img.getType();}
BufferedImage ret = (BufferedImage) img;
int w, h;
if (higherQuality) {
w = img.getWidth();
h = img.getHeight();
} else {
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 = isIndexColorModel ?
new BufferedImage(w, h, type, (IndexColorModel)img.getColorModel()) :
new BufferedImage(w, h, type);
Graphics2D g2 = tmp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(ret, 0, 0, w, h, null);
g2.dispose();
ret = tmp;
} while (w != targetWidth || h != targetHeight);
return ret;
}
/**
* Write the jpeg file
* @param outFile
* @param bimg
* @param quality
*/
public void saveJpeg(String outFile, BufferedImage bimg, float quality) throws ImageFormatException, IOException {
FileOutputStream out = new FileOutputStream(outFile);
// Encodes image as a JPEG data stream
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimg);
param.setQuality(quality, true);
encoder.setJPEGEncodeParam(param);
encoder.encode(bimg);
}
}