Thursday, August 13, 2009

JAI resize images

JAI provides two operator to resize pictures, “SubsampleAverage” and “Scale”.  In most scenarios, “SubsampleAverage” provides better quality. But if the picture is mainly composed by declining straight line. “Scale” may be better.

sample of SubsampleAverage sample of Scale
subSampleAverageSample-01

scaleSample-01

 

Sample code

package com.elasticpath;

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.RenderingHints;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.renderable.ParameterBlock;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;
import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.swing.JFrame;
import javax.swing.JPanel;

import com.sun.media.jai.widget.DisplayJAI;

public class JAITest extends JFrame {

private static final String PICTURE = "./pics/td83504.jpg";

public static void main(String[] args) throws IOException {

for (int y = 0; y <=1; y++) {
for (double i = 0.8; i < 0.9; i = i + 0.1) {
JAITest testFrame = new JAITest(y, i, Interpolation.getInstance(Interpolation.INTERP_BICUBIC));
JAITest testFrame2 = new JAITest(y, i, Interpolation.getInstance(Interpolation.INTERP_BICUBIC_2));
JAITest testFrame3 = new JAITest(y, i, Interpolation.getInstance(Interpolation.INTERP_BILINEAR));
JAITest testFrame4 = new JAITest(y, i, Interpolation.getInstance(Interpolation.INTERP_NEAREST));
}
}
}

/**
* @param interpolation
* @throws IOException
*/
public JAITest(int y, double scale, Interpolation interpolation) throws IOException {

JPanel contentPane;
BorderLayout borderLayout1 = new BorderLayout();

contentPane = (JPanel) getContentPane();
contentPane.setLayout(borderLayout1);
setExtendedState(JFrame.MAXIMIZED_BOTH);

enableEvents(AWTEvent.WINDOW_EVENT_MASK);

InputStream inputStream = new BufferedInputStream(new FileInputStream(PICTURE));

BufferedImage bufferedImage = ImageIO.read(inputStream);
int originalWidth = bufferedImage.getWidth();
int originalHeight = bufferedImage.getHeight();

double newWidth = originalWidth * scale;
double newHeight = originalHeight * scale;

double scalex = Math.ceil(newWidth) / originalWidth;
double scaley = Math.ceil(newHeight) / originalHeight;

ParameterBlock parameterBlock = new ParameterBlock();
parameterBlock.addSource(bufferedImage);

//TEST different renderingHints
RenderingHints renderingHints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
renderingHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);

PlanarImage newImage = null;
if (y == 0) {
parameterBlock.add((float)scalex);
parameterBlock.add((float)scaley);
parameterBlock.add((float)0.0);
parameterBlock.add((float)0.0);
parameterBlock.add(interpolation);
newImage = JAI.create("Scale", parameterBlock, renderingHints);
} else {
parameterBlock.add(scalex);
parameterBlock.add(scaley);
newImage = JAI.create("SubsampleAverage", parameterBlock, renderingHints);
}

// Display the final image in a DisplayJAI widget
DisplayJAI displayWidget = new DisplayJAI(newImage);
// System.out.println("Created the displayWidget");
contentPane.add(displayWidget, BorderLayout.CENTER);

pack();
//show();
this.setVisible(true);
}

protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}

}

Also, slightly OT but while we're on the subject of images, the jpeg encoding parameters in the image controller don't specify the subsampling, so by default standard subsampling (4:2:2) is used. You can specify no subsampling by adding:

param.setVerticalSubsampling(0, 1);
param.setVerticalSubsampling(1, 1);                    
param.setVerticalSubsampling(2, 1);                    
param.setHorizontalSubsampling(0, 1);                    
param.setHorizontalSubsampling(1, 1);                    
param.setHorizontalSubsampling(2, 1);

This will increase the file size of the output, but will increase the level of detail (especially noticeable around text in images). Most people won't notice a difference, so only do this if you're a fanatic


 


 


 


  

No comments:

Post a Comment