Improve ImageUtilsAndroid and ImageUtils check() system
[fanfix.git] / src / be / nikiroo / utils / ui / ImageUtilsAwt.java
1 package be.nikiroo.utils.ui;
2
3 import java.awt.geom.AffineTransform;
4 import java.awt.image.AffineTransformOp;
5 import java.awt.image.BufferedImage;
6 import java.io.File;
7 import java.io.IOException;
8 import java.io.InputStream;
9
10 import javax.imageio.ImageIO;
11
12 import be.nikiroo.utils.Image;
13 import be.nikiroo.utils.ImageUtils;
14
15 /**
16 * This class offer some utilities based around images and uses java.awt.
17 *
18 * @author niki
19 */
20 public class ImageUtilsAwt extends ImageUtils {
21 @Override
22 protected boolean check() {
23 // Will not work if ImageIO is not available
24 ImageIO.getCacheDirectory();
25 return true;
26 }
27
28 @Override
29 public void saveAsImage(Image img, File target, String format)
30 throws IOException {
31 try {
32 BufferedImage image = fromImage(img);
33
34 boolean ok = false;
35 try {
36
37 ok = ImageIO.write(image, format, target);
38 } catch (IOException e) {
39 ok = false;
40 }
41
42 // Some formats are not reliable
43 // Second chance: PNG
44 if (!ok && !format.equals("png")) {
45 try {
46 ok = ImageIO.write(image, "png", target);
47 } catch (IllegalArgumentException e) {
48 throw e;
49 } catch (Exception e) {
50 throw new IOException("Undocumented exception occured, "
51 + "converting to IOException", e);
52 }
53 }
54
55 if (!ok) {
56 throw new IOException(
57 "Cannot find a writer for this image and format: "
58 + format);
59 }
60 } catch (IOException e) {
61 throw new IOException("Cannot write image to " + target, e);
62 }
63 }
64
65 /**
66 * Convert the given {@link Image} into a {@link BufferedImage} object,
67 * respecting the EXIF transformations if any.
68 *
69 * @param img
70 * the {@link Image}
71 *
72 * @return the {@link Image} object
73 *
74 * @throws IOException
75 * in case of IO error
76 */
77 public static BufferedImage fromImage(Image img) throws IOException {
78 InputStream in = img.newInputStream();
79 BufferedImage image;
80 try {
81 int orientation;
82 try {
83 orientation = getExifTransorm(in);
84 } catch (Exception e) {
85 // no EXIF transform, ok
86 orientation = -1;
87 }
88
89 in.reset();
90
91 try {
92 image = ImageIO.read(in);
93 } catch (IllegalArgumentException e) {
94 throw e;
95 } catch (Exception e) {
96 throw new IOException("Undocumented exception occured, "
97 + "converting to IOException", e);
98 }
99
100 if (image == null) {
101 throw new IOException("Failed to convert input to image");
102 }
103
104 // Note: this code has been found on Internet;
105 // thank you anonymous coder.
106 int width = image.getWidth();
107 int height = image.getHeight();
108 AffineTransform affineTransform = new AffineTransform();
109
110 switch (orientation) {
111 case 1:
112 affineTransform = null;
113 break;
114 case 2: // Flip X
115 affineTransform.scale(-1.0, 1.0);
116 affineTransform.translate(-width, 0);
117 break;
118 case 3: // PI rotation
119 affineTransform.translate(width, height);
120 affineTransform.rotate(Math.PI);
121 break;
122 case 4: // Flip Y
123 affineTransform.scale(1.0, -1.0);
124 affineTransform.translate(0, -height);
125 break;
126 case 5: // - PI/2 and Flip X
127 affineTransform.rotate(-Math.PI / 2);
128 affineTransform.scale(-1.0, 1.0);
129 break;
130 case 6: // -PI/2 and -width
131 affineTransform.translate(height, 0);
132 affineTransform.rotate(Math.PI / 2);
133 break;
134 case 7: // PI/2 and Flip
135 affineTransform.scale(-1.0, 1.0);
136 affineTransform.translate(-height, 0);
137 affineTransform.translate(0, width);
138 affineTransform.rotate(3 * Math.PI / 2);
139 break;
140 case 8: // PI / 2
141 affineTransform.translate(0, width);
142 affineTransform.rotate(3 * Math.PI / 2);
143 break;
144 default:
145 affineTransform = null;
146 break;
147 }
148
149 if (affineTransform != null) {
150 AffineTransformOp affineTransformOp = new AffineTransformOp(
151 affineTransform, AffineTransformOp.TYPE_BILINEAR);
152
153 BufferedImage transformedImage = new BufferedImage(width,
154 height, image.getType());
155 transformedImage = affineTransformOp.filter(image,
156 transformedImage);
157
158 image = transformedImage;
159 }
160 //
161 } finally {
162 in.close();
163 }
164
165 return image;
166 }
167 }