better error handling
[meviz.git] / src / main / java / eu / svjatoslav / meviz / htmlindexer / metadata / fileTypes / Picture.java
1 /*
2  * Meviz - Various tools collection to work with multimedia.
3  * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU General Public License
7  * as published by the Free Software Foundation.
8  */
9
10 package eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes;
11
12 import java.awt.Graphics2D;
13 import java.awt.Image;
14 import java.awt.Toolkit;
15 import java.awt.image.BufferedImage;
16 import java.awt.image.FilteredImageSource;
17 import java.awt.image.ImageFilter;
18 import java.awt.image.ImageProducer;
19 import java.io.File;
20 import java.io.FileOutputStream;
21 import java.io.OutputStream;
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import javax.imageio.ImageIO;
26 import javax.swing.ImageIcon;
27
28 import eu.svjatoslav.commons.file.FilePathParser;
29 import eu.svjatoslav.meviz.htmlindexer.Constants;
30 import eu.svjatoslav.meviz.htmlindexer.Utils;
31 import eu.svjatoslav.meviz.htmlindexer.metadata.Dimension;
32
33 public class Picture extends AbstractFile {
34
35         /**
36          * Actual returned target thumbnail size will be adjusted from desired one
37          * by attempting to generate as large as possible thumbnail, while not
38          * exceeding provided thumbnail width and height, and preserving aspect
39          * ratio of original image.
40          */
41         public static java.awt.Dimension getTargetThumbnailDimension(
42                         final java.awt.Dimension originalImageDimension,
43                         final java.awt.Dimension desiredTargetDimension) {
44
45                 final double thumbWidthToHeightRatio = (double) desiredTargetDimension.width
46                                 / (double) desiredTargetDimension.height;
47                 final double inputImageWidthToHeightRatio = (double) originalImageDimension.width
48                                 / (double) originalImageDimension.height;
49
50                 if (thumbWidthToHeightRatio < inputImageWidthToHeightRatio) {
51
52                         final java.awt.Dimension result = new java.awt.Dimension(
53                                         desiredTargetDimension.width,
54                                         (int) (desiredTargetDimension.width / inputImageWidthToHeightRatio));
55
56                         return result;
57                 } else {
58
59                         final java.awt.Dimension result = new java.awt.Dimension(
60                                         (int) (desiredTargetDimension.height * inputImageWidthToHeightRatio),
61                                         desiredTargetDimension.height);
62
63                         return result;
64                 }
65         }
66
67         /**
68          * Propose list of thumbnail dimensions.
69          */
70         public static List<Dimension> getThumbnailDimensions(Dimension current) {
71                 final ArrayList<Dimension> result = new ArrayList<Dimension>();
72                 result.add(current);
73
74                 while (current.getArea() > 1000000) {
75                         current = current.getScaled(0.5d);
76                         result.add(current);
77                 }
78
79                 return result;
80
81         }
82
83         public static void makeThumbnail(final File inputFile,
84                         final File outputFile,
85                         final java.awt.Dimension preferredTargetDimensions) {
86
87                 try {
88
89                         final BufferedImage inputImage = Utils.getBufferedImage(inputFile);
90
91                         final java.awt.Dimension sourceImageDimension = new java.awt.Dimension(
92                                         inputImage.getWidth(), inputImage.getHeight());
93
94                         final java.awt.Dimension targetDimensions = getTargetThumbnailDimension(
95                                         sourceImageDimension, preferredTargetDimensions);
96
97                         final OutputStream out = new FileOutputStream(outputFile);
98
99                         final Image scaledImage = scaleImage(inputImage,
100                                         targetDimensions.width, targetDimensions.height);
101
102                         final BufferedImage bufferedImage = new BufferedImage(
103                                         scaledImage.getWidth(null), scaledImage.getHeight(null),
104                                         BufferedImage.TYPE_INT_RGB);
105
106                         final Graphics2D g = bufferedImage.createGraphics();
107                         g.drawImage(scaledImage, 0, 0, null);
108                         g.dispose();
109
110                         ImageIO.write(bufferedImage, "jpg", out);
111                         out.close();
112
113                 } catch (final Exception exception) {
114                         System.out.println(exception.toString());
115                         exception.printStackTrace();
116                 }
117         }
118
119         /**
120          * @return new image scaled to desired dimensions
121          */
122         public static Image scaleImage(final Image srcImage, final int width,
123                         final int height) {
124
125                 ImageFilter filter;
126                 filter = new java.awt.image.AreaAveragingScaleFilter(width, height);
127
128                 final ImageProducer prod = new FilteredImageSource(
129                                 srcImage.getSource(), filter);
130
131                 final Image newImage = Toolkit.getDefaultToolkit().createImage(prod);
132
133                 final ImageIcon imageIcon = new ImageIcon(newImage);
134                 return imageIcon.getImage();
135         }
136
137         private static final long serialVersionUID = -4156533490858298387L;;
138
139         /**
140          * Picture dimensions.
141          */
142         private Dimension dimensions;
143
144         public Picture(final File parentDirectory, final String fileName)
145                         throws Exception {
146                 super(parentDirectory, fileName);
147         }
148
149         private String computeThumbnailHash(final Dimension targetDimension) {
150
151                 // compute new thumbnails hash number
152                 final String forMagicHash = fileName + " "
153                                 + String.valueOf(targetDimension.width) + " "
154                                 + String.valueOf(targetDimension.height) + " "
155                                 + String.valueOf(getFileLength()) + " "
156                                 + Constants.THUMBNAIL_VERSION;
157
158                 // System.out.println("Computing hash from: " + forMagicHash);
159                 return Utils.getStringCrcAsHex(forMagicHash);
160         }
161
162         public Dimension getDimensions() {
163                 return dimensions;
164         }
165
166         /**
167          * Get thumbnail file name for this image and desired thumbnail dimensions
168          * relative to designated thumbnails directory within parent directory.
169          */
170         public String getRelativeThumbnailFileName(final Dimension targetDimension) {
171                 return FilePathParser.getFileNameWithoutExtension(fileName) + " ("
172                                 + computeThumbnailHash(targetDimension) + ").jpeg";
173         }
174
175         @Override
176         public void updateFileMetainfo(final File parentDirectory) throws Exception {
177                 final BufferedImage image = Utils
178                                 .getBufferedImage(getFile(parentDirectory));
179                 dimensions = new Dimension(image.getWidth(), image.getHeight());
180         }
181
182 }