1 /*
2  * Copyright (c) 2001, 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.jpeg;
27 
28 import javax.imageio.metadata.IIOMetadataFormat;
29 import javax.imageio.metadata.IIOMetadataFormatImpl;
30 import javax.imageio.ImageTypeSpecifier;
31 
32 import java.awt.color.ICC_Profile;
33 import java.awt.color.ColorSpace;
34 import java.awt.image.ColorModel;
35 
36 import java.util.List;
37 import java.util.ArrayList;
38 
39 public class JPEGImageMetadataFormat extends JPEGMetadataFormat {
40 
41     private static JPEGImageMetadataFormat theInstance = null;
42 
JPEGImageMetadataFormat()43     private JPEGImageMetadataFormat() {
44         super(JPEG.nativeImageMetadataFormatName,
45               CHILD_POLICY_ALL);
46 
47         addElement("JPEGvariety",
48                    JPEG.nativeImageMetadataFormatName,
49                    CHILD_POLICY_CHOICE);
50 
51         addElement("markerSequence",
52                    JPEG.nativeImageMetadataFormatName,
53                    CHILD_POLICY_SEQUENCE);
54 
55         addElement("app0JFIF", "JPEGvariety", CHILD_POLICY_SOME);
56 
57         addStreamElements("markerSequence");
58 
59         addElement("app14Adobe", "markerSequence", CHILD_POLICY_EMPTY);
60 
61         addElement("sof", "markerSequence", 1, 4);
62 
63         addElement("sos", "markerSequence", 1, 4);
64 
65         addElement("JFXX", "app0JFIF", 1, Integer.MAX_VALUE);
66 
67         addElement("app0JFXX", "JFXX", CHILD_POLICY_CHOICE);
68 
69         addElement("app2ICC", "app0JFIF", CHILD_POLICY_EMPTY);
70 
71         addAttribute("app0JFIF",
72                      "majorVersion",
73                      DATATYPE_INTEGER,
74                      false,
75                      "1",
76                      "0", "255",
77                      true, true);
78         addAttribute("app0JFIF",
79                      "minorVersion",
80                      DATATYPE_INTEGER,
81                      false,
82                      "2",
83                      "0", "255",
84                      true, true);
85         List<String> resUnits = new ArrayList<>();
86         resUnits.add("0");
87         resUnits.add("1");
88         resUnits.add("2");
89         addAttribute("app0JFIF",
90                      "resUnits",
91                      DATATYPE_INTEGER,
92                      false,
93                      "0",
94                      resUnits);
95         addAttribute("app0JFIF",
96                      "Xdensity",
97                      DATATYPE_INTEGER,
98                      false,
99                      "1",
100                      "1", "65535",
101                      true, true);
102         addAttribute("app0JFIF",
103                      "Ydensity",
104                      DATATYPE_INTEGER,
105                      false,
106                      "1",
107                      "1", "65535",
108                      true, true);
109         addAttribute("app0JFIF",
110                      "thumbWidth",
111                      DATATYPE_INTEGER,
112                      false,
113                      "0",
114                      "0", "255",
115                      true, true);
116         addAttribute("app0JFIF",
117                      "thumbHeight",
118                      DATATYPE_INTEGER,
119                      false,
120                      "0",
121                      "0", "255",
122                      true, true);
123 
124         addElement("JFIFthumbJPEG", "app0JFXX", CHILD_POLICY_SOME);
125         addElement("JFIFthumbPalette", "app0JFXX", CHILD_POLICY_EMPTY);
126         addElement("JFIFthumbRGB", "app0JFXX", CHILD_POLICY_EMPTY);
127 
128         List<String> codes = new ArrayList<>();
129         codes.add("16"); // Hex 10
130         codes.add("17"); // Hex 11
131         codes.add("19"); // Hex 13
132         addAttribute("app0JFXX",
133                      "extensionCode",
134                      DATATYPE_INTEGER,
135                      false,
136                      null,
137                      codes);
138 
139         addChildElement("markerSequence", "JFIFthumbJPEG");
140 
141         addAttribute("JFIFthumbPalette",
142                      "thumbWidth",
143                      DATATYPE_INTEGER,
144                      false,
145                      null,
146                      "0", "255",
147                      true, true);
148         addAttribute("JFIFthumbPalette",
149                      "thumbHeight",
150                      DATATYPE_INTEGER,
151                      false,
152                      null,
153                      "0", "255",
154                      true, true);
155 
156         addAttribute("JFIFthumbRGB",
157                      "thumbWidth",
158                      DATATYPE_INTEGER,
159                      false,
160                      null,
161                      "0", "255",
162                      true, true);
163         addAttribute("JFIFthumbRGB",
164                      "thumbHeight",
165                      DATATYPE_INTEGER,
166                      false,
167                      null,
168                      "0", "255",
169                      true, true);
170 
171         addObjectValue("app2ICC", ICC_Profile.class, false, null);
172 
173         addAttribute("app14Adobe",
174                      "version",
175                      DATATYPE_INTEGER,
176                      false,
177                      "100",
178                      "100", "255",
179                      true, true);
180         addAttribute("app14Adobe",
181                      "flags0",
182                      DATATYPE_INTEGER,
183                      false,
184                      "0",
185                      "0", "65535",
186                      true, true);
187         addAttribute("app14Adobe",
188                      "flags1",
189                      DATATYPE_INTEGER,
190                      false,
191                      "0",
192                      "0", "65535",
193                      true, true);
194 
195         List<String> transforms = new ArrayList<>();
196         transforms.add("0");
197         transforms.add("1");
198         transforms.add("2");
199         addAttribute("app14Adobe",
200                      "transform",
201                      DATATYPE_INTEGER,
202                      true,
203                      null,
204                      transforms);
205 
206         addElement("componentSpec", "sof", CHILD_POLICY_EMPTY);
207 
208         List<String> procs = new ArrayList<>();
209         procs.add("0");
210         procs.add("1");
211         procs.add("2");
212         addAttribute("sof",
213                      "process",
214                      DATATYPE_INTEGER,
215                      false,
216                      null,
217                      procs);
218         addAttribute("sof",
219                      "samplePrecision",
220                      DATATYPE_INTEGER,
221                      false,
222                      "8");
223         addAttribute("sof",
224                      "numLines",
225                      DATATYPE_INTEGER,
226                      false,
227                      null,
228                      "0", "65535",
229                      true, true);
230         addAttribute("sof",
231                      "samplesPerLine",
232                      DATATYPE_INTEGER,
233                      false,
234                      null,
235                      "0", "65535",
236                      true, true);
237         List<String> comps = new ArrayList<>();
238         comps.add("1");
239         comps.add("2");
240         comps.add("3");
241         comps.add("4");
242         addAttribute("sof",
243                      "numFrameComponents",
244                      DATATYPE_INTEGER,
245                      false,
246                      null,
247                      comps);
248 
249         addAttribute("componentSpec",
250                      "componentId",
251                      DATATYPE_INTEGER,
252                      true,
253                      null,
254                      "0", "255",
255                      true, true);
256         addAttribute("componentSpec",
257                      "HsamplingFactor",
258                      DATATYPE_INTEGER,
259                      true,
260                      null,
261                      "1", "255",
262                      true, true);
263         addAttribute("componentSpec",
264                      "VsamplingFactor",
265                      DATATYPE_INTEGER,
266                      true,
267                      null,
268                      "1", "255",
269                      true, true);
270         List<String> tabids = new ArrayList<>();
271         tabids.add("0");
272         tabids.add("1");
273         tabids.add("2");
274         tabids.add("3");
275         addAttribute("componentSpec",
276                      "QtableSelector",
277                      DATATYPE_INTEGER,
278                      true,
279                      null,
280                      tabids);
281 
282         addElement("scanComponentSpec", "sos", CHILD_POLICY_EMPTY);
283 
284         addAttribute("sos",
285                      "numScanComponents",
286                      DATATYPE_INTEGER,
287                      true,
288                      null,
289                      comps);
290         addAttribute("sos",
291                      "startSpectralSelection",
292                       DATATYPE_INTEGER,
293                      false,
294                      "0",
295                      "0", "63",
296                      true, true);
297         addAttribute("sos",
298                      "endSpectralSelection",
299                       DATATYPE_INTEGER,
300                      false,
301                      "63",
302                      "0", "63",
303                      true, true);
304         addAttribute("sos",
305                      "approxHigh",
306                       DATATYPE_INTEGER,
307                      false,
308                      "0",
309                      "0", "15",
310                      true, true);
311         addAttribute("sos",
312                      "approxLow",
313                       DATATYPE_INTEGER,
314                      false,
315                      "0",
316                      "0", "15",
317                      true, true);
318 
319         addAttribute("scanComponentSpec",
320                      "componentSelector",
321                      DATATYPE_INTEGER,
322                      true,
323                      null,
324                      "0", "255",
325                      true, true);
326         addAttribute("scanComponentSpec",
327                      "dcHuffTable",
328                      DATATYPE_INTEGER,
329                      true,
330                      null,
331                      tabids);
332         addAttribute("scanComponentSpec",
333                      "acHuffTable",
334                      DATATYPE_INTEGER,
335                      true,
336                      null,
337                      tabids);
338     }
339 
canNodeAppear(String elementName, ImageTypeSpecifier imageType)340     public boolean canNodeAppear(String elementName,
341                                  ImageTypeSpecifier imageType) {
342         // All images can have these
343         if (elementName.equals(getRootName())
344             || elementName.equals("JPEGvariety")
345             || isInSubtree(elementName, "markerSequence")) {
346             return true;
347         }
348 
349         // If it is an element in the app0jfif subtree, just check
350         // that the image type is JFIF compliant.
351         if ((isInSubtree(elementName, "app0JFIF"))
352             && JPEG.isJFIFcompliant(imageType, true)) {
353             return true;
354         }
355 
356         return false;
357     }
358 
359 
getInstance()360     public static synchronized IIOMetadataFormat getInstance() {
361         if (theInstance == null) {
362             theInstance = new JPEGImageMetadataFormat();
363         }
364         return theInstance;
365     }
366 }
367