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