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