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.ImageReadException;
029import org.apache.commons.imaging.formats.jpeg.JpegConstants;
030
031public class SofnSegment extends Segment {
032
033    private static final Logger LOGGER = Logger.getLogger(SofnSegment.class.getName());
034
035    public final int width;
036    public final int height;
037    public final int numberOfComponents;
038    public final int precision;
039    private final Component[] components;
040
041    public static class Component {
042        public final int componentIdentifier;
043        public final int horizontalSamplingFactor;
044        public final int verticalSamplingFactor;
045        public final int quantTabDestSelector;
046
047        public Component(final int componentIdentifier, final int horizontalSamplingFactor,
048                final int veritcalSamplingFactor, final int quantTabDestSelector) {
049            this.componentIdentifier = componentIdentifier;
050            this.horizontalSamplingFactor = horizontalSamplingFactor;
051            this.verticalSamplingFactor = veritcalSamplingFactor;
052            this.quantTabDestSelector = quantTabDestSelector;
053        }
054    }
055
056    public SofnSegment(final int marker, final byte[] segmentData) throws IOException, ImageReadException {
057        this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
058    }
059
060    public SofnSegment(final int marker, final int markerLength, final InputStream is)
061            throws IOException, ImageReadException {
062        super(marker, markerLength);
063
064        if (LOGGER.isLoggable(Level.FINEST)) {
065            LOGGER.finest("SOF0Segment marker_length: " + markerLength);
066        }
067
068        precision = readByte("Data_precision", is, "Not a Valid JPEG File");
069        height = read2Bytes("Image_height", is, "Not a Valid JPEG File", getByteOrder());
070        width = read2Bytes("Image_Width", is, "Not a Valid JPEG File", getByteOrder());
071        numberOfComponents = readByte("Number_of_components", is,
072                "Not a Valid JPEG File");
073        if (numberOfComponents < 0) {
074            throw new ImageReadException("The number of components in a SOF0Segment cannot be less than 0!");
075        }
076        components = new Component[numberOfComponents];
077        for (int i = 0; i < numberOfComponents; i++) {
078            final int componentIdentifier = readByte("ComponentIdentifier", is,
079                    "Not a Valid JPEG File");
080
081            final int hvSamplingFactors = readByte("SamplingFactors", is,
082                    "Not a Valid JPEG File");
083            final int horizontalSamplingFactor = (hvSamplingFactors >> 4) & 0xf;
084            final int verticalSamplingFactor = hvSamplingFactors & 0xf;
085            final int quantTabDestSelector = readByte("QuantTabDestSel", is,
086                    "Not a Valid JPEG File");
087            components[i] = new Component(componentIdentifier,
088                    horizontalSamplingFactor, verticalSamplingFactor,
089                    quantTabDestSelector);
090        }
091    }
092
093    /**
094     * Returns a copy of all the components.
095     * @return the components
096     */
097    public Component[] getComponents() {
098        return components.clone();
099    }
100
101    /**
102     * Returns the component at the specified index.
103     * @param index the array index
104     * @return the component
105     */
106    public Component getComponents(final int index) {
107        return components[index];
108    }
109
110
111    @Override
112    public String getDescription() {
113        return "SOFN (SOF" + (marker - JpegConstants.SOF0_MARKER) + ") ("
114                + getSegmentType() + ")";
115    }
116
117}