/* * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * This source code is provided to illustrate the usage of a given feature * or technique and has been deliberately simplified. Additional steps * required for a production-quality application, such as security checks, * input validation and proper error handling, might not be present in * this sample code. */ package stream.parallel; import java.awt.image.BufferedImage; import static java.awt.image.BufferedImage.TYPE_INT_RGB; import java.io.File; import java.util.stream.IntStream; import javax.imageio.ImageIO; import static stream.parallel.RandomPrimeNumber.usage; /** * This demo shows parallel geometrical transformations of images.The operations * of image include rotation, shift, scale, inversion. * * @author tyan */ public class ImageTransform { public static void main(String[] args) { try { if (args.length < 5) { usage(); return; } int argPos = 0; int oprand = 0; String command = ""; String inputFile = "", outputFile = ""; boolean yes = true; while (argPos < args.length) { switch (args[argPos++]) { case "-ls": case "-rs": yes = args[argPos - 1].equals("-ls"); oprand = Integer.parseInt(args[argPos++]); command = "shift"; break; case "-cl": case "-ccl": yes = args[argPos - 1].equals("-cl"); oprand = Integer.parseInt(args[argPos++]); command = "rotate"; break; case "-zo": oprand = Integer.parseInt(args[argPos++]); command = "zoom"; break; case "-iv": command = "invert"; break; case "-i": inputFile = args[argPos++]; break; case "-o": outputFile = args[argPos++]; break; default: usage(); return; } } if (inputFile.equals("") || outputFile.equals("")) { throw new Exception("Input/Output file is needed"); } File inFile = new File(inputFile); File outFile = new File(outputFile); BufferedImage in = ImageIO.read(inFile); int newWidth = in.getWidth(); int newHeight = in.getHeight(); if (command.equals("zoom")) { double magnitude = oprand / 100.0; newWidth = (int) (newWidth * magnitude); newHeight = (int) (newHeight * magnitude); } else if (command.equals("rorate")) { int max = Math.max(newWidth, newWidth); newWidth = max; newHeight = max; } BufferedImage out = new BufferedImage(newWidth, newHeight, TYPE_INT_RGB); if(!command.equals("invert") && oprand <= 0) { throw new Exception("Value must be a positive number"); } switch (command) { case "shift": shift(in, out, yes, oprand); break; case "rotate": rotate(in, out, yes, oprand); break; case "zoom": zoom(in, out, oprand / 100.0); break; case "invert": invert(in, out); break; } ImageIO.write(out, "jpg", outFile); } catch (Exception ex) { usage(); } } /** * Rotate an image as given angle. * @param in input image * @param out output image * @param clockwise true clockwise * false counter-clockwise * @param angle angle that image will rotate */ public static void rotate(BufferedImage in, BufferedImage out, boolean clockwise, int angle) { int width = (int) in.getWidth(); int height = (int) in.getHeight(); int centerX = width / 2; int centerY = height / 2; double rotateV = (clockwise ? 360 - angle : angle) / 180.0 * Math.PI; IntStream.range(0, width).parallel().forEach(x -> { IntStream.range(0, height).parallel().forEach(y -> { int newX = (int) (centerX + (x - centerX) * Math.cos(rotateV) + (y - centerY) * Math.sin(rotateV)); int newY = (int) (centerY + (x - centerX) * Math.sin(rotateV) + (y - centerY) * Math.cos(rotateV)); if (newX >= 0 && newX < width && newY >= 0 && newY < height) { out.setRGB(newX, newY, in.getRGB(x, y)); } }); }); } /** * Shift an image horizontally. * @param in input image * @param out output image * @param left true left shift * false right shift * @param length size that image shifts */ public static void shift(BufferedImage in, BufferedImage out, boolean left, int length) { int width = (int) out.getWidth(); int height = (int) out.getHeight(); int leftShift = left ? length % width : width - length % width; IntStream.range(0, width).parallel().forEach(x -> { IntStream.range(0, height).parallel().forEach(y -> { int newX = x >= leftShift ? x - leftShift : width + x - leftShift; out.setRGB(newX, y, in.getRGB(x, y)); }); }); } /** * Zoom in/out an image. * @param in input image * @param out output image * @param magnitude scale of original image. */ public static void zoom(BufferedImage in, BufferedImage out, double magnitude) { int width = (int) out.getWidth(); int height = (int) out.getHeight(); IntStream.range(0, width).parallel().forEach(x -> { IntStream.range(0, height).parallel().forEach(y -> { int oldX = (int) (x / magnitude); int oldY = (int) (y / magnitude); if (oldX < in.getWidth() && oldY < in.getHeight()) { out.setRGB(x, y, in.getRGB(oldX, oldY)); } }); }); } /** * Invert color of an image. * @param in input image * @param out output image */ public static void invert(BufferedImage in, BufferedImage out) { int width = (int) out.getWidth(); int height = (int) out.getHeight(); IntStream.range(0, width).parallel().forEach(x -> { IntStream.range(0, height).parallel().forEach(y -> { out.setRGB(x, y, in.getRGB(x, y) ^ 0xffffff); }); }); } /** * Usage of this program */ public static void usage() { System.out.println("Usage: java ImageTransform {-rs size|-ls size|" + "-cl angle|-ccl angle|-zo percentage|-zo precentage|-iv} " + "-i InputFile -o OutputFile"); } }