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 
  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 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 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 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 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 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 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 
 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 
 360     public static synchronized IIOMetadataFormat getInstance() {
 361         if (theInstance == null) {
 362             theInstance = new JPEGImageMetadataFormat();
 363         }
 364         return theInstance;
 365     }
 366 }