Image: perfs improvement
authorNiki Roo <niki@nikiroo.be>
Tue, 23 Apr 2019 11:43:52 +0000 (13:43 +0200)
committerNiki Roo <niki@nikiroo.be>
Tue, 23 Apr 2019 11:43:52 +0000 (13:43 +0200)
src/be/nikiroo/utils/Image.java
src/be/nikiroo/utils/android/ImageUtilsAndroid.java
src/be/nikiroo/utils/ui/ImageUtilsAwt.java

index 6edc1051ab7b910c0b47733407c99d804a08a8fe..cfcaa74e2c1b8e2f1cd280f687afbfd7e8ad51bf 100644 (file)
@@ -76,14 +76,35 @@ public class Image implements Closeable {
                IOUtils.write(in, data);
        }
 
+       /**
+        * Generate an {@link InputStream} for this {@link Image}.
+        * <p>
+        * This {@link InputStream} will (always) be a new one, and <b>you</b> are
+        * responsible for it.
+        * <p>
+        * Note: take care that the {@link InputStream} <b>must not</b> live past
+        * the {@link Image} life time!
+        * 
+        * @return the stream
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public InputStream newInputStream() throws IOException {
+               return new FileInputStream(data);
+       }
+
        /**
         * <b>Read</b> the actual image data, as a byte array.
+        * <p>
+        * Note: if possible, prefer the {@link Image#newInputStream()} method, as
+        * it can be more efficient.
         * 
         * @return the image data
         */
        public byte[] getData() {
                try {
-                       FileInputStream in = new FileInputStream(data);
+                       InputStream in = newInputStream();
                        try {
                                return IOUtils.toByteArray(in);
                        } finally {
@@ -97,11 +118,18 @@ public class Image implements Closeable {
        /**
         * Convert the given {@link Image} object into a Base64 representation of
         * the same {@link Image} object.
+        * <p>
+        * Note: if possible, prefer the {@link Image#newInputStream()} method, as
+        * it can be more efficient.
         * 
         * @return the Base64 representation
         */
        public String toBase64() {
-               return Base64.encodeBytes(getData());
+               try {
+                       return StringUtils.base64(getData(), false);
+               } catch (IOException e) {
+                       throw new RuntimeException(e);
+               }
        }
 
        /**
index eb65ff135dd26bc4e7a659a04d48a4b8ea1a5985..f198862437754f0883d6ecc77dbacf03c55d4eb7 100644 (file)
@@ -62,8 +62,9 @@ public class ImageUtilsAndroid extends ImageUtils {
         *             in case of IO error
         */
        static public Bitmap fromImage(Image img) throws IOException {
-               int size = img.getData().length;
-               Bitmap image = BitmapFactory.decodeByteArray(img.getData(), 0, size);
+               byte[] array = img.getData();
+               int size = array.length;
+               Bitmap image = BitmapFactory.decodeByteArray(array, 0, size);
                if (image == null) {
                        String ssize = StringUtils.formatNumber(size);
                        throw new IOException(
index 148f8f57451141805c508de08e8254b0f3e2d407..6e9160f5c02f38964e343035d4cda7a7c7f34cff 100644 (file)
@@ -3,7 +3,6 @@ package be.nikiroo.utils.ui;
 import java.awt.geom.AffineTransform;
 import java.awt.image.AffineTransformOp;
 import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -69,88 +68,92 @@ public class ImageUtilsAwt extends ImageUtils {
         *             in case of IO error
         */
        public static BufferedImage fromImage(Image img) throws IOException {
-               InputStream in = new ByteArrayInputStream(img.getData());
-
-               int orientation;
-               try {
-                       orientation = getExifTransorm(in);
-               } catch (Exception e) {
-                       // no EXIF transform, ok
-                       orientation = -1;
-               }
-
-               in.reset();
+               InputStream in = img.newInputStream();
                BufferedImage image;
                try {
-                       image = ImageIO.read(in);
-               } catch (IllegalArgumentException e) {
-                       throw e;
-               } catch (Exception e) {
-                       throw new IOException("Undocumented exception occured, "
-                                       + "converting to IOException", e);
-               }
+                       int orientation;
+                       try {
+                               orientation = getExifTransorm(in);
+                       } catch (Exception e) {
+                               // no EXIF transform, ok
+                               orientation = -1;
+                       }
 
-               if (image == null) {
-                       throw new IOException("Failed to convert input to image");
-               }
+                       in.reset();
 
-               // Note: this code has been found on Internet;
-               // thank you anonymous coder.
-               int width = image.getWidth();
-               int height = image.getHeight();
-               AffineTransform affineTransform = new AffineTransform();
-
-               switch (orientation) {
-               case 1:
-                       affineTransform = null;
-                       break;
-               case 2: // Flip X
-                       affineTransform.scale(-1.0, 1.0);
-                       affineTransform.translate(-width, 0);
-                       break;
-               case 3: // PI rotation
-                       affineTransform.translate(width, height);
-                       affineTransform.rotate(Math.PI);
-                       break;
-               case 4: // Flip Y
-                       affineTransform.scale(1.0, -1.0);
-                       affineTransform.translate(0, -height);
-                       break;
-               case 5: // - PI/2 and Flip X
-                       affineTransform.rotate(-Math.PI / 2);
-                       affineTransform.scale(-1.0, 1.0);
-                       break;
-               case 6: // -PI/2 and -width
-                       affineTransform.translate(height, 0);
-                       affineTransform.rotate(Math.PI / 2);
-                       break;
-               case 7: // PI/2 and Flip
-                       affineTransform.scale(-1.0, 1.0);
-                       affineTransform.translate(-height, 0);
-                       affineTransform.translate(0, width);
-                       affineTransform.rotate(3 * Math.PI / 2);
-                       break;
-               case 8: // PI / 2
-                       affineTransform.translate(0, width);
-                       affineTransform.rotate(3 * Math.PI / 2);
-                       break;
-               default:
-                       affineTransform = null;
-                       break;
-               }
+                       try {
+                               image = ImageIO.read(in);
+                       } catch (IllegalArgumentException e) {
+                               throw e;
+                       } catch (Exception e) {
+                               throw new IOException("Undocumented exception occured, "
+                                               + "converting to IOException", e);
+                       }
+
+                       if (image == null) {
+                               throw new IOException("Failed to convert input to image");
+                       }
+
+                       // Note: this code has been found on Internet;
+                       // thank you anonymous coder.
+                       int width = image.getWidth();
+                       int height = image.getHeight();
+                       AffineTransform affineTransform = new AffineTransform();
+
+                       switch (orientation) {
+                       case 1:
+                               affineTransform = null;
+                               break;
+                       case 2: // Flip X
+                               affineTransform.scale(-1.0, 1.0);
+                               affineTransform.translate(-width, 0);
+                               break;
+                       case 3: // PI rotation
+                               affineTransform.translate(width, height);
+                               affineTransform.rotate(Math.PI);
+                               break;
+                       case 4: // Flip Y
+                               affineTransform.scale(1.0, -1.0);
+                               affineTransform.translate(0, -height);
+                               break;
+                       case 5: // - PI/2 and Flip X
+                               affineTransform.rotate(-Math.PI / 2);
+                               affineTransform.scale(-1.0, 1.0);
+                               break;
+                       case 6: // -PI/2 and -width
+                               affineTransform.translate(height, 0);
+                               affineTransform.rotate(Math.PI / 2);
+                               break;
+                       case 7: // PI/2 and Flip
+                               affineTransform.scale(-1.0, 1.0);
+                               affineTransform.translate(-height, 0);
+                               affineTransform.translate(0, width);
+                               affineTransform.rotate(3 * Math.PI / 2);
+                               break;
+                       case 8: // PI / 2
+                               affineTransform.translate(0, width);
+                               affineTransform.rotate(3 * Math.PI / 2);
+                               break;
+                       default:
+                               affineTransform = null;
+                               break;
+                       }
 
-               if (affineTransform != null) {
-                       AffineTransformOp affineTransformOp = new AffineTransformOp(
-                                       affineTransform, AffineTransformOp.TYPE_BILINEAR);
+                       if (affineTransform != null) {
+                               AffineTransformOp affineTransformOp = new AffineTransformOp(
+                                               affineTransform, AffineTransformOp.TYPE_BILINEAR);
 
-                       BufferedImage transformedImage = new BufferedImage(width, height,
-                                       image.getType());
-                       transformedImage = affineTransformOp
-                                       .filter(image, transformedImage);
+                               BufferedImage transformedImage = new BufferedImage(width,
+                                               height, image.getType());
+                               transformedImage = affineTransformOp.filter(image,
+                                               transformedImage);
 
-                       image = transformedImage;
+                               image = transformedImage;
+                       }
+                       //
+               } finally {
+                       in.close();
                }
-               //
 
                return image;
        }