- http://www.javalobby.org/articles/ultimate-image/
- http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
import java.util.*;
import java.io.*;
import java.awt.image.*;
import java.awt.*;
import javax.imageio.ImageIO;
import java.io.FilenameFilter;
public class Autoboxing
{
public static String DESTINATION_PATH = "C:\\destination";
public static String SOURCE_PATH = "C:\\source";
public static boolean verbose = false;
public static int MAX_RETRIES = 20;
/**
* Saves a BufferedImage to the given file, pathname must not have any
* periods "." in it except for the one before the format, i.e. C:/images/fooimage.png
* @param img
* @param ref a pathname
*/
public static void saveImage(BufferedImage img, String ref)
{
try {
String format = (ref.endsWith(".png")) ? "png" : "jpg";
ImageIO.write(img, format, new File(ref));
} catch (IOException e) {
e.printStackTrace();
}
}
public static BufferedImage loadImage(File ref)
{
BufferedImage bimg = null;
try {
bimg = ImageIO.read(ref);
} catch (Exception e) {
e.printStackTrace();
}
return bimg;
}
/**
* Convenience method that returns a scaled instance of the
* provided {@code BufferedImage}.
*
* @param img the original image to be scaled
* @param targetWidth the desired width of the scaled instance,
* in pixels
* @param targetHeight the desired height of the scaled instance,
* in pixels
* @param hint one of the rendering hints that corresponds to
* {@code RenderingHints.KEY_INTERPOLATION} (e.g.
* {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR},
* {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR},
* {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC})
* @param higherQuality if true, this method will use a multi-step
* scaling technique that provides higher quality than the usual
* one-step technique (only useful in downscaling cases, where
* {@code targetWidth} or {@code targetHeight} is
* smaller than the original dimensions, and generally only when
* the {@code BILINEAR} hint is specified)
* @return a scaled version of the original {@code BufferedImage}
*/
public static BufferedImage getScaledInstance(BufferedImage img,
int targetWidth,
int targetHeight,
Object hint,
boolean higherQuality)
{
int type = (img.getTransparency() == Transparency.OPAQUE) ?
BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage ret = (BufferedImage)img;
int w, h;
if (higherQuality) {
// Use multi-step technique: start with original size, then
// scale down in multiple passes with drawImage()
// until the target size is reached
w = img.getWidth();
h = img.getHeight();
} else {
// Use one-step technique: scale directly from original
// size to target size with a single drawImage() call
w = targetWidth;
h = targetHeight;
}
int count = 0;
do {
count ++;
if (count > MAX_RETRIES)
{
throw new RuntimeException("Max retries reached.");
}
if (higherQuality && w > targetWidth) {
w /= 2;
if (w < targetWidth) {
w = targetWidth;
}
}
if (higherQuality && h > targetHeight) {
h /= 2;
if (h < targetHeight) {
h = targetHeight;
}
}
BufferedImage tmp = new BufferedImage(w, h, type);
Graphics2D g2 = tmp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(ret, 0, 0, w, h, null);
g2.dispose();
ret = tmp;
} while (w != targetWidth || h != targetHeight);
return ret;
}
/**
* Recursively resizes images.
* @param directory the source directory containing .jpg files
* @param destination the destination directory where the resized .jpg files are to be put
* @param filter the filter to use, for example *.jpg
* @param recurse wether or not to traverse the directory tree
* @param recreate wether or not to recreate the entire directory tree
* in the destination or simply dump .jpg files.
* @param overwrite true, it overwrites existing files, false, if destination file already exists, skips it.
*/
public static void changeFiles(
File directory,
File destination,
FilenameFilter filter,
boolean recurse,
boolean recreate,
boolean overwrite)
throws IOException
{
if (verbose) System.out.println("Checking directory : " + directory.getCanonicalPath() + " with " + destination.getCanonicalPath() );
// List of files / directories
Vector<File> files = new Vector<File>();
// Get files / directories in the directory
File[] entries = directory.listFiles();
// Go over entries
for (File entry : entries)
{
if (verbose) System.out.println(" File: " + entry.getName());
// If there is no filter or the filter accepts the
// file / directory, resize the image found
if (filter == null || filter.accept(directory, entry.getName()))
{
File newFile = new File(destination.getCanonicalPath() + File.separator + entry.getName());
if (newFile.exists() && !overwrite)
{
// skipping this one, already done apparently.
if (verbose) System.out.println(" File " + newFile .getCanonicalPath() + " exists, skipped.");
continue;
}
try
{
BufferedImage theImage = loadImage(entry);
theImage = getScaledInstance(theImage, 50, 50, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);
if (!recreate)
{
saveImage(theImage, destination.getCanonicalPath() + "\\" + entry.getName());
}
else
{
if (!newFile.exists())
{
// create the equivalent
newFile.createNewFile();
}
saveImage(theImage, newFile.getCanonicalPath());
}
}
catch (Exception e)
{
System.out.println("Error resizing image " + entry.getCanonicalPath());
e.printStackTrace();
}
}
// If the file is a directory and the recurse flag
// is set, recurse into the directory
if (recurse && entry.isDirectory())
{
if (recreate)
{
File newFile = new File(destination.getCanonicalPath() + File.separator + entry.getName());
if (!newFile.exists())
{
// create the equivalent
newFile.mkdir();
}
changeFiles(entry, new File(destination.getCanonicalPath() + File.separator + entry.getName()), filter, recurse, recreate, overwrite);
}
else
{
changeFiles(entry, new File(destination.getCanonicalPath()), filter, recurse, recreate, overwrite);
}
}
}
}
public static class MyFilenameFilter implements FilenameFilter
{
public boolean accept(File dir,
String name)
{
return name.endsWith(".jpg");
}
}
public static void main(String args[])
throws IOException
{
boolean overwrite = false;
boolean recursive = false;
boolean recreate = false;
boolean nextIsDestination = false;
boolean nextIsSource = false;
String destination = DESTINATION_PATH;
String source = SOURCE_PATH;
for (String argument : args)
{
if (nextIsDestination)
{
destination = argument;
nextIsDestination = false;
}
if (nextIsSource)
{
source = argument;
nextIsSource = false;
}
if ("-r".equals(argument))
{
recursive = true;
}
if ("-tree".equals(argument))
{
recreate = true;
}
if ("-s".equals(argument))
{
nextIsSource = true;
}
if ("-d".equals(argument))
{
nextIsDestination = true;
}
if ("-o".equals(argument))
{
overwrite = true;
}
if ("-v".equals(argument))
{
verbose = true;
}
}
File src_file = new File(source);
File dest_file = new File(destination);
System.out.println("absolute path: " + src_file.getAbsolutePath());
System.out.println("canonical path: " + src_file.getCanonicalPath());
System.out.println("path: " + src_file.getPath());
System.out.println("name: " + src_file.getName());
changeFiles(src_file, dest_file, new MyFilenameFilter(), recursive, recreate, overwrite);
}
}
import java.io.*;
import java.awt.image.*;
import java.awt.*;
import javax.imageio.ImageIO;
import java.io.FilenameFilter;
public class Autoboxing
{
public static String DESTINATION_PATH = "C:\\destination";
public static String SOURCE_PATH = "C:\\source";
public static boolean verbose = false;
public static int MAX_RETRIES = 20;
/**
* Saves a BufferedImage to the given file, pathname must not have any
* periods "." in it except for the one before the format, i.e. C:/images/fooimage.png
* @param img
* @param ref a pathname
*/
public static void saveImage(BufferedImage img, String ref)
{
try {
String format = (ref.endsWith(".png")) ? "png" : "jpg";
ImageIO.write(img, format, new File(ref));
} catch (IOException e) {
e.printStackTrace();
}
}
public static BufferedImage loadImage(File ref)
{
BufferedImage bimg = null;
try {
bimg = ImageIO.read(ref);
} catch (Exception e) {
e.printStackTrace();
}
return bimg;
}
/**
* Convenience method that returns a scaled instance of the
* provided {@code BufferedImage}.
*
* @param img the original image to be scaled
* @param targetWidth the desired width of the scaled instance,
* in pixels
* @param targetHeight the desired height of the scaled instance,
* in pixels
* @param hint one of the rendering hints that corresponds to
* {@code RenderingHints.KEY_INTERPOLATION} (e.g.
* {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR},
* {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR},
* {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC})
* @param higherQuality if true, this method will use a multi-step
* scaling technique that provides higher quality than the usual
* one-step technique (only useful in downscaling cases, where
* {@code targetWidth} or {@code targetHeight} is
* smaller than the original dimensions, and generally only when
* the {@code BILINEAR} hint is specified)
* @return a scaled version of the original {@code BufferedImage}
*/
public static BufferedImage getScaledInstance(BufferedImage img,
int targetWidth,
int targetHeight,
Object hint,
boolean higherQuality)
{
int type = (img.getTransparency() == Transparency.OPAQUE) ?
BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage ret = (BufferedImage)img;
int w, h;
if (higherQuality) {
// Use multi-step technique: start with original size, then
// scale down in multiple passes with drawImage()
// until the target size is reached
w = img.getWidth();
h = img.getHeight();
} else {
// Use one-step technique: scale directly from original
// size to target size with a single drawImage() call
w = targetWidth;
h = targetHeight;
}
int count = 0;
do {
count ++;
if (count > MAX_RETRIES)
{
throw new RuntimeException("Max retries reached.");
}
if (higherQuality && w > targetWidth) {
w /= 2;
if (w < targetWidth) {
w = targetWidth;
}
}
if (higherQuality && h > targetHeight) {
h /= 2;
if (h < targetHeight) {
h = targetHeight;
}
}
BufferedImage tmp = new BufferedImage(w, h, type);
Graphics2D g2 = tmp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(ret, 0, 0, w, h, null);
g2.dispose();
ret = tmp;
} while (w != targetWidth || h != targetHeight);
return ret;
}
/**
* Recursively resizes images.
* @param directory the source directory containing .jpg files
* @param destination the destination directory where the resized .jpg files are to be put
* @param filter the filter to use, for example *.jpg
* @param recurse wether or not to traverse the directory tree
* @param recreate wether or not to recreate the entire directory tree
* in the destination or simply dump .jpg files.
* @param overwrite true, it overwrites existing files, false, if destination file already exists, skips it.
*/
public static void changeFiles(
File directory,
File destination,
FilenameFilter filter,
boolean recurse,
boolean recreate,
boolean overwrite)
throws IOException
{
if (verbose) System.out.println("Checking directory : " + directory.getCanonicalPath() + " with " + destination.getCanonicalPath() );
// List of files / directories
Vector<File> files = new Vector<File>();
// Get files / directories in the directory
File[] entries = directory.listFiles();
// Go over entries
for (File entry : entries)
{
if (verbose) System.out.println(" File: " + entry.getName());
// If there is no filter or the filter accepts the
// file / directory, resize the image found
if (filter == null || filter.accept(directory, entry.getName()))
{
File newFile = new File(destination.getCanonicalPath() + File.separator + entry.getName());
if (newFile.exists() && !overwrite)
{
// skipping this one, already done apparently.
if (verbose) System.out.println(" File " + newFile .getCanonicalPath() + " exists, skipped.");
continue;
}
try
{
BufferedImage theImage = loadImage(entry);
theImage = getScaledInstance(theImage, 50, 50, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);
if (!recreate)
{
saveImage(theImage, destination.getCanonicalPath() + "\\" + entry.getName());
}
else
{
if (!newFile.exists())
{
// create the equivalent
newFile.createNewFile();
}
saveImage(theImage, newFile.getCanonicalPath());
}
}
catch (Exception e)
{
System.out.println("Error resizing image " + entry.getCanonicalPath());
e.printStackTrace();
}
}
// If the file is a directory and the recurse flag
// is set, recurse into the directory
if (recurse && entry.isDirectory())
{
if (recreate)
{
File newFile = new File(destination.getCanonicalPath() + File.separator + entry.getName());
if (!newFile.exists())
{
// create the equivalent
newFile.mkdir();
}
changeFiles(entry, new File(destination.getCanonicalPath() + File.separator + entry.getName()), filter, recurse, recreate, overwrite);
}
else
{
changeFiles(entry, new File(destination.getCanonicalPath()), filter, recurse, recreate, overwrite);
}
}
}
}
public static class MyFilenameFilter implements FilenameFilter
{
public boolean accept(File dir,
String name)
{
return name.endsWith(".jpg");
}
}
public static void main(String args[])
throws IOException
{
boolean overwrite = false;
boolean recursive = false;
boolean recreate = false;
boolean nextIsDestination = false;
boolean nextIsSource = false;
String destination = DESTINATION_PATH;
String source = SOURCE_PATH;
for (String argument : args)
{
if (nextIsDestination)
{
destination = argument;
nextIsDestination = false;
}
if (nextIsSource)
{
source = argument;
nextIsSource = false;
}
if ("-r".equals(argument))
{
recursive = true;
}
if ("-tree".equals(argument))
{
recreate = true;
}
if ("-s".equals(argument))
{
nextIsSource = true;
}
if ("-d".equals(argument))
{
nextIsDestination = true;
}
if ("-o".equals(argument))
{
overwrite = true;
}
if ("-v".equals(argument))
{
verbose = true;
}
}
File src_file = new File(source);
File dest_file = new File(destination);
System.out.println("absolute path: " + src_file.getAbsolutePath());
System.out.println("canonical path: " + src_file.getCanonicalPath());
System.out.println("path: " + src_file.getPath());
System.out.println("name: " + src_file.getName());
changeFiles(src_file, dest_file, new MyFilenameFilter(), recursive, recreate, overwrite);
}
}
No comments:
Post a Comment