|
1 /* |
|
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 */ |
|
23 |
|
24 /** |
|
25 * @test |
|
26 * @bug 8149028 |
|
27 * @author a.stepanov |
|
28 * @summary check TIFFDirectory manipulation |
|
29 * by means of TIFFImageReadParam |
|
30 * @run main TIFFImageReadParamTest |
|
31 */ |
|
32 |
|
33 |
|
34 import java.awt.Color; |
|
35 import java.awt.Graphics; |
|
36 import java.awt.image.BufferedImage; |
|
37 import java.io.*; |
|
38 import javax.imageio.*; |
|
39 import javax.imageio.metadata.IIOMetadata; |
|
40 import javax.imageio.plugins.tiff.*; |
|
41 import javax.imageio.stream.ImageInputStream; |
|
42 import javax.imageio.stream.ImageOutputStream; |
|
43 |
|
44 public class TIFFImageReadParamTest { |
|
45 |
|
46 private final static String FILENAME = "test.tiff"; |
|
47 private final static int SZ = 100; |
|
48 private final static Color C = Color.RED; |
|
49 |
|
50 private final static String GEO_DATA = "test params"; |
|
51 private final static int GEO_N = GeoTIFFTagSet.TAG_GEO_ASCII_PARAMS; |
|
52 |
|
53 private final static String EXIF_DATA = "2000:01:01 00:00:01"; |
|
54 private final static int EXIF_N = ExifTIFFTagSet.TAG_DATE_TIME_ORIGINAL; |
|
55 |
|
56 private final static String GPS_DATA = |
|
57 ExifGPSTagSet.STATUS_MEASUREMENT_IN_PROGRESS; |
|
58 private final static int GPS_N = ExifGPSTagSet.TAG_GPS_STATUS; |
|
59 |
|
60 private final static short FAX_DATA = |
|
61 FaxTIFFTagSet.CLEAN_FAX_DATA_ERRORS_UNCORRECTED; |
|
62 private final static int FAX_N = FaxTIFFTagSet.TAG_CLEAN_FAX_DATA; |
|
63 |
|
64 private ImageWriter getTIFFWriter() { |
|
65 |
|
66 java.util.Iterator<ImageWriter> writers = |
|
67 ImageIO.getImageWritersByFormatName("TIFF"); |
|
68 if (!writers.hasNext()) { |
|
69 throw new RuntimeException("No writers available for TIFF format"); |
|
70 } |
|
71 return writers.next(); |
|
72 } |
|
73 |
|
74 private ImageReader getTIFFReader() { |
|
75 |
|
76 java.util.Iterator<ImageReader> readers = |
|
77 ImageIO.getImageReadersByFormatName("TIFF"); |
|
78 if (!readers.hasNext()) { |
|
79 throw new RuntimeException("No readers available for TIFF format"); |
|
80 } |
|
81 return readers.next(); |
|
82 } |
|
83 |
|
84 private void check(boolean ok, String msg) { |
|
85 if (!ok) { throw new RuntimeException(msg); } |
|
86 } |
|
87 |
|
88 private void addASCIIField(TIFFDirectory d, |
|
89 String name, |
|
90 String data, |
|
91 int num) { |
|
92 |
|
93 String a[] = {data}; |
|
94 d.addTIFFField(new TIFFField( |
|
95 new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII), |
|
96 TIFFTag.TIFF_ASCII, 1, a)); |
|
97 } |
|
98 |
|
99 private void checkASCIIValue(TIFFDirectory d, |
|
100 String what, |
|
101 String data, |
|
102 int num) { |
|
103 |
|
104 TIFFField f = d.getTIFFField(num); |
|
105 check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII"); |
|
106 check(f.getCount() == 1, "invalid " + what + " data count"); |
|
107 check(f.getValueAsString(0).equals(data), |
|
108 "invalid " + what + " data"); |
|
109 } |
|
110 |
|
111 |
|
112 private void writeImage() throws Exception { |
|
113 |
|
114 OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME)); |
|
115 try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) { |
|
116 ImageWriter writer = getTIFFWriter(); |
|
117 writer.setOutput(ios); |
|
118 |
|
119 BufferedImage img = |
|
120 new BufferedImage(SZ, SZ, BufferedImage.TYPE_INT_RGB); |
|
121 Graphics g = img.getGraphics(); |
|
122 g.setColor(C); |
|
123 g.fillRect(0, 0, SZ, SZ); |
|
124 g.dispose(); |
|
125 |
|
126 IIOMetadata metadata = writer.getDefaultImageMetadata( |
|
127 new ImageTypeSpecifier(img), writer.getDefaultWriteParam()); |
|
128 |
|
129 TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata); |
|
130 |
|
131 // add some extension tags |
|
132 addASCIIField(dir, "GeoAsciiParamsTag", GEO_DATA, GEO_N); |
|
133 addASCIIField(dir, "DateTimeOriginal", EXIF_DATA, EXIF_N); |
|
134 addASCIIField(dir, "GPSStatus", GPS_DATA, GPS_N); |
|
135 |
|
136 dir.addTIFFField(new TIFFField(new TIFFTag( |
|
137 "CleanFaxData", FAX_N, 1 << TIFFTag.TIFF_SHORT), FAX_DATA)); |
|
138 |
|
139 IIOMetadata data = dir.getAsMetadata(); |
|
140 |
|
141 writer.write(new IIOImage(img, null, data)); |
|
142 |
|
143 ios.flush(); |
|
144 writer.dispose(); |
|
145 } |
|
146 } |
|
147 |
|
148 private void checkImage(BufferedImage img) { |
|
149 |
|
150 check(img.getWidth() == SZ, "invalid image width"); |
|
151 check(img.getHeight() == SZ, "invalid image height"); |
|
152 Color c = new Color(img.getRGB(SZ / 2, SZ / 2)); |
|
153 check(c.equals(C), "invalid image color"); |
|
154 } |
|
155 |
|
156 private TIFFDirectory getDir(TIFFTagSet[] add, |
|
157 TIFFTagSet[] remove) throws Exception { |
|
158 |
|
159 ImageReader reader = getTIFFReader(); |
|
160 |
|
161 ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME)); |
|
162 reader.setInput(s, false, true); |
|
163 |
|
164 int ni = reader.getNumImages(true); |
|
165 check(ni == 1, "invalid number of images: " + ni); |
|
166 |
|
167 TIFFImageReadParam param = new TIFFImageReadParam(); |
|
168 for (TIFFTagSet ts: add) { param.addAllowedTagSet(ts); } |
|
169 for (TIFFTagSet ts: remove) { param.removeAllowedTagSet(ts); } |
|
170 |
|
171 IIOImage img = reader.readAll(0, param); |
|
172 |
|
173 // just in case, check image |
|
174 checkImage((BufferedImage) img.getRenderedImage()); |
|
175 |
|
176 IIOMetadata metadata = img.getMetadata(); |
|
177 TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata); |
|
178 |
|
179 reader.dispose(); |
|
180 s.close(); |
|
181 |
|
182 return dir; |
|
183 } |
|
184 |
|
185 private void simpleChecks() { |
|
186 |
|
187 TIFFImageReadParam param = new TIFFImageReadParam(); |
|
188 |
|
189 java.util.List<TIFFTagSet> allowed = param.getAllowedTagSets(); |
|
190 |
|
191 // see docs |
|
192 check(allowed.contains(BaselineTIFFTagSet.getInstance()), |
|
193 "must contain BaselineTIFFTagSet"); |
|
194 check(allowed.contains(FaxTIFFTagSet.getInstance()), |
|
195 "must contain FaxTIFFTagSet"); |
|
196 check(allowed.contains(ExifParentTIFFTagSet.getInstance()), |
|
197 "must contain ExifParentTIFFTagSet"); |
|
198 check(allowed.contains(GeoTIFFTagSet.getInstance()), |
|
199 "must contain GeoTIFFTagSet"); |
|
200 |
|
201 TIFFTagSet gps = ExifGPSTagSet.getInstance(); |
|
202 param.addAllowedTagSet(gps); |
|
203 check(param.getAllowedTagSets().contains(gps), |
|
204 "must contain ExifGPSTagSet"); |
|
205 |
|
206 param.removeAllowedTagSet(gps); |
|
207 check(!param.getAllowedTagSets().contains(gps), |
|
208 "must not contain ExifGPSTagSet"); |
|
209 |
|
210 // check that repeating remove goes properly |
|
211 param.removeAllowedTagSet(gps); |
|
212 |
|
213 boolean ok = false; |
|
214 try { param.addAllowedTagSet(null); } |
|
215 catch (IllegalArgumentException e) { ok = true; } |
|
216 check(ok, "must not be able to add null tag set"); |
|
217 |
|
218 ok = false; |
|
219 try { param.removeAllowedTagSet(null); } |
|
220 catch (IllegalArgumentException e) { ok = true; } |
|
221 check(ok, "must not be able to remove null tag set"); |
|
222 } |
|
223 |
|
224 private void run() { |
|
225 |
|
226 simpleChecks(); |
|
227 |
|
228 try { |
|
229 |
|
230 writeImage(); |
|
231 |
|
232 TIFFTagSet |
|
233 empty[] = {}, |
|
234 geo[] = { GeoTIFFTagSet.getInstance() }, |
|
235 exif[] = { ExifTIFFTagSet.getInstance() }, |
|
236 gps[] = { ExifGPSTagSet.getInstance() }, |
|
237 fax[] = { FaxTIFFTagSet.getInstance() }; |
|
238 |
|
239 // default param state |
|
240 TIFFDirectory dir = getDir(empty, empty); |
|
241 // Geo and Fax are default allowed tag sets |
|
242 check(dir.containsTIFFField(GEO_N), "must contain Geo field"); |
|
243 checkASCIIValue(dir, "Geo", GEO_DATA, GEO_N); |
|
244 check(dir.containsTIFFField(FAX_N), "must contain Fax field"); |
|
245 check( |
|
246 (dir.getTIFFField(FAX_N).getCount() == 1) && |
|
247 (dir.getTIFFField(FAX_N).getAsInt(0) == FAX_DATA), |
|
248 "invalid Fax field value"); |
|
249 |
|
250 // corresponding tag sets are non-default |
|
251 check(!dir.containsTIFFField(EXIF_N), "must not contain Geo field"); |
|
252 check(!dir.containsTIFFField(GPS_N), "must not contain GPS field"); |
|
253 |
|
254 // remove Fax |
|
255 dir = getDir(empty, fax); |
|
256 check(!dir.containsTIFFField(FAX_N), "must not contain Fax field"); |
|
257 |
|
258 // add EXIF, remove Geo |
|
259 dir = getDir(exif, geo); |
|
260 check(dir.containsTIFFField(EXIF_N), "must contain EXIF field"); |
|
261 checkASCIIValue(dir, "EXIF", EXIF_DATA, EXIF_N); |
|
262 check(!dir.containsTIFFField(GEO_N), "must not contain Geo field"); |
|
263 |
|
264 // add GPS |
|
265 dir = getDir(gps, empty); |
|
266 check(dir.containsTIFFField(GPS_N), "must contain GPS field"); |
|
267 checkASCIIValue(dir, "GPS", GPS_DATA, GPS_N); |
|
268 |
|
269 } catch (Exception e) { throw new RuntimeException(e); } |
|
270 } |
|
271 |
|
272 public static void main(String[] args) { |
|
273 (new TIFFImageReadParamTest()).run(); |
|
274 } |
|
275 } |