Merge commit '7ce18848c8327967ce27b90abf2e280953530b5f'
[nikiroo-utils.git] / src / be / nikiroo / utils / ui / ImageUtilsAwt.java
index 4cf12c04cd0573629d90ed6e376be7c5ca6e7155..c273e0d45879628543dcab75f2c7c88f133224d9 100644 (file)
@@ -1,5 +1,7 @@
 package be.nikiroo.utils.ui;
 
+import java.awt.Dimension;
+import java.awt.Graphics2D;
 import java.awt.geom.AffineTransform;
 import java.awt.image.AffineTransformOp;
 import java.awt.image.BufferedImage;
@@ -9,6 +11,7 @@ import java.io.InputStream;
 
 import javax.imageio.ImageIO;
 
+import be.nikiroo.utils.IOUtils;
 import be.nikiroo.utils.Image;
 import be.nikiroo.utils.ImageUtils;
 import be.nikiroo.utils.StringUtils;
@@ -19,6 +22,22 @@ import be.nikiroo.utils.StringUtils;
  * @author niki
  */
 public class ImageUtilsAwt extends ImageUtils {
+       /**
+        * A rotation to perform on an image.
+        * 
+        * @author niki
+        */
+       public enum Rotation {
+               /** No rotation */
+               NONE,
+               /** Rotate the image to the right */
+               RIGHT,
+               /** Rotate the image to the left */
+               LEFT,
+               /** Rotate the image by 180° */
+               UTURN
+       }
+
        @Override
        protected boolean check() {
                // Will not work if ImageIO is not available
@@ -76,6 +95,26 @@ public class ImageUtilsAwt extends ImageUtils {
         *             in case of IO error
         */
        public static BufferedImage fromImage(Image img) throws IOException {
+               return fromImage(img, Rotation.NONE);
+       }
+
+       /**
+        * Convert the given {@link Image} into a {@link BufferedImage} object,
+        * respecting the EXIF transformations if any.
+        * 
+        * @param img
+        *            the {@link Image}
+        * @param rotation
+        *            the rotation to apply, if any (can be null, same as
+        *            {@link Rotation#NONE})
+        * 
+        * @return the {@link Image} object
+        * 
+        * @throws IOException
+        *             in case of IO error
+        */
+       public static BufferedImage fromImage(Image img, Rotation rotation)
+                       throws IOException {
                InputStream in = img.newInputStream();
                BufferedImage image;
                try {
@@ -102,8 +141,14 @@ public class ImageUtilsAwt extends ImageUtils {
                                String extra = "";
                                if (img.getSize() <= 2048) {
                                        try {
-                                               extra = ", content: "
-                                                               + new String(img.getData(), "UTF-8");
+                                               byte[] data = null;
+                                               InputStream inData = img.newInputStream();
+                                               try {
+                                                       data = IOUtils.toByteArray(inData);
+                                               } finally {
+                                                       inData.close();
+                                               }
+                                               extra = ", content: " + new String(data, "UTF-8");
                                        } catch (Exception e) {
                                                extra = ", content unavailable";
                                        }
@@ -159,6 +204,45 @@ public class ImageUtilsAwt extends ImageUtils {
                                break;
                        }
 
+                       if (rotation == null)
+                               rotation = Rotation.NONE;
+
+                       switch (rotation) {
+                       case RIGHT:
+                               if (affineTransform == null) {
+                                       affineTransform = new AffineTransform();
+                               }
+                               affineTransform.translate(height, 0);
+                               affineTransform.rotate(Math.PI / 2);
+
+                               int tmp = width;
+                               width = height;
+                               height = tmp;
+
+                               break;
+                       case LEFT:
+                               if (affineTransform == null) {
+                                       affineTransform = new AffineTransform();
+                               }
+                               affineTransform.translate(0, width);
+                               affineTransform.rotate(3 * Math.PI / 2);
+
+                               int temp = width;
+                               width = height;
+                               height = temp;
+
+                               break;
+                       case UTURN:
+                               if (affineTransform == null) {
+                                       affineTransform = new AffineTransform();
+                               }
+                               affineTransform.translate(width, height);
+                               affineTransform.rotate(Math.PI);
+                               break;
+                       default:
+                               break;
+                       }
+
                        if (affineTransform != null) {
                                AffineTransformOp affineTransformOp = new AffineTransformOp(
                                                affineTransform, AffineTransformOp.TYPE_BILINEAR);
@@ -177,4 +261,74 @@ public class ImageUtilsAwt extends ImageUtils {
 
                return image;
        }
+
+       /**
+        * Scale a dimension.
+        * 
+        * @param imageSize
+        *            the actual image size
+        * @param areaSize
+        *            the base size of the target to get snap sizes for
+        * @param zoom
+        *            the zoom factor (ignored on snap mode)
+        * @param snapMode
+        *            NULL for no snap mode, TRUE to snap to width and FALSE for
+        *            snap to height)
+        * 
+        * @return the scaled (minimum is 1x1)
+        */
+       public static Dimension scaleSize(Dimension imageSize, Dimension areaSize,
+                       double zoom, Boolean snapMode) {
+               Integer[] sz = scaleSize(imageSize.width, imageSize.height,
+                               areaSize.width, areaSize.height, zoom, snapMode);
+               return new Dimension(sz[0], sz[1]);
+       }
+
+       /**
+        * Resize the given image.
+        * 
+        * @param image
+        *            the image to resize
+        * @param areaSize
+        *            the base size of the target dimension for snap sizes
+        * @param zoom
+        *            the zoom factor (ignored on snap mode)
+        * @param snapMode
+        *            NULL for no snap mode, TRUE to snap to width and FALSE for
+        *            snap to height)
+        * 
+        * @return a new, resized image
+        */
+       public static BufferedImage scaleImage(BufferedImage image,
+                       Dimension areaSize, double zoom, Boolean snapMode) {
+               Dimension scaledSize = scaleSize(
+                               new Dimension(image.getWidth(), image.getHeight()), areaSize,
+                               zoom, snapMode);
+
+               return scaleImage(image, scaledSize);
+       }
+
+       /**
+        * Resize the given image.
+        * 
+        * @param image
+        *            the image to resize
+        * @param targetSize
+        *            the target size
+        * 
+        * @return a new, resized image
+        */
+       public static BufferedImage scaleImage(BufferedImage image,
+                       Dimension targetSize) {
+               BufferedImage resizedImage = new BufferedImage(targetSize.width,
+                               targetSize.height, BufferedImage.TYPE_4BYTE_ABGR);
+               Graphics2D g = resizedImage.createGraphics();
+               try {
+                       g.drawImage(image, 0, 0, targetSize.width, targetSize.height, null);
+               } finally {
+                       g.dispose();
+               }
+
+               return resizedImage;
+       }
 }