mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-05 04:25:29 -04:00
#323: Minor optimization + changed warning message.
This commit is contained in:
parent
ee299ee577
commit
7bed5a1c9c
@ -36,9 +36,12 @@ import javax.imageio.stream.ImageInputStreamImpl;
|
|||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static com.twelvemonkeys.lang.Validate.notNull;
|
import static com.twelvemonkeys.lang.Validate.notNull;
|
||||||
|
import static java.util.Arrays.copyOf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageInputStream implementation that filters out or rewrites
|
* ImageInputStream implementation that filters out or rewrites
|
||||||
@ -55,7 +58,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
|||||||
final private ImageInputStream stream;
|
final private ImageInputStream stream;
|
||||||
final private JPEGSegmentStreamWarningListener warningListener;
|
final private JPEGSegmentStreamWarningListener warningListener;
|
||||||
|
|
||||||
final private Set<Integer> componentIds = new LinkedHashSet<>(4);
|
final private ComponentIdSet componentIds = new ComponentIdSet();
|
||||||
|
|
||||||
private final List<Segment> segments = new ArrayList<Segment>(64);
|
private final List<Segment> segments = new ArrayList<Segment>(64);
|
||||||
private int currentSegment = -1;
|
private int currentSegment = -1;
|
||||||
@ -166,12 +169,12 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
|||||||
}
|
}
|
||||||
else if (isSOFMarker(marker)) {
|
else if (isSOFMarker(marker)) {
|
||||||
// Replace duplicate SOFn component ids
|
// Replace duplicate SOFn component ids
|
||||||
byte[] data = replaceDuplicateSOFnComponentIds(marker, length);
|
byte[] data = readReplaceDuplicateSOFnComponentIds(marker, length);
|
||||||
segment = new ReplacementSegment(marker, realPosition, segment.end(), length, data);
|
segment = new ReplacementSegment(marker, realPosition, segment.end(), length, data);
|
||||||
}
|
}
|
||||||
else if (marker == JPEG.SOS) {
|
else if (marker == JPEG.SOS) {
|
||||||
// Replace duplicate SOS component selectors
|
// Replace duplicate SOS component selectors
|
||||||
byte[] data = replaceDuplicateSOSComponentSelectors(length);
|
byte[] data = readReplaceDuplicateSOSComponentSelectors(length);
|
||||||
|
|
||||||
segment = new ReplacementSegment(marker, realPosition, segment.end(), length, data);
|
segment = new ReplacementSegment(marker, realPosition, segment.end(), length, data);
|
||||||
}
|
}
|
||||||
@ -223,18 +226,19 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
|||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] replaceDuplicateSOSComponentSelectors(long length) throws IOException {
|
private byte[] readReplaceDuplicateSOSComponentSelectors(final long length) throws IOException {
|
||||||
// See: http://www.hackerfactor.com/blog/index.php?/archives/588-JPEG-Patches.html
|
// See: http://www.hackerfactor.com/blog/index.php?/archives/588-JPEG-Patches.html
|
||||||
byte[] data = readSegment(JPEG.SOS, (int) length, stream);
|
byte[] data = readSegment(JPEG.SOS, (int) length, stream);
|
||||||
|
|
||||||
// Detect duplicates
|
// Detect duplicates
|
||||||
Set<Integer> componentSelectors = new LinkedHashSet<>(4);
|
ComponentIdSet componentSelectors = new ComponentIdSet();
|
||||||
boolean duplicatesFound = false;
|
boolean duplicatesFound = false;
|
||||||
int off = 5;
|
int off = 5;
|
||||||
|
|
||||||
while (off < length - 3) {
|
while (off < length - 3) {
|
||||||
int selector = data[off] & 0xff;
|
int selector = data[off] & 0xff;
|
||||||
if (!componentSelectors.add(selector)) {
|
if (!componentSelectors.add(selector)) {
|
||||||
processWarningOccured(String.format("Duplicate component selector %d in SOS", selector));
|
processWarningOccured(String.format("Duplicate component ID %d in SOS", selector));
|
||||||
duplicatesFound = true;
|
duplicatesFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,23 +249,19 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
|||||||
if (duplicatesFound) {
|
if (duplicatesFound) {
|
||||||
off = 5;
|
off = 5;
|
||||||
|
|
||||||
Iterator<Integer> ids = componentIds.iterator();
|
for (int i = 0; i < componentIds.size() && off < length - 3; i++, off += 2) {
|
||||||
while (off < length - 3) {
|
data[off] = (byte) componentIds.get(i);
|
||||||
if (ids.hasNext()) {
|
|
||||||
data[off] = (byte) (int) ids.next();
|
|
||||||
}
|
|
||||||
// Otherwise we'll have an undefined component selector...
|
|
||||||
|
|
||||||
off += 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] replaceDuplicateSOFnComponentIds(int marker, long length) throws IOException {
|
private byte[] readReplaceDuplicateSOFnComponentIds(final int marker, final long length) throws IOException {
|
||||||
byte[] data = readSegment(marker, (int) length, stream);
|
byte[] data = readSegment(marker, (int) length, stream);
|
||||||
|
|
||||||
int off = 10;
|
int off = 10;
|
||||||
|
|
||||||
while (off < length) {
|
while (off < length) {
|
||||||
int id = data[off] & 0xff;
|
int id = data[off] & 0xff;
|
||||||
if (!componentIds.add(id)) {
|
if (!componentIds.add(id)) {
|
||||||
@ -277,6 +277,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
|||||||
|
|
||||||
off += 3;
|
off += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,16 +494,6 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
|||||||
|
|
||||||
private static byte[] createMarkerFixedLength(final ImageInputStream stream) throws IOException {
|
private static byte[] createMarkerFixedLength(final ImageInputStream stream) throws IOException {
|
||||||
return readSegment(JPEG.APP14, 16, stream);
|
return readSegment(JPEG.APP14, 16, stream);
|
||||||
// byte[] segmentData = new byte[16];
|
|
||||||
//
|
|
||||||
// segmentData[0] = (byte) ((JPEG.APP14 >> 8) & 0xff);
|
|
||||||
// segmentData[1] = (byte) (JPEG.APP14 & 0xff);
|
|
||||||
// segmentData[2] = (byte) 0;
|
|
||||||
// segmentData[3] = (byte) 14;
|
|
||||||
//
|
|
||||||
// stream.readFully(segmentData, 4, segmentData.length - 4);
|
|
||||||
//
|
|
||||||
// return segmentData;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,4 +575,42 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final class ComponentIdSet {
|
||||||
|
final int[] values = new int[4]; // The native code don't support more than 4 components
|
||||||
|
int size;
|
||||||
|
|
||||||
|
boolean add(final int value) {
|
||||||
|
if (contains(value) || size >= values.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
values[size++] = value;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean contains(final int value) {
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
if (values[i] == value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get(final int index) {
|
||||||
|
return values[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Arrays.toString(copyOf(values, size));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1644,8 +1644,8 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
|
|
||||||
BufferedImage image = reader.read(0, null);
|
BufferedImage image = reader.read(0, null);
|
||||||
|
|
||||||
verify(listener, times(1)).warningOccurred(eq(reader), and(matches("(?i).*duplicate component id.*(?-i)SOF.*"), contains("1")));
|
verify(listener, times(1)).warningOccurred(eq(reader), and(matches("(?i).*duplicate component ID.*(?-i)SOF.*"), contains("1")));
|
||||||
verify(listener, times(1)).warningOccurred(eq(reader), and(matches("(?i).*duplicate component selector.*(?-i)SOS.*"), contains("1")));
|
verify(listener, times(1)).warningOccurred(eq(reader), and(matches("(?i).*duplicate component ID.*(?-i)SOS.*"), contains("1")));
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(367, image.getWidth());
|
assertEquals(367, image.getWidth());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user