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.readByte;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.logging.Level;
25  import java.util.logging.Logger;
26  
27  import org.apache.commons.imaging.common.Allocator;
28  
29  public class SosSegment extends AbstractSegment {
30  
31      public static class Component {
32          static final int SHALLOW_SIZE = 24;
33          public final int scanComponentSelector;
34          public final int dcCodingTableSelector;
35          public final int acCodingTableSelector;
36  
37          public Component(final int scanComponentSelector, final int dcCodingTableSelector, final int acCodingTableSelector) {
38              this.scanComponentSelector = scanComponentSelector;
39              this.dcCodingTableSelector = dcCodingTableSelector;
40              this.acCodingTableSelector = acCodingTableSelector;
41          }
42      }
43  
44      private static final Logger LOGGER = Logger.getLogger(SosSegment.class.getName());
45      public final int numberOfComponents;
46      private final Component[] components;
47      public final int startOfSpectralSelection;
48      public final int endOfSpectralSelection;
49      public final int successiveApproximationBitHigh;
50  
51      public final int successiveApproximationBitLow;
52  
53      public SosSegment(final int marker, final byte[] segmentData) throws IOException {
54          this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
55      }
56  
57      public SosSegment(final int marker, final int markerLength, final InputStream is) throws IOException {
58          super(marker, markerLength);
59  
60          if (LOGGER.isLoggable(Level.FINEST)) {
61              LOGGER.finest("SosSegment markerLength: " + markerLength);
62          }
63  
64          // Debug.debug("SOS", marker_length);
65  
66          numberOfComponents = readByte("numberOfComponents", is, "Not a Valid JPEG File");
67          // Debug.debug("number_of_components_in_scan",
68          // numberOfComponents);
69  
70          components = Allocator.array(numberOfComponents, Component[]::new, Component.SHALLOW_SIZE);
71          for (int i = 0; i < numberOfComponents; i++) {
72              final int scanComponentSelector = readByte("scanComponentSelector", is, "Not a Valid JPEG File");
73              // Debug.debug("scanComponentSelector", scanComponentSelector);
74  
75              final int acDcEntropyCodingTableSelector = readByte("acDcEntropyCodingTableSelector", is, "Not a Valid JPEG File");
76              // Debug.debug("ac_dc_entrooy_coding_table_selector",
77              // acDcEntropyCodingTableSelector);
78  
79              final int dcCodingTableSelector = acDcEntropyCodingTableSelector >> 4 & 0xf;
80              final int acCodingTableSelector = acDcEntropyCodingTableSelector & 0xf;
81              components[i] = new Component(scanComponentSelector, dcCodingTableSelector, acCodingTableSelector);
82          }
83  
84          startOfSpectralSelection = readByte("startOfSpectralSelection", is, "Not a Valid JPEG File");
85          // Debug.debug("start_of_spectral_selection", startOfSpectralSelection);
86          endOfSpectralSelection = readByte("endOfSpectralSelection", is, "Not a Valid JPEG File");
87          // Debug.debug("end_of_spectral_selection", endOfSpectralSelection);
88          final int successiveApproximationBitPosition = readByte("successiveApproximationBitPosition", is, "Not a Valid JPEG File");
89          // Debug.debug("successive_approximation_bit_position",
90          // successive_approximation_bit_position);
91          successiveApproximationBitHigh = successiveApproximationBitPosition >> 4 & 0xf;
92          successiveApproximationBitLow = successiveApproximationBitPosition & 0xf;
93      }
94  
95      /**
96       * Returns a copy of all the components.
97       *
98       * @return all the components
99       */
100     public Component[] getComponents() {
101         return components.clone();
102     }
103 
104     /**
105      * Gets a component at the specified index.
106      *
107      * @param index the component index
108      * @return the component
109      */
110     public Component getComponents(final int index) {
111         return components[index];
112     }
113 
114     @Override
115     public String getDescription() {
116         return "SOS (" + getSegmentType() + ")";
117     }
118 
119 }