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}