View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.imaging.formats.jpeg.segments;
18  
19  import static org.apache.commons.imaging.common.BinaryFunctions.read2Bytes;
20  import static org.apache.commons.imaging.common.BinaryFunctions.readByte;
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.util.logging.Level;
26  import java.util.logging.Logger;
27  
28  import org.apache.commons.imaging.ImagingException;
29  import org.apache.commons.imaging.common.Allocator;
30  import org.apache.commons.imaging.formats.jpeg.JpegConstants;
31  
32  public final class SofnSegment extends AbstractSegment {
33  
34      public static class Component {
35          static final int SHALLOW_SIZE = 32;
36          public final int componentIdentifier;
37          public final int horizontalSamplingFactor;
38          public final int verticalSamplingFactor;
39          public final int quantTabDestSelector;
40  
41          public Component(final int componentIdentifier, final int horizontalSamplingFactor, final int veritcalSamplingFactor, final int quantTabDestSelector) {
42              this.componentIdentifier = componentIdentifier;
43              this.horizontalSamplingFactor = horizontalSamplingFactor;
44              this.verticalSamplingFactor = veritcalSamplingFactor;
45              this.quantTabDestSelector = quantTabDestSelector;
46          }
47      }
48  
49      private static final Logger LOGGER = Logger.getLogger(SofnSegment.class.getName());
50      public final int width;
51      public final int height;
52      public final int numberOfComponents;
53      public final int precision;
54  
55      private final Component[] components;
56  
57      public SofnSegment(final int marker, final byte[] segmentData) throws IOException, ImagingException {
58          this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
59      }
60  
61      public SofnSegment(final int marker, final int markerLength, final InputStream is) throws IOException, ImagingException {
62          super(marker, markerLength);
63  
64          if (LOGGER.isLoggable(Level.FINEST)) {
65              LOGGER.finest("SOF0Segment markerLength: " + markerLength);
66          }
67  
68          precision = readByte("precision", is, "Not a Valid JPEG File");
69          height = read2Bytes("height", is, "Not a Valid JPEG File", getByteOrder());
70          width = read2Bytes("width", is, "Not a Valid JPEG File", getByteOrder());
71          numberOfComponents = readByte("numberOfComponents", is, "Not a Valid JPEG File");
72          if (numberOfComponents < 0) {
73              throw new ImagingException("The number of components in a SOF0Segment cannot be less than 0!");
74          }
75          components = Allocator.array(numberOfComponents, Component[]::new, Component.SHALLOW_SIZE);
76          for (int i = 0; i < numberOfComponents; i++) {
77              final int componentIdentifier = readByte("ComponentIdentifier", is, "Not a Valid JPEG File");
78  
79              final int hvSamplingFactors = readByte("SamplingFactors", is, "Not a Valid JPEG File");
80              final int horizontalSamplingFactor = hvSamplingFactors >> 4 & 0xf;
81              final int verticalSamplingFactor = hvSamplingFactors & 0xf;
82              final int quantTabDestSelector = readByte("QuantTabDestSel", is, "Not a Valid JPEG File");
83              components[i] = new Component(componentIdentifier, horizontalSamplingFactor, verticalSamplingFactor, quantTabDestSelector);
84          }
85      }
86  
87      /**
88       * Returns a copy of all the components.
89       *
90       * @return the components
91       */
92      public Component[] getComponents() {
93          return components.clone();
94      }
95  
96      /**
97       * Returns the component at the specified index.
98       *
99       * @param index the array index
100      * @return the component
101      */
102     public Component getComponents(final int index) {
103         return components[index];
104     }
105 
106     @Override
107     public String getDescription() {
108         return "SOFN (SOF" + (marker - JpegConstants.SOF0_MARKER) + ") (" + getSegmentType() + ")";
109     }
110 
111 }