00001
00004 package edu.stanford.hci.r3.util.graphics;
00005
00006 import java.awt.RenderingHints;
00007 import java.awt.Transparency;
00008 import java.awt.color.ColorSpace;
00009 import java.awt.color.ICC_ColorSpace;
00010 import java.awt.color.ICC_Profile;
00011 import java.awt.image.ColorModel;
00012 import java.awt.image.ComponentColorModel;
00013 import java.awt.image.DataBuffer;
00014 import java.awt.image.PixelInterleavedSampleModel;
00015 import java.awt.image.SampleModel;
00016 import java.awt.image.renderable.ParameterBlock;
00017 import java.io.File;
00018
00019 import javax.media.jai.BorderExtender;
00020 import javax.media.jai.JAI;
00021 import javax.media.jai.PlanarImage;
00022 import javax.media.jai.TiledImage;
00023
00032 public class JAIUtils {
00033
00037 private static final RenderingHints RH_BORDER_REFLECT = new RenderingHints(
00038 JAI.KEY_BORDER_EXTENDER, BorderExtender.createInstance(BorderExtender.BORDER_REFLECT));
00039
00047 public static TiledImage createWritableBuffer(int width, int height) {
00048 return createWritableBuffer(width, height, 4);
00049 }
00050
00058 private static TiledImage createWritableBuffer(int width, int height, int numBands) {
00059
00060 final ICC_Profile profile = ICC_Profile.getInstance(ColorSpace.CS_sRGB);
00061 final boolean hasAlpha = (numBands > 3) ? true : false;
00062 final ColorModel colorModel = new ComponentColorModel(new ICC_ColorSpace(profile),
00063 hasAlpha,
00064 false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
00065
00066
00067 final int defaultTileSize = 128;
00068 final int[] bandOffsets = new int[numBands];
00069 for (int i = 0; i < numBands; i++) {
00070 bandOffsets[i] = numBands - 1 - i;
00071 }
00072
00073 final SampleModel sampleModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
00074 defaultTileSize, defaultTileSize , numBands ,
00075 numBands * defaultTileSize, bandOffsets);
00076
00077 return new TiledImage(0, 0, width, height, 0, 0, sampleModel, colorModel);
00078 }
00079
00088 public static TiledImage createWritableBufferWithoutAlpha(int width, int height) {
00089 return createWritableBuffer(width, height, 3);
00090 }
00091
00101 public static PlanarImage createZeroImage(int width, int height, int numBands) {
00102 final Byte[] bandValues = new Byte[numBands];
00103 for (int i = 0; i < numBands; i++) {
00104 bandValues[i] = new Byte((byte) 0);
00105 }
00106 final ParameterBlock pb = new ParameterBlock();
00107 pb.add(new Float(width));
00108 pb.add(new Float(height));
00109 pb.add(bandValues);
00110 return (PlanarImage) JAI.create("constant", pb);
00111 }
00112
00117 public static PlanarImage readJPEG(final File jpegFile) {
00118 return JAI.create("fileload", jpegFile.getAbsolutePath());
00119 }
00120
00130 public static PlanarImage scaleImage(PlanarImage src, InterpolationQuality interpQuality,
00131 float scaleFactorX, float scaleFactorY) {
00132
00133
00134 final ParameterBlock pb = new ParameterBlock();
00135 pb.addSource(src);
00136 pb.add(scaleFactorX);
00137 pb.add(scaleFactorY);
00138 pb.add(0.0f);
00139 pb.add(0.0f);
00140 pb.add(interpQuality.getInterpolation());
00141
00142
00143 return JAI.create("scale", pb, RH_BORDER_REFLECT);
00144 }
00145
00146 public static PlanarImage scaleImageIteratively(PlanarImage src, float scaleFactorX,
00147 float scaleFactorY) {
00148 return scaleImageIterativelyToDimensions(src, InterpolationQuality.BILINEAR, (int) Math
00149 .round(src.getWidth() * scaleFactorX), (int) Math.round(src.getHeight()
00150 * scaleFactorY));
00151 }
00152
00162 public static PlanarImage scaleImageIteratively(PlanarImage src,
00163 InterpolationQuality interpQuality, float scaleFactorX, float scaleFactorY) {
00164 return scaleImageIterativelyToDimensions(src, interpQuality, (int) Math.round(src
00165 .getWidth()
00166 * scaleFactorX), (int) Math.round(src.getHeight() * scaleFactorY));
00167 }
00168
00169 private static PlanarImage scaleImageIterativelyToDimensions(PlanarImage src,
00170 InterpolationQuality interpQuality, int width, int height) {
00171
00172 double minScale = .5;
00173
00174
00175
00176 int iterations = 0;
00177 final double targetWidth = (double) width;
00178 final double targetHeight = (double) height;
00179 while (!(src.getWidth() == width & src.getHeight() == height) && iterations < 10) {
00180 float scaleFactorX = (float) Math.max(minScale, targetWidth / src.getWidth());
00181 float scaleFactorY = (float) Math.max(minScale, (targetHeight / src.getHeight()));
00182
00183 src = scaleImage(src, interpQuality, scaleFactorX, scaleFactorY);
00184 iterations++;
00185 }
00186 return src;
00187 }
00188
00200 public static PlanarImage scaleImageToFit(PlanarImage src, int width, int height) {
00201 return scaleImageToSize(src, width, height, InterpolationQuality.BICUBIC, true);
00202 }
00203
00214 public static PlanarImage scaleImageToSize(PlanarImage src, int targetWidth, int targetHeight,
00215 InterpolationQuality quality, boolean maintainAspectRatio) {
00216 int oldWidth = src.getWidth();
00217 int oldHeight = src.getHeight();
00218
00219 float testScaleFactorX = (float) targetWidth / (float) oldWidth;
00220 float testScaleFactorY = (float) targetHeight / (float) oldHeight;
00221
00222 float scaleFactorX = 0;
00223 float scaleFactorY = 0;
00224
00225
00226 if (maintainAspectRatio) {
00227 float min = Math.min(testScaleFactorX, testScaleFactorY);
00228 scaleFactorX = min;
00229 scaleFactorY = min;
00230 } else {
00231 scaleFactorX = testScaleFactorX;
00232 scaleFactorY = testScaleFactorY;
00233 }
00234
00235 return scaleImageIteratively(src, quality, scaleFactorX, scaleFactorY);
00236 }
00237
00246 public static void writeImageToJPEG(PlanarImage img, File path) {
00247 ImageUtils.writeImageToJPEG(img.getAsBufferedImage(), 100, path);
00248 }
00249
00250 }