Use jpeg as thumbnail extension except for gif-s.
[meviz.git] / src / main / java / eu / svjatoslav / meviz / htmlindexer / metadata / fileTypes / Picture.java
index 7ed4d09..6f74473 100755 (executable)
@@ -1,32 +1,40 @@
 /*
  * Meviz - Various tools collection to work with multimedia.
- * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * Copyright (C) 2012 -- 2019, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public License
- * as published by the Free Software Foundation.
- */
+ * modify it under the terms of version 3 of the GNU Lesser General Public License
+ * or later as published by the Free Software Foundation.
+*/
 
 package eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes;
 
 import eu.svjatoslav.commons.file.FilePathParser;
+import eu.svjatoslav.commons.file.IOHelper;
 import eu.svjatoslav.meviz.htmlindexer.Constants;
+import eu.svjatoslav.meviz.htmlindexer.GifSequenceWriter;
+import eu.svjatoslav.meviz.htmlindexer.ImageFormatError;
 import eu.svjatoslav.meviz.htmlindexer.Utils;
 import eu.svjatoslav.meviz.htmlindexer.metadata.Dimension;
 
 import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.FileImageOutputStream;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.ImageOutputStream;
 import javax.swing.*;
 import java.awt.*;
 import java.awt.image.BufferedImage;
 import java.awt.image.FilteredImageSource;
 import java.awt.image.ImageFilter;
 import java.awt.image.ImageProducer;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
+import java.io.*;
 import java.util.ArrayList;
 import java.util.List;
 
