1 /*
2  * Copyright (c) 2001, 2004, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.imageio.plugins.png;
27 
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.List;
31 import java.util.ListResourceBundle;
32 import javax.imageio.ImageTypeSpecifier;
33 import javax.imageio.metadata.IIOMetadataFormat;
34 import javax.imageio.metadata.IIOMetadataFormatImpl;
35 
36 public class PNGMetadataFormat extends IIOMetadataFormatImpl {
37 
38     private static IIOMetadataFormat instance = null;
39 
40     private static String VALUE_0 = "0";
41     private static String VALUE_1 = "1";
42     private static String VALUE_12 = "12";
43     private static String VALUE_23 = "23";
44     private static String VALUE_31 = "31";
45     private static String VALUE_59 = "59";
46     private static String VALUE_60 = "60";
47     private static String VALUE_255 = "255";
48     private static String VALUE_MAX_16 = "65535"; // 2^16 - 1
49     private static String VALUE_MAX_32 = "2147483647"; // 2^32 - 1
50 
PNGMetadataFormat()51     private PNGMetadataFormat() {
52         super(PNGMetadata.nativeMetadataFormatName,
53               CHILD_POLICY_SOME);
54 
55         // root -> IHDR
56         addElement("IHDR", PNGMetadata.nativeMetadataFormatName,
57                    CHILD_POLICY_EMPTY);
58 
59         addAttribute("IHDR", "width",
60                      DATATYPE_INTEGER, true, null,
61                      VALUE_1, VALUE_MAX_32, true, true);
62 
63         addAttribute("IHDR", "height",
64                      DATATYPE_INTEGER, true, null,
65                      VALUE_1, VALUE_MAX_32, true, true);
66 
67         addAttribute("IHDR", "bitDepth",
68                      DATATYPE_INTEGER, true, null,
69                      Arrays.asList(PNGMetadata.IHDR_bitDepths));
70 
71         String[] colorTypes = {
72             "Grayscale", "RGB", "Palette", "GrayAlpha", "RGBAlpha"
73         };
74         addAttribute("IHDR", "colorType",
75                      DATATYPE_STRING, true, null,
76                      Arrays.asList(colorTypes));
77 
78         addAttribute("IHDR", "compressionMethod",
79                      DATATYPE_STRING, true, null,
80                      Arrays.asList(PNGMetadata.IHDR_compressionMethodNames));
81 
82         addAttribute("IHDR", "filterMethod",
83                      DATATYPE_STRING, true, null,
84                      Arrays.asList(PNGMetadata.IHDR_filterMethodNames));
85 
86         addAttribute("IHDR", "interlaceMethod",
87                      DATATYPE_STRING, true, null,
88                      Arrays.asList(PNGMetadata.IHDR_interlaceMethodNames));
89 
90         // root -> PLTE
91         addElement("PLTE", PNGMetadata.nativeMetadataFormatName,
92                    1, 256);
93 
94         // root -> PLTE -> PLTEEntry
95         addElement("PLTEEntry", "PLTE",
96                    CHILD_POLICY_EMPTY);
97 
98         addAttribute("PLTEEntry", "index",
99                      DATATYPE_INTEGER, true, null,
100                      VALUE_0, VALUE_255, true, true);
101 
102         addAttribute("PLTEEntry", "red",
103                      DATATYPE_INTEGER, true, null,
104                      VALUE_0, VALUE_255, true, true);
105 
106         addAttribute("PLTEEntry", "green",
107                      DATATYPE_INTEGER, true, null,
108                      VALUE_0, VALUE_255, true, true);
109 
110         addAttribute("PLTEEntry", "blue",
111                      DATATYPE_INTEGER, true, null,
112                      VALUE_0, VALUE_255, true, true);
113 
114         // root -> bKGD
115         addElement("bKGD", PNGMetadata.nativeMetadataFormatName,
116                    CHILD_POLICY_CHOICE);
117 
118         // root -> bKGD -> bKGD_Grayscale
119         addElement("bKGD_Grayscale", "bKGD",
120                    CHILD_POLICY_EMPTY);
121 
122         addAttribute("bKGD_Grayscale", "gray",
123                      DATATYPE_INTEGER, true, null,
124                      VALUE_0, VALUE_MAX_16, true, true);
125 
126         // root -> bKGD -> bKGD_RGB
127         addElement("bKGD_RGB", "bKGD",
128                    CHILD_POLICY_EMPTY);
129 
130         addAttribute("bKGD_RGB", "red",
131                      DATATYPE_INTEGER, true, null,
132                      VALUE_0, VALUE_MAX_16, true, true);
133 
134         addAttribute("bKGD_RGB", "green",
135                      DATATYPE_INTEGER, true, null,
136                      VALUE_0, VALUE_MAX_16, true, true);
137 
138         addAttribute("bKGD_RGB", "blue",
139                      DATATYPE_INTEGER, true, null,
140                      VALUE_0, VALUE_MAX_16, true, true);
141 
142         // root -> bKGD -> bKGD_Palette
143         addElement("bKGD_Palette", "bKGD",
144                    CHILD_POLICY_EMPTY);
145 
146         addAttribute("bKGD_Palette", "index",
147                      DATATYPE_INTEGER, true, null,
148                      VALUE_0, VALUE_255, true, true);
149 
150         // root -> cHRM
151         addElement("cHRM", PNGMetadata.nativeMetadataFormatName,
152                    CHILD_POLICY_EMPTY);
153 
154         addAttribute("cHRM", "whitePointX",
155                      DATATYPE_INTEGER, true, null,
156                      VALUE_0, VALUE_MAX_16, true, true);
157 
158         addAttribute("cHRM", "whitePointY",
159                      DATATYPE_INTEGER, true, null,
160                      VALUE_0, VALUE_MAX_16, true, true);
161 
162         addAttribute("cHRM", "redX",
163                      DATATYPE_INTEGER, true, null,
164                      VALUE_0, VALUE_MAX_16, true, true);
165 
166         addAttribute("cHRM", "redY",
167                      DATATYPE_INTEGER, true, null,
168                      VALUE_0, VALUE_MAX_16, true, true);
169 
170         addAttribute("cHRM", "greenX",
171                      DATATYPE_INTEGER, true, null,
172                      VALUE_0, VALUE_MAX_16, true, true);
173 
174         addAttribute("cHRM", "greenY",
175                      DATATYPE_INTEGER, true, null,
176                      VALUE_0, VALUE_MAX_16, true, true);
177 
178         addAttribute("cHRM", "blueX",
179                      DATATYPE_INTEGER, true, null,
180                      VALUE_0, VALUE_MAX_16, true, true);
181 
182         addAttribute("cHRM", "blueY",
183                      DATATYPE_INTEGER, true, null,
184                      VALUE_0, VALUE_MAX_16, true, true);
185 
186         // root -> gAMA
187         addElement("gAMA", PNGMetadata.nativeMetadataFormatName,
188                    CHILD_POLICY_EMPTY);
189 
190         addAttribute("gAMA", "value",
191                      DATATYPE_INTEGER, true, null,
192                      VALUE_0, VALUE_MAX_32, true, true);
193 
194         // root -> hIST
195         addElement("hIST", PNGMetadata.nativeMetadataFormatName,
196                    1, 256);
197 
198         // root -> hISTEntry
199         addElement("hISTEntry", "hIST",
200                    CHILD_POLICY_EMPTY);
201 
202         addAttribute("hISTEntry", "index",
203                      DATATYPE_INTEGER, true, null,
204                      VALUE_0, VALUE_255, true, true);
205 
206         addAttribute("hISTEntry", "value",
207                      DATATYPE_INTEGER, true, null,
208                      VALUE_0, VALUE_MAX_16, true, true);
209 
210         // root -> iCCP
211         addElement("iCCP", PNGMetadata.nativeMetadataFormatName,
212                    CHILD_POLICY_EMPTY);
213 
214         addAttribute("iCCP", "profileName",
215                      DATATYPE_STRING, true, null);
216 
217         addAttribute("iCCP", "compressionMethod",
218                      DATATYPE_STRING, true, null,
219                      Arrays.asList(PNGMetadata.iCCP_compressionMethodNames));
220 
221         addObjectValue("iCCP", byte.class, 0, Integer.MAX_VALUE);
222 
223         // root -> iTXt
224         addElement("iTXt", PNGMetadata.nativeMetadataFormatName,
225                    1, Integer.MAX_VALUE);
226 
227         // root -> iTXt -> iTXtEntry
228         addElement("iTXtEntry", "iTXt",
229                    CHILD_POLICY_EMPTY);
230 
231         addAttribute("iTXtEntry", "keyword",
232                      DATATYPE_STRING, true, null);
233 
234         addBooleanAttribute("iTXtEntry", "compressionFlag",
235                             false, false);
236 
237         addAttribute("iTXtEntry", "compressionMethod",
238                      DATATYPE_STRING, true, null);
239 
240         addAttribute("iTXtEntry", "languageTag",
241                      DATATYPE_STRING, true, null);
242 
243         addAttribute("iTXtEntry", "translatedKeyword",
244                      DATATYPE_STRING, true, null);
245 
246         addAttribute("iTXtEntry", "text",
247                      DATATYPE_STRING, true, null);
248 
249         // root -> pHYS
250         addElement("pHYS", PNGMetadata.nativeMetadataFormatName,
251                    CHILD_POLICY_EMPTY);
252 
253         addAttribute("pHYS", "pixelsPerUnitXAxis",
254                      DATATYPE_INTEGER, true, null,
255                      VALUE_0, VALUE_MAX_32, true, true);
256         addAttribute("pHYS", "pixelsPerUnitYAxis",
257                      DATATYPE_INTEGER, true, null,
258                      VALUE_0, VALUE_MAX_32, true, true);
259         addAttribute("pHYS", "unitSpecifier",
260                      DATATYPE_STRING, true, null,
261                      Arrays.asList(PNGMetadata.unitSpecifierNames));
262 
263         // root -> sBIT
264         addElement("sBIT", PNGMetadata.nativeMetadataFormatName,
265                    CHILD_POLICY_CHOICE);
266 
267         // root -> sBIT -> sBIT_Grayscale
268         addElement("sBIT_Grayscale", "sBIT",
269                    CHILD_POLICY_EMPTY);
270 
271         addAttribute("sBIT_Grayscale", "gray",
272                      DATATYPE_INTEGER, true, null,
273                      VALUE_0, VALUE_255, true, true);
274 
275         // root -> sBIT -> sBIT_GrayAlpha
276         addElement("sBIT_GrayAlpha", "sBIT",
277                    CHILD_POLICY_EMPTY);
278 
279         addAttribute("sBIT_GrayAlpha", "gray",
280                      DATATYPE_INTEGER, true, null,
281                      VALUE_0, VALUE_255, true, true);
282 
283         addAttribute("sBIT_GrayAlpha", "alpha",
284                      DATATYPE_INTEGER, true, null,
285                      VALUE_0, VALUE_255, true, true);
286 
287         // root -> sBIT -> sBIT_RGB
288         addElement("sBIT_RGB", "sBIT",
289                    CHILD_POLICY_EMPTY);
290 
291         addAttribute("sBIT_RGB", "red",
292                      DATATYPE_INTEGER, true, null,
293                      VALUE_0, VALUE_255, true, true);
294 
295         addAttribute("sBIT_RGB", "green",
296                      DATATYPE_INTEGER, true, null,
297                      VALUE_0, VALUE_255, true, true);
298 
299         addAttribute("sBIT_RGB", "blue",
300                      DATATYPE_INTEGER, true, null,
301                      VALUE_0, VALUE_255, true, true);
302 
303         // root -> sBIT -> sBIT_RGBAlpha
304         addElement("sBIT_RGBAlpha", "sBIT",
305                    CHILD_POLICY_EMPTY);
306 
307         addAttribute("sBIT_RGBAlpha", "red",
308                      DATATYPE_INTEGER, true, null,
309                      VALUE_0, VALUE_255, true, true);
310 
311         addAttribute("sBIT_RGBAlpha", "green",
312                      DATATYPE_INTEGER, true, null,
313                      VALUE_0, VALUE_255, true, true);
314 
315         addAttribute("sBIT_RGBAlpha", "blue",
316                      DATATYPE_INTEGER, true, null,
317                      VALUE_0, VALUE_255, true, true);
318 
319         addAttribute("sBIT_RGBAlpha", "alpha",
320                      DATATYPE_INTEGER, true, null,
321                      VALUE_0, VALUE_255, true, true);
322 
323         // root -> sBIT -> sBIT_Palette
324         addElement("sBIT_Palette", "sBIT",
325                    CHILD_POLICY_EMPTY);
326 
327         addAttribute("sBIT_Palette", "red",
328                      DATATYPE_INTEGER, true, null,
329                      VALUE_0, VALUE_255, true, true);
330 
331         addAttribute("sBIT_Palette", "green",
332                      DATATYPE_INTEGER, true, null,
333                      VALUE_0, VALUE_255, true, true);
334 
335         addAttribute("sBIT_Palette", "blue",
336                      DATATYPE_INTEGER, true, null,
337                      VALUE_0, VALUE_255, true, true);
338 
339         // root -> sPLT
340         addElement("sPLT", PNGMetadata.nativeMetadataFormatName,
341                    1, 256);
342 
343         // root -> sPLT -> sPLTEntry
344         addElement("sPLTEntry", "sPLT",
345                    CHILD_POLICY_EMPTY);
346 
347         addAttribute("sPLTEntry", "index",
348                      DATATYPE_INTEGER, true, null,
349                      VALUE_0, VALUE_255, true, true);
350 
351         addAttribute("sPLTEntry", "red",
352                      DATATYPE_INTEGER, true, null,
353                      VALUE_0, VALUE_255, true, true);
354 
355         addAttribute("sPLTEntry", "green",
356                      DATATYPE_INTEGER, true, null,
357                      VALUE_0, VALUE_255, true, true);
358 
359         addAttribute("sPLTEntry", "blue",
360                      DATATYPE_INTEGER, true, null,
361                      VALUE_0, VALUE_255, true, true);
362 
363         addAttribute("sPLTEntry", "alpha",
364                      DATATYPE_INTEGER, true, null,
365                      VALUE_0, VALUE_255, true, true);
366 
367         // root -> sRGB
368         addElement("sRGB", PNGMetadata.nativeMetadataFormatName,
369                    CHILD_POLICY_EMPTY);
370 
371         addAttribute("sRGB", "renderingIntent",
372                      DATATYPE_STRING, true, null,
373                      Arrays.asList(PNGMetadata.renderingIntentNames));
374 
375         // root -> tEXt
376         addElement("tEXt", PNGMetadata.nativeMetadataFormatName,
377                    1, Integer.MAX_VALUE);
378 
379         // root -> tEXt -> tEXtEntry
380         addElement("tEXtEntry", "tEXt",
381                    CHILD_POLICY_EMPTY);
382 
383         addAttribute("tEXtEntry", "keyword",
384                      DATATYPE_STRING, true, null);
385 
386         addAttribute("tEXtEntry", "value",
387                      DATATYPE_STRING, true, null);
388 
389         // root -> tIME
390         addElement("tIME", PNGMetadata.nativeMetadataFormatName,
391                    CHILD_POLICY_EMPTY);
392 
393         addAttribute("tIME", "year",
394                      DATATYPE_INTEGER, true, null,
395                      VALUE_0, VALUE_MAX_16, true, true);
396 
397         addAttribute("tIME", "month",
398                      DATATYPE_INTEGER, true, null,
399                      VALUE_1, VALUE_12, true, true);
400 
401         addAttribute("tIME", "day",
402                      DATATYPE_INTEGER, true, null,
403                      VALUE_1, VALUE_31, true, true);
404 
405         addAttribute("tIME", "hour",
406                      DATATYPE_INTEGER, true, null,
407                      VALUE_0, VALUE_23, true, true);
408 
409         addAttribute("tIME", "minute",
410                      DATATYPE_INTEGER, true, null,
411                      VALUE_0, VALUE_59, true, true);
412 
413         addAttribute("tIME", "second",
414                      DATATYPE_INTEGER, true, null,
415                      VALUE_0, VALUE_60, true, true);
416 
417         // root -> tRNS
418         addElement("tRNS", PNGMetadata.nativeMetadataFormatName,
419                    CHILD_POLICY_CHOICE);
420 
421         // root -> tRNS -> tRNS_Grayscale
422         addElement("tRNS_Grayscale", "tRNS",
423                    CHILD_POLICY_EMPTY);
424 
425         addAttribute("tRNS_Grayscale", "gray",
426                      DATATYPE_INTEGER, true, null,
427                      VALUE_0, VALUE_MAX_16, true, true);
428 
429         // root -> tRNS -> tRNS_RGB
430         addElement("tRNS_RGB", "tRNS",
431                    CHILD_POLICY_EMPTY);
432 
433         addAttribute("tRNS_RGB", "red",
434                      DATATYPE_INTEGER, true, null,
435                      VALUE_0, VALUE_MAX_16, true, true);
436 
437         addAttribute("tRNS_RGB", "green",
438                      DATATYPE_INTEGER, true, null,
439                      VALUE_0, VALUE_MAX_16, true, true);
440 
441         addAttribute("tRNS_RGB", "blue",
442                      DATATYPE_INTEGER, true, null,
443                      VALUE_0, VALUE_MAX_16, true, true);
444 
445         // root -> tRNS -> tRNS_Palette
446         addElement("tRNS_Palette", "tRNS",
447                    CHILD_POLICY_EMPTY);
448 
449         addAttribute("tRNS_Palette", "index",
450                      DATATYPE_INTEGER, true, null,
451                      VALUE_0, VALUE_255, true, true);
452 
453         addAttribute("tRNS_Palette", "alpha",
454                      DATATYPE_INTEGER, true, null,
455                      VALUE_0, VALUE_255, true, true);
456 
457         // root -> zTXt
458         addElement("zTXt", PNGMetadata.nativeMetadataFormatName,
459                    1, Integer.MAX_VALUE);
460 
461         // root -> zTXt -> zTXtEntry
462         addElement("zTXtEntry", "zTXt",
463                    CHILD_POLICY_EMPTY);
464 
465         addAttribute("zTXtEntry", "keyword",
466                      DATATYPE_STRING, true, null);
467 
468         addAttribute("zTXtEntry", "compressionMethod",
469                      DATATYPE_STRING, true, null,
470                      Arrays.asList(PNGMetadata.zTXt_compressionMethodNames));
471 
472         addAttribute("zTXtEntry", "text",
473                      DATATYPE_STRING, true, null);
474 
475         // root -> UnknownChunks
476         addElement("UnknownChunks", PNGMetadata.nativeMetadataFormatName,
477                    1, Integer.MAX_VALUE);
478 
479         // root -> UnknownChunks -> UnknownChunk
480         addElement("UnknownChunk", "UnknownChunks",
481                    CHILD_POLICY_EMPTY);
482 
483         addAttribute("UnknownChunk", "type",
484                      DATATYPE_STRING, true, null);
485 
486         addObjectValue("UnknownChunk", byte.class, 0, Integer.MAX_VALUE);
487     }
488 
canNodeAppear(String elementName, ImageTypeSpecifier imageType)489     public boolean canNodeAppear(String elementName,
490                                  ImageTypeSpecifier imageType) {
491         return true;
492     }
493 
getInstance()494     public static synchronized IIOMetadataFormat getInstance() {
495         if (instance == null) {
496             instance = new PNGMetadataFormat();
497         }
498         return instance;
499     }
500 }
501