001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.imaging.formats.jpeg.segments;
018
019import static org.apache.commons.imaging.common.BinaryFunctions.read2Bytes;
020import static org.apache.commons.imaging.common.BinaryFunctions.readByte;
021
022import java.io.ByteArrayInputStream;
023import java.io.IOException;
024import java.io.InputStream;
025import java.util.logging.Level;
026import java.util.logging.Logger;
027
028import org.apache.commons.imaging.formats.jpeg.JpegConstants;
029
030public class SofnSegment extends Segment {
031
032    private static final Logger LOGGER = Logger.getLogger(SofnSegment.class.getName());
033
034    public final int width;
035    public final int height;
036    public final int numberOfComponents;
037    public final int precision;
038    private final Component[] components;
039
040    public static class Component {
041        public final int componentIdentifier;
042        public final int horizontalSamplingFactor;
043        public final int verticalSamplingFactor;
044        public final int quantTabDestSelector;
045
046        public Component(final int componentIdentifier, final int horizontalSamplingFactor,
047                final int veritcalSamplingFactor, final int quantTabDestSelector) {
048            this.componentIdentifier = componentIdentifier;
049            this.horizontalSamplingFactor = horizontalSamplingFactor;
050            this.verticalSamplingFactor = veritcalSamplingFactor;
051            this.quantTabDestSelector = quantTabDestSelector;
052        }
053    }
054
055    public SofnSegment(final int marker, final byte[] segmentData) throws IOException {
056        this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
057    }
058
059    public SofnSegment(final int marker, final int markerLength, final InputStream is)
060            throws IOException {
061        super(marker, markerLength);
062
063        if (LOGGER.isLoggable(Level.FINEST)) {
064            LOGGER.finest("SOF0Segment marker_length: " + markerLength);
065        }
066
067        precision = readByte("Data_precision", is, "Not a Valid JPEG File");
068        height = read2Bytes("Image_height", is, "Not a Valid JPEG File", getByteOrder());
069        width = read2Bytes("Image_Width", is, "Not a Valid JPEG File", getByteOrder());
070        numberOfComponents = readByte("Number_of_components", is,
071                "Not a Valid JPEG File");
072        components = new Component[numberOfComponents];
073        for (int i = 0; i < numberOfComponents; i++) {
074            final int componentIdentifier = readByte("ComponentIdentifier", is,
075                    "Not a Valid JPEG File");
076
077            final int hvSamplingFactors = readByte("SamplingFactors", is,
078                    "Not a Valid JPEG File");
079            final int horizontalSamplingFactor = (hvSamplingFactors >> 4) & 0xf;
080            final int verticalSamplingFactor = hvSamplingFactors & 0xf;
081            final int quantTabDestSelector = readByte("QuantTabDestSel", is,
082                    "Not a Valid JPEG File");
083            components[i] = new Component(componentIdentifier,
084                    horizontalSamplingFactor, verticalSamplingFactor,
085                    quantTabDestSelector);
086        }
087    }
088
089    /**
090     * Returns a copy of all the components.
091     * @return the components
092     */
093    public Component[] getComponents() {
094        return components.clone();
095    }
096
097    /**
098     * Returns the component at the specified index.
099     * @param index the array index
100     * @return the component
101     */
102    public Component getComponents(final int index) {
103        return components[index];
104    }
105
106
107    @Override
108    public String getDescription() {
109        return "SOFN (SOF" + (marker - JpegConstants.SOF0_MARKER) + ") ("
110                + getSegmentType() + ")";
111    }
112
113}