Commit | Line | Data |
---|---|---|
80500544 NR |
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; | |
80500544 NR |
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; | |
c48600a5 | 14 | import be.nikiroo.utils.StringUtils; |
80500544 NR |
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 { | |
10b6023d NR |
22 | @Override |
23 | protected boolean check() { | |
a2c1d5fe NR |
24 | // Will not work if ImageIO is not available |
25 | ImageIO.getCacheDirectory(); | |
10b6023d NR |
26 | return true; |
27 | } | |
28 | ||
80500544 NR |
29 | @Override |
30 | public void saveAsImage(Image img, File target, String format) | |
31 | throws IOException { | |
32 | try { | |
e8aa5bf9 | 33 | BufferedImage image = fromImage(img); |
80500544 NR |
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 | |
e8aa5bf9 | 44 | // Second chance: PNG |
80500544 | 45 | if (!ok && !format.equals("png")) { |
89aa5782 NR |
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 | } | |
80500544 NR |
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 | */ | |
e704a414 | 78 | public static BufferedImage fromImage(Image img) throws IOException { |
7b42695f | 79 | InputStream in = img.newInputStream(); |
35466644 NR |
80 | BufferedImage image; |
81 | try { | |
7b42695f NR |
82 | int orientation; |
83 | try { | |
84 | orientation = getExifTransorm(in); | |
85 | } catch (Exception e) { | |
86 | // no EXIF transform, ok | |
87 | orientation = -1; | |
88 | } | |
80500544 | 89 | |
7b42695f | 90 | in.reset(); |
80500544 | 91 | |
7b42695f NR |
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) { | |
c48600a5 | 102 | String extra = ""; |
59654e2a | 103 | if (img.getSize() <= 2048) { |
c48600a5 NR |
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); | |
7b42695f NR |
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 | } | |
80500544 | 161 | |
7b42695f NR |
162 | if (affineTransform != null) { |
163 | AffineTransformOp affineTransformOp = new AffineTransformOp( | |
164 | affineTransform, AffineTransformOp.TYPE_BILINEAR); | |
80500544 | 165 | |
7b42695f NR |
166 | BufferedImage transformedImage = new BufferedImage(width, |
167 | height, image.getType()); | |
168 | transformedImage = affineTransformOp.filter(image, | |
169 | transformedImage); | |
80500544 | 170 | |
7b42695f NR |
171 | image = transformedImage; |
172 | } | |
173 | // | |
174 | } finally { | |
175 | in.close(); | |
80500544 | 176 | } |
80500544 NR |
177 | |
178 | return image; | |
179 | } | |
180 | } |