in progress...
basic rotation and flip?
| package lib.transformations; | |
| import java.awt.Graphics; | |
| import java.awt.color.ColorSpace; | |
| import java.awt.geom.AffineTransform; | |
| import java.awt.image.AffineTransformOp; | |
| import java.awt.image.BufferedImage; | |
| import java.awt.image.ColorConvertOp; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| /** | |
| * Produces transformed copies of a given input image. | |
| */ | |
| public class ImageTransformer { | |
| // private | |
| public | |
| enum DefaultAffinePropertiesMaps { | |
| FLIP() { | |
| public BufferedImage transform(BufferedImage inputimage) { | |
| return ImageTransformer.flip(inputimage); | |
| } | |
| }, | |
| FLOP() { | |
| public BufferedImage transform(BufferedImage inputimage) { | |
| return ImageTransformer.flop(inputimage); | |
| } | |
| }, | |
| SHRINK_HALF() { | |
| public BufferedImage transform(BufferedImage inputimage) { | |
| return ImageTransformer.shrinkToHalf(inputimage); | |
| } | |
| }, | |
| ROTATE_45() { | |
| public BufferedImage transform(BufferedImage inputimage) { | |
| return ImageTransformer.rotateByDegrees(inputimage, 45D); | |
| } | |
| }, | |
| ROTATE_90() { | |
| public BufferedImage transform(BufferedImage inputimage) { | |
| return ImageTransformer.rotateByDegrees(inputimage, 90D); | |
| } | |
| }, | |
| ROTATE_180() { | |
| public BufferedImage transform(BufferedImage inputimage) { | |
| return ImageTransformer.rotateByDegrees(inputimage, 180D); | |
| } | |
| }, | |
| ROTATE_270() { | |
| public BufferedImage transform(BufferedImage inputimage) { | |
| return ImageTransformer.rotateByDegrees(inputimage, 270D); | |
| } | |
| },; | |
| public BufferedImage affineTransform(BufferedImage inputimage) { | |
| switch (this) { | |
| case FLIP: | |
| return ImageTransformer.flip(inputimage); | |
| case FLOP: | |
| return ImageTransformer.flop(inputimage); | |
| case SHRINK_HALF: | |
| return ImageTransformer.shrinkToHalf(inputimage); | |
| case ROTATE_45: | |
| return ImageTransformer.rotateByDegrees(inputimage, 45D); | |
| case ROTATE_90: | |
| return ImageTransformer.rotateByDegrees(inputimage, 90D); | |
| case ROTATE_180: | |
| return ImageTransformer.rotateByDegrees(inputimage, 180D); | |
| case ROTATE_270: | |
| return ImageTransformer.rotateByDegrees(inputimage, 270D); | |
| } | |
| return inputimage; | |
| } | |
| } | |
| public static List<BufferedImage> defaultAffineTransform(BufferedImage inputimage) { | |
| ArrayList<BufferedImage> imagelist = new ArrayList(); | |
| for(DefaultAffinePropertiesMaps transformation : DefaultAffinePropertiesMaps.values()) | |
| { | |
| imagelist.add(transformation.affineTransform(inputimage)); | |
| } | |
| return imagelist; | |
| } | |
| public static BufferedImage affineTransform(BufferedImage inputimage, AffineTransform transform) { | |
| return new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR).filter(inputimage, null); | |
| } | |
| public static BufferedImage flip(BufferedImage inputimage) { | |
| AffineTransform transform = new AffineTransform(); | |
| transform.translate(inputimage.getWidth() / 2, inputimage.getHeight() / 2); | |
| transform.scale(1, -1); | |
| transform.translate(-inputimage.getWidth() / 2, -inputimage.getHeight() / 2); | |
| return affineTransform(inputimage, transform); | |
| } | |
| public static BufferedImage flop(BufferedImage inputimage) { | |
| AffineTransform transform = new AffineTransform(); | |
| transform.translate(inputimage.getWidth() / 2, inputimage.getHeight() / 2); | |
| transform.scale(-1, 1); | |
| transform.translate(-inputimage.getWidth() / 2, -inputimage.getHeight() / 2); | |
| return affineTransform(inputimage, transform); | |
| } | |
| public static BufferedImage shrinkToHalf(BufferedImage inputimage) { | |
| return scale(inputimage, .5, .5); | |
| } | |
| public static BufferedImage scale(BufferedImage inputimage, double scalex, double scaley) { | |
| return affineTransform(inputimage, AffineTransform.getScaleInstance(scalex, scaley)); | |
| } | |
| public static BufferedImage shear(BufferedImage inputimage, double shearx, double sheary) { | |
| return affineTransform(inputimage, AffineTransform.getShearInstance(shearx, sheary)); | |
| } | |
| public static BufferedImage rotateByDegrees(BufferedImage inputimage, double degrees) { | |
| return affineTransform(inputimage, AffineTransform.getRotateInstance(degrees, | |
| inputimage.getWidth() / 2, | |
| inputimage.getHeight() / 2)); | |
| } | |
| public static BufferedImage rotateByQuadrant(BufferedImage inputimage, int quadrantants) { | |
| return affineTransform(inputimage, AffineTransform.getQuadrantRotateInstance(quadrantants, | |
| inputimage.getWidth() / 2, | |
| inputimage.getHeight() / 2)); | |
| } | |
| public static BufferedImage grayScaleImage(BufferedImage inputimage) { | |
| BufferedImage grayImg = new BufferedImage(inputimage.getWidth(), | |
| inputimage.getHeight(), | |
| BufferedImage.TYPE_BYTE_GRAY); | |
| Graphics g = grayImg.getGraphics(); | |
| g.drawImage(inputimage, 0, 0, null); | |
| g.dispose(); | |
| return grayImg; | |
| } | |
| public static BufferedImage colorSpaceFilteredImage(BufferedImage inputimage, int colorspace) { | |
| return new ColorConvertOp(ColorSpace.getInstance(colorspace), null).filter(inputimage, null); | |
| } | |
| } |
| package app.task; | |
| import app.Err; | |
| import app.Opts; | |
| import java.awt.Color; | |
| import java.awt.Graphics; | |
| import java.awt.color.ColorSpace; | |
| import lib.tilers.Tiler; | |
| import lib.tilers.RectangularTiler; | |
| import lib.tilers.AdaptiveRectangularTiler; | |
| import lib.comparison.ImageComparator; | |
| import lib.comparison.Metric; | |
| import lib.transformations.ImageTransformer; | |
| import java.util.Properties; | |
| import java.io.File; | |
| import java.io.IOException; | |
| import java.awt.image.BufferedImage; | |
| import javax.imageio.ImageIO; | |
| import lib.transformations.ImageTransformer.DefaultAffinePropertiesMaps; | |
| import org.im4java.core.IM4JavaException; | |
| /** | |
| * Test cases | |
| */ | |
| public class TestTask extends Task { | |
| private BufferedImage inputimg; | |
| private File inputname; | |
| private String outputname; | |
| private static String sep = "-----------------------------------------"; | |
| public TestTask(Properties properties) { | |
| super(properties); | |
| inputname = new File(properties.getProperty(Opts.INPUT.toString())); | |
| outputname = properties.getProperty(Opts.OUTPUT.toString()); | |
| try { | |
| inputimg = ImageIO.read(inputname); | |
| } catch (IOException ex) { | |
| System.err.println(Err.IMAGE_NOT_FOUND.description()); | |
| System.exit(Err.IMAGE_NOT_FOUND.errcode()); | |
| } | |
| } | |
| @Override | |
| public void run() { | |
| //testRectTiler(); | |
| //testAdaptRectTiler(); | |
| testAdaptRectTilerImg(); | |
| //testComparison(); | |
| //testTransformation(); | |
| } | |
| /** | |
| * Test the rectangular tiler | |
| * | |
| * @see RectangularTiler | |
| */ | |
| private void testRectTiler() { | |
| System.out.printf("%s\n start of testRectTiler \n%s\n", sep, sep); | |
| Tiler tiler = new RectangularTiler(5, 5); | |
| BufferedImage[] blocks = tiler.tile(inputimg); | |
| System.out.println(blocks.length); | |
| for (int i = 0; i < blocks.length; i++) { | |
| try { | |
| ImageIO.write(blocks[i], "PNG", new File(String.format("tile_block_%d.png", i))); | |
| } catch (IOException ex) { | |
| System.err.printf("Couldn't write image: %d\n", i); | |
| } | |
| } | |
| System.out.printf("%s\n end of testRectTiler \n%s\n", sep, sep); | |
| } | |
| /** | |
| * Test the adaptive rectangular tiler | |
| * | |
| * @see AdaptiveRectangularTiler | |
| */ | |
| private void testAdaptRectTiler() { | |
| System.out.printf("%s\n start of testAdaptRectTiler \n%s\n", sep, sep); | |
| Tiler tiler = new AdaptiveRectangularTiler(5, 6); | |
| BufferedImage[] blocks = tiler.tile(inputimg); | |
| System.out.println(blocks.length); | |
| for (int i = 0; i < blocks.length; i++) { | |
| try { | |
| ImageIO.write(blocks[i], "PNG", new File(String.format("tile_block_%d.png", i))); | |
| } catch (IOException ex) { | |
| System.err.printf("Couldn't write image: %d\n", i); | |
| } | |
| } | |
| System.out.printf("%s\n end of testAdaptRectTiler \n%s\n", sep, sep); | |
| } | |
| /** | |
| * Draw the tiled image with its tiles. | |
| * | |
| * @see AdaptiveRectangularTiler | |
| */ | |
| private void testAdaptRectTilerImg() { | |
| System.out.printf("%s\n start of testAdaptRectTilerImg \n%s\n", sep, sep); | |
| Tiler tiler = new AdaptiveRectangularTiler(5, 6); | |
| BufferedImage[] blocks = tiler.tile(inputimg); | |
| BufferedImage rectimg = new BufferedImage(inputimg.getWidth(), inputimg.getHeight(), inputimg.getType()); | |
| Graphics g = rectimg.getGraphics(); | |
| g.drawImage(inputimg, 0, 0, null); | |
| g.setColor(Color.BLACK); | |
| int bw = blocks[0].getWidth(); | |
| int bh = blocks[0].getHeight(); | |
| int r = inputimg.getHeight() / bh; | |
| int c = inputimg.getWidth() / bw; | |
| for (int y = 0; y < r; y++) { | |
| for (int x = 0; x < c; x++) { | |
| g.drawRect(x * bw, y * bh, bw, bh); | |
| } | |
| } | |
| g.dispose(); | |
| try { | |
| ImageIO.write(rectimg, "PNG", new File(outputname + "_rect.png")); | |
| } catch (IOException ex) { | |
| System.err.printf("Couldn't write image: rects\n"); | |
| } | |
| System.out.printf("%s\n end of testAdaptRectTilerImg \n%s\n", sep, sep); | |
| } | |
| /** | |
| * Test the ImageComparator of images | |
| * | |
| * @see ImageComparator | |
| */ | |
| private void testComparison() { | |
| System.out.printf("%s\n start of testComparison \n%s\n", sep, sep); | |
| ImageComparator comparison = new ImageComparator(Metric.PSNR, 5.2D); | |
| try { | |
| if (comparison.compare(inputimg, inputimg)) { | |
| System.out.printf("Images match: %s\n", comparison.getDifference()); | |
| } else { | |
| System.out.printf("Images differ: %s\n", comparison.getDifference()); | |
| } | |
| } catch (IOException ex) { | |
| System.err.printf("Couldn't run op: compare ioe\n"); | |
| } catch (InterruptedException ex) { | |
| System.err.printf("Couldn't run op: compare ie\n"); | |
| } catch (IM4JavaException ex) { | |
| System.err.printf("Couldn't run op: compare im4jve\n"); | |
| } | |
| if (properties.getProperty(Opts.VERBOSE.toString()) != null) { | |
| System.out.println("== out stream =="); | |
| for (String line : comparison.getStdout()) { | |
| System.out.println(line); | |
| } | |
| System.err.println("\n== error stream =="); | |
| for (String line : comparison.getStderr()) { | |
| System.err.println(line); | |
| } | |
| } | |
| System.out.printf("%s\n end of testComparison \n%s\n", sep, sep); | |
| } | |
| /** | |
| * Test the transformation of images | |
| * | |
| * @see ImageTransformer | |
| */ | |
| private void testTransformation() { | |
| System.out.printf("%s\n start of testAffineTransformation \n%s\n", sep, sep); | |
| Long start = System.currentTimeMillis(); | |
| BufferedImage flip = ImageTransformer.flip(inputimg); | |
| BufferedImage flop = ImageTransformer.flop(inputimg); | |
| BufferedImage shri = ImageTransformer.shrinkToHalf(inputimg); | |
| BufferedImage qrot = ImageTransformer.rotateByQuadrant(inputimg, 3); | |
| BufferedImage drot = ImageTransformer.rotateByDegrees(inputimg, 60); | |
| BufferedImage gray = ImageTransformer.grayScaleImage(inputimg); | |
| BufferedImage filt = ImageTransformer.colorSpaceFilteredImage(inputimg, ColorSpace.CS_LINEAR_RGB); | |
| System.out.printf(":: Affine operations took %dms\n", System.currentTimeMillis() - start); | |
| try { | |
| System.out.println("FLIP"); | |
| ImageIO.write(flip, "PNG", new File(outputname + "_flip.png")); | |
| System.out.println("FLOP"); | |
| ImageIO.write(flop, "PNG", new File(outputname + "_flop.png")); | |
| System.out.println("SHRINK"); | |
| ImageIO.write(shri, "PNG", new File(outputname + "_shrink.png")); | |
| System.out.println("Q-ROTATE"); | |
| ImageIO.write(qrot, "PNG", new File(outputname + "_qrot.png")); | |
| System.out.println("D-ROTATE"); | |
| ImageIO.write(drot, "PNG", new File(outputname + "_drot.png")); | |
| System.out.println("GRAYSCALE"); | |
| ImageIO.write(gray, "PNG", new File(outputname + "_gray.png")); | |
| System.out.println("FILTER"); | |
| ImageIO.write(filt, "PNG", new File(outputname + "_cs.png")); | |
| } catch (IOException ex) { | |
| System.err.printf("Couldn't write image: affine\n"); | |
| } | |
| System.out.printf("%s\n end of testAffineTransformation\n%s\n", sep, sep); | |
| } | |
| // private void testTransformations() { | |
| // for(DefaultAffinePropertiesMaps transformation : DefaultAffinePropertiesMaps.values()) | |
| // { | |
| // transformation.affineTransform(inputimg); | |
| // } | |
| // } | |
| } |