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 import javax.imageio.plugins.jpeg.JPEGQTable;
32 import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
33 
34 import java.util.List;
35 import java.util.ArrayList;
36 
37 abstract class JPEGMetadataFormat extends IIOMetadataFormatImpl {
38     // 2-byte length reduces max to 65533
39     private static final int MAX_JPEG_DATA_SIZE = 65533;
40 
41     String resourceBaseName = this.getClass().getName() + "Resources";
42 
JPEGMetadataFormat(String formatName, int childPolicy)43     JPEGMetadataFormat(String formatName, int childPolicy) {
44         super(formatName, childPolicy);
45         setResourceBaseName(resourceBaseName);
46     }
47 
48     // Format shared between image and stream formats
addStreamElements(String parentName)49     void addStreamElements(String parentName) {
50         addElement("dqt", parentName, 1, 4);
51 
52         addElement("dqtable", "dqt", CHILD_POLICY_EMPTY);
53 
54         addAttribute("dqtable",
55                      "elementPrecision",
56                      DATATYPE_INTEGER,
57                      false,
58                      "0");
59         List<String> tabids = new ArrayList<>();
60         tabids.add("0");
61         tabids.add("1");
62         tabids.add("2");
63         tabids.add("3");
64         addAttribute("dqtable",
65                      "qtableId",
66                      DATATYPE_INTEGER,
67                      true,
68                      null,
69                      tabids);
70         addObjectValue("dqtable",
71                        JPEGQTable.class,
72                        true,
73                        null);
74 
75         addElement("dht", parentName, 1, 4);
76         addElement("dhtable", "dht", CHILD_POLICY_EMPTY);
77         List<String> classes = new ArrayList<>();
78         classes.add("0");
79         classes.add("1");
80         addAttribute("dhtable",
81                      "class",
82                      DATATYPE_INTEGER,
83                      true,
84                      null,
85                      classes);
86         addAttribute("dhtable",
87                      "htableId",
88                      DATATYPE_INTEGER,
89                      true,
90                      null,
91                      tabids);
92         addObjectValue("dhtable",
93                        JPEGHuffmanTable.class,
94                        true,
95                        null);
96 
97 
98         addElement("dri", parentName, CHILD_POLICY_EMPTY);
99         addAttribute("dri",
100                      "interval",
101                      DATATYPE_INTEGER,
102                      true,
103                      null,
104                      "0", "65535",
105                      true, true);
106 
107         addElement("com", parentName, CHILD_POLICY_EMPTY);
108         addAttribute("com",
109                      "comment",
110                      DATATYPE_STRING,
111                      false,
112                      null);
113         addObjectValue("com", byte[].class, 1, MAX_JPEG_DATA_SIZE);
114 
115         addElement("unknown", parentName, CHILD_POLICY_EMPTY);
116         addAttribute("unknown",
117                      "MarkerTag",
118                      DATATYPE_INTEGER,
119                      true,
120                      null,
121                      "0", "255",
122                      true, true);
123         addObjectValue("unknown", byte[].class, 1, MAX_JPEG_DATA_SIZE);
124     }
125 
canNodeAppear(String elementName, ImageTypeSpecifier imageType)126     public boolean canNodeAppear(String elementName,
127                                  ImageTypeSpecifier imageType) {
128         // Just check if it appears in the format
129         if (isInSubtree(elementName, getRootName())){
130             return true;
131         }
132         return false;
133     }
134 
135     /**
136      * Returns {@code true} if the named element occurs in the
137      * subtree of the format starting with the node named by
138      * {@code subtreeName}, including the node
139      * itself.  {@code subtreeName} may be any node in
140      * the format.  If it is not, an
141      * {@code IllegalArgumentException} is thrown.
142      */
isInSubtree(String elementName, String subtreeName)143     protected boolean isInSubtree(String elementName,
144                                   String subtreeName) {
145         if (elementName.equals(subtreeName)) {
146             return true;
147         }
148         String [] children = getChildNames(elementName);
149         for (int i=0; i < children.length; i++) {
150             if (isInSubtree(elementName, children[i])) {
151                 return true;
152             }
153         }
154         return false;
155     }
156 
157 }
158