00001 package edu.stanford.hci.r3.util.graphics;
00002
00003 import java.awt.Dimension;
00004 import java.awt.Graphics2D;
00005 import java.awt.image.BufferedImage;
00006 import java.awt.image.RenderedImage;
00007 import java.io.BufferedOutputStream;
00008 import java.io.File;
00009 import java.io.FileNotFoundException;
00010 import java.io.FileOutputStream;
00011 import java.io.IOException;
00012 import java.sql.Timestamp;
00013
00014 import javax.imageio.ImageIO;
00015 import javax.media.jai.PlanarImage;
00016
00017 import com.drew.imaging.jpeg.JpegMetadataReader;
00018 import com.drew.imaging.jpeg.JpegProcessingException;
00019 import com.drew.metadata.Directory;
00020 import com.drew.metadata.Metadata;
00021 import com.drew.metadata.MetadataException;
00022 import com.drew.metadata.exif.ExifDirectory;
00023 import com.drew.metadata.jpeg.JpegDirectory;
00024 import com.sun.image.codec.jpeg.ImageFormatException;
00025 import com.sun.image.codec.jpeg.JPEGCodec;
00026 import com.sun.image.codec.jpeg.JPEGEncodeParam;
00027 import com.sun.image.codec.jpeg.JPEGImageEncoder;
00028
00037 public class ImageUtils {
00038
00044 public static BufferedImage createWritableBuffer(int width, int height) {
00045 return new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
00046 }
00047
00054 public static long getTimeFromString(String timestampString) {
00055
00056
00057
00058 if (timestampString == null) {
00059 return new Timestamp(0).getTime();
00060 }
00061 if (timestampString.trim().equals("")) {
00062 return new Timestamp(0).getTime();
00063 }
00064
00065
00066 String ymd = timestampString.substring(0, 11);
00067 ymd = ymd.replaceAll(":", "-");
00068
00069
00070 final String hms = timestampString.substring(11) + ".000000000";
00071
00072
00073 final String ts = ymd + hms;
00074
00075 return Timestamp.valueOf(ts).getTime();
00076 }
00077
00081 public static boolean isJPEGFile(File imageFile) {
00082 final String fileName = imageFile.getName().toLowerCase();
00083 if (fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")) {
00084 return true;
00085 } else {
00086 return false;
00087 }
00088 }
00089
00096 public static String readCaptureDateFromEXIF(File photoFile) {
00097 Metadata metadata = null;
00098 try {
00099 metadata = JpegMetadataReader.readMetadata(photoFile);
00100 } catch (JpegProcessingException e) {
00101
00102
00103 return null;
00104 }
00105
00106 if (metadata == null) {
00107 return null;
00108 }
00109 Directory exifDirectory = metadata.getDirectory(ExifDirectory.class);
00110
00111
00112
00113
00114
00115
00116
00117
00118 String ts = exifDirectory.getString(ExifDirectory.TAG_DATETIME_ORIGINAL);
00119 return ts;
00120 }
00121
00126 public static BufferedImage readImage(File source) {
00127 return JAIUtils.readJPEG(source).getAsBufferedImage();
00128 }
00129
00137 public static Dimension readSize(File imageFile) {
00138 if (isJPEGFile(imageFile)) {
00139 try {
00140 final Metadata metadata = JpegMetadataReader.readMetadata(imageFile);
00141 final Directory jpegDirectory = metadata.getDirectory(JpegDirectory.class);
00142 return new Dimension(jpegDirectory.getInt(JpegDirectory.TAG_JPEG_IMAGE_WIDTH),
00143 jpegDirectory.getInt(JpegDirectory.TAG_JPEG_IMAGE_HEIGHT));
00144 } catch (JpegProcessingException e) {
00145
00146 } catch (MetadataException e) {
00147
00148 }
00149 }
00150 return readSizeByLoading(imageFile);
00151 }
00152
00161 public static Dimension readSizeByLoading(File imageFile) {
00162 final PlanarImage planarImage = ImageCache.getInstance().getPlanarImage(imageFile);
00163 return new Dimension(planarImage.getWidth(), planarImage.getHeight());
00164 }
00165
00177 public static long readTimeFrom(File photo) {
00178 String ts = readCaptureDateFromEXIF(photo);
00179 if (ts == null) {
00180 return photo.lastModified();
00181 } else {
00182 return getTimeFromString(ts);
00183 }
00184 }
00185
00196 public static BufferedImage scaleImage(BufferedImage src, float sX, float sY) {
00197 System.err
00198 .println("Warning: ImageUtils::scaleImage is a low quality scale. Please use ImageUtils::scaleImageIteratively.");
00199
00200 final int width = (int) (src.getWidth() * sX + 0.5);
00201 final int height = (int) (src.getHeight() * sY + 0.5);
00202 final BufferedImage scaledImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
00203 final Graphics2D gScaledImg = scaledImg.createGraphics();
00204 gScaledImg.setRenderingHints(GraphicsUtils.getBestRenderingHints());
00205 gScaledImg.drawImage(src, 0, 0, width, height, null);
00206 return scaledImg;
00207 }
00208
00209 public static BufferedImage scaleImageToFit(BufferedImage src, int width, int height) {
00210 return scaleImageToSize(src, width, height, true);
00211 }
00212
00213 public static BufferedImage scaleImageToSize(BufferedImage src, int targetWidth,
00214 int targetHeight, boolean maintainAspectRatio) {
00215
00216 final int width = src.getWidth();
00217 final int height = src.getHeight();
00218
00219
00220 final float testScaleFactorX = (float) targetWidth / (float) width;
00221 final float testScaleFactorY = (float) targetHeight / (float) height;
00222
00223
00224
00225 float scaleFactorX = 0;
00226 float scaleFactorY = 0;
00227
00228
00229
00230 if (maintainAspectRatio) {
00231 float min = Math.min(testScaleFactorX, testScaleFactorY);
00232 scaleFactorX = min;
00233 scaleFactorY = min;
00234 } else {
00235 scaleFactorX = testScaleFactorX;
00236 scaleFactorY = testScaleFactorY;
00237 }
00238
00239
00240 if (scaleFactorX >= 1 || scaleFactorY >= 1) {
00241 return src;
00242 }
00243
00244 return scaleImage(src, scaleFactorX, scaleFactorY);
00245 }
00246
00251 public static void writeImageToJPEG(BufferedImage bufferedImage, File file) {
00252 writeImageToJPEG(bufferedImage, 100, file);
00253 }
00254
00267 public static void writeImageToJPEG(BufferedImage buffImage, int quality, File outputFile) {
00268 BufferedOutputStream out;
00269
00270
00271 if (quality < 0) {
00272 quality = 0;
00273 }
00274 if (quality > 100) {
00275 quality = 100;
00276 }
00277
00278 try {
00279 out = new BufferedOutputStream(new FileOutputStream(outputFile));
00280 final JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
00281 final JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(buffImage);
00282 quality = Math.max(0, Math.min(quality, 100));
00283 param.setQuality(quality / 100.0f, false);
00284 encoder.setJPEGEncodeParam(param);
00285 encoder.encode(buffImage);
00286 out.close();
00287 } catch (FileNotFoundException e) {
00288 e.printStackTrace();
00289 } catch (ImageFormatException e) {
00290 e.printStackTrace();
00291 } catch (IOException e) {
00292 e.printStackTrace();
00293 }
00294 }
00295
00300 public static void writeImageToPNG(RenderedImage rImage, File outputFile) {
00301 try {
00302 ImageIO.write(rImage, "png", outputFile);
00303 } catch (IOException e) {
00304 e.printStackTrace();
00305 }
00306 }
00307
00308 }