1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.formats.jpeg.segments;
18
19 import static org.apache.commons.imaging.common.BinaryFunctions.read2Bytes;
20 import static org.apache.commons.imaging.common.BinaryFunctions.readByte;
21
22 import java.io.ByteArrayInputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27
28 import org.apache.commons.imaging.ImagingException;
29 import org.apache.commons.imaging.common.Allocator;
30 import org.apache.commons.imaging.formats.jpeg.JpegConstants;
31
32 public final class SofnSegment extends AbstractSegment {
33
34 public static class Component {
35 static final int SHALLOW_SIZE = 32;
36 public final int componentIdentifier;
37 public final int horizontalSamplingFactor;
38 public final int verticalSamplingFactor;
39 public final int quantTabDestSelector;
40
41 public Component(final int componentIdentifier, final int horizontalSamplingFactor, final int veritcalSamplingFactor, final int quantTabDestSelector) {
42 this.componentIdentifier = componentIdentifier;
43 this.horizontalSamplingFactor = horizontalSamplingFactor;
44 this.verticalSamplingFactor = veritcalSamplingFactor;
45 this.quantTabDestSelector = quantTabDestSelector;
46 }
47 }
48
49 private static final Logger LOGGER = Logger.getLogger(SofnSegment.class.getName());
50 public final int width;
51 public final int height;
52 public final int numberOfComponents;
53 public final int precision;
54
55 private final Component[] components;
56
57 public SofnSegment(final int marker, final byte[] segmentData) throws IOException, ImagingException {
58 this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
59 }
60
61 public SofnSegment(final int marker, final int markerLength, final InputStream is) throws IOException, ImagingException {
62 super(marker, markerLength);
63
64 if (LOGGER.isLoggable(Level.FINEST)) {
65 LOGGER.finest("SOF0Segment markerLength: " + markerLength);
66 }
67
68 precision = readByte("precision", is, "Not a Valid JPEG File");
69 height = read2Bytes("height", is, "Not a Valid JPEG File", getByteOrder());
70 width = read2Bytes("width", is, "Not a Valid JPEG File", getByteOrder());
71 numberOfComponents = readByte("numberOfComponents", is, "Not a Valid JPEG File");
72 if (numberOfComponents < 0) {
73 throw new ImagingException("The number of components in a SOF0Segment cannot be less than 0!");
74 }
75 components = Allocator.array(numberOfComponents, Component[]::new, Component.SHALLOW_SIZE);
76 for (int i = 0; i < numberOfComponents; i++) {
77 final int componentIdentifier = readByte("ComponentIdentifier", is, "Not a Valid JPEG File");
78
79 final int hvSamplingFactors = readByte("SamplingFactors", is, "Not a Valid JPEG File");
80 final int horizontalSamplingFactor = hvSamplingFactors >> 4 & 0xf;
81 final int verticalSamplingFactor = hvSamplingFactors & 0xf;
82 final int quantTabDestSelector = readByte("QuantTabDestSel", is, "Not a Valid JPEG File");
83 components[i] = new Component(componentIdentifier, horizontalSamplingFactor, verticalSamplingFactor, quantTabDestSelector);
84 }
85 }
86
87
88
89
90
91
92 public Component[] getComponents() {
93 return components.clone();
94 }
95
96
97
98
99
100
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 }