+import static eu.svjatoslav.meviz.htmlindexer.Utils.getBufferedImage;
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+
 public class Picture extends AbstractFile {
 
     private static final long serialVersionUID = -4156533490858298387L;
@@ -53,7 +61,7 @@ public class Picture extends AbstractFile {
      * exceeding provided thumbnail width and height, and preserving aspect
      * ratio of original image.
      */
-    public static java.awt.Dimension getTargetThumbnailDimension(
+    private static java.awt.Dimension getTargetThumbnailDimension(
             final java.awt.Dimension originalImageDimension,
             final java.awt.Dimension desiredTargetDimension) {
 
@@ -87,7 +95,7 @@ public class Picture extends AbstractFile {
      * Propose list of thumbnail dimensions.
      */
     public static List<Dimension> getThumbnailDimensions(Dimension current) {
-        final ArrayList<Dimension> result = new ArrayList<Dimension>();
+        final ArrayList<Dimension> result = new ArrayList<>();
         result.add(current);
 
         while (current.getArea() > 1000000) {
@@ -103,9 +111,23 @@ public class Picture extends AbstractFile {
                                      final File outputFile,
                                      final java.awt.Dimension preferredTargetDimensions) {
 
+        String fileExtension = FilePathParser.getFileExtension(inputFile.getName());
+
         try {
+            if ("gif".equalsIgnoreCase(fileExtension))
+                makeGifThumbnail(inputFile, outputFile, preferredTargetDimensions);
+            else
+                makeJpegThumbnail(inputFile, outputFile, preferredTargetDimensions);
+        } catch (final Exception exception) {
+            System.out.println(exception.toString());
+            exception.printStackTrace();
+        }
+    }
 
-            final BufferedImage inputImage = Utils.getBufferedImage(inputFile);
+    private static void makeJpegThumbnail(File inputFile, File outputFile, java.awt.Dimension preferredTargetDimensions)
+            throws IOException, ImageFormatError {
+
+            final BufferedImage inputImage = getBufferedImage(inputFile);
 
             final java.awt.Dimension sourceImageDimension = new java.awt.Dimension(
                     inputImage.getWidth(), inputImage.getHeight());
@@ -120,7 +142,7 @@ public class Picture extends AbstractFile {
 
             final BufferedImage bufferedImage = new BufferedImage(
                     scaledImage.getWidth(null), scaledImage.getHeight(null),
-                    BufferedImage.TYPE_INT_RGB);
+                    TYPE_INT_RGB);
 
             final Graphics2D g = bufferedImage.createGraphics();
             g.drawImage(scaledImage, 0, 0, null);
@@ -128,18 +150,59 @@ public class Picture extends AbstractFile {
 
             ImageIO.write(bufferedImage, "jpg", out);
             out.close();
+    }
 
-        } catch (final Exception exception) {
-            System.out.println(exception.toString());
-            exception.printStackTrace();
+    private static void makeGifThumbnail(
+            File inputFile, File outputFile, java.awt.Dimension preferredTargetDimensions) throws IOException {
+        ImageIcon imageIcon = new ImageIcon(IOHelper.getFileContents(inputFile));
+
+        final java.awt.Dimension sourceImageDimension = new java.awt.Dimension(
+                imageIcon.getIconWidth(), imageIcon.getIconHeight());
+
+        System.out.println("Source image dimensions:" + sourceImageDimension);
+
+        final java.awt.Dimension targetDimensions = getTargetThumbnailDimension(
+                sourceImageDimension, preferredTargetDimensions);
+
+        System.out.println("Desired target image dimensions:" + targetDimensions);
+
+        FileInputStream fiStream = new FileInputStream( inputFile );
+
+        ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next();
+        ImageInputStream stream = ImageIO.createImageInputStream(inputFile);
+        reader.setInput(stream);
+
+        Utils.ImageFrame[] frames = Utils.readGIF(reader);
+        for (Utils.ImageFrame frame : frames) {
+            Image scaleImage = scaleImage(frame.image, targetDimensions.width, targetDimensions.height);
+            BufferedImage bimage = new BufferedImage(
+                    targetDimensions.width, targetDimensions.height, BufferedImage.TYPE_INT_ARGB);
+            Graphics2D bGr = bimage.createGraphics();
+            bGr.drawImage(scaleImage, 0, 0, null);
+            bGr.dispose();
+            frame.image = bimage;
         }
+
+        ImageOutputStream output = new FileImageOutputStream(outputFile );
+
+        GifSequenceWriter writer =
+                new GifSequenceWriter( output, frames[0].image.getType(), frames[0].getDelay(), true );
+
+        writer.writeToSequence( frames[0].image );
+        for ( int i = 1; i < frames.length; i++ ) {
+            BufferedImage nextImage = frames[i].image;
+            writer.writeToSequence( nextImage );
+        }
+
+        writer.close();
+        output.close();
     }
 
     /**
      * @return new image scaled to desired dimensions
      */
-    public static Image scaleImage(final Image srcImage, final int width,
-                                   final int height) {
+    private static Image scaleImage(final Image srcImage, final int width,
+                                    final int height) {
 
         final ImageFilter filter = new java.awt.image.AreaAveragingScaleFilter(
                 width, height);
@@ -156,12 +219,11 @@ public class Picture extends AbstractFile {
 
         // compute new thumbnails hash number
         final String forMagicHash = fileName + " "
-                + String.valueOf(targetDimension.width) + " "
-                + String.valueOf(targetDimension.height) + " "
-                + String.valueOf(getFileLength()) + " "
+                + targetDimension.width + " "
+                + targetDimension.height + " "
+                + getFileLength() + " "
                 + Constants.THUMBNAIL_VERSION;
 
-        // System.out.println("Computing hash from: " + forMagicHash);
         return Utils.getStringCrcAsHex(forMagicHash);
     }
 
@@ -174,14 +236,15 @@ public class Picture extends AbstractFile {
      * relative to designated thumbnails directory within parent directory.
      */
     public String getRelativeThumbnailFileName(final Dimension targetDimension) {
+        String thumbnailExtension = "gif".equalsIgnoreCase(getFileExtension()) ? "gif" : "jpeg";
+
         return FilePathParser.getFileNameWithoutExtension(fileName) + " ("
-                + computeThumbnailHash(targetDimension) + ").jpeg";
+                + computeThumbnailHash(targetDimension) + ")." + thumbnailExtension;
     }
 
     @Override
-    public void updateFileMetainfo(final File parentDirectory) throws Exception {
-        final BufferedImage image = Utils
-                .getBufferedImage(getFile(parentDirectory));
+    public void updateFileMetadata(final File parentDirectory) throws Exception {
+        final BufferedImage image = getBufferedImage(getFile(parentDirectory));
         dimensions = new Dimension(image.getWidth(), image.getHeight());
     }