mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-27 18:50:07 +00:00
8154058: [TIFF] ignoreMetadata parameter of TIFFImageReader's setInput() method affects TIFFImageReadParam in non-obvious way
Add readUnknownTags to TIFFImageReadParam and add ReadParamTest Reviewed-by: prr
This commit is contained in:
parent
a4865ea66a
commit
bcfb267efe
@ -541,10 +541,10 @@ public class TIFFIFD extends TIFFDirectory {
|
||||
}
|
||||
|
||||
// Stream position initially at beginning, left at end
|
||||
// if ignoreUnknownFields is true, do not load fields for which
|
||||
// if readUnknownTags is false, do not load fields for which
|
||||
// a tag cannot be found in an allowed TagSet.
|
||||
public void initialize(ImageInputStream stream, boolean isPrimaryIFD,
|
||||
boolean ignoreUnknownFields) throws IOException {
|
||||
boolean ignoreMetadata, boolean readUnknownTags) throws IOException {
|
||||
|
||||
removeTIFFFields();
|
||||
|
||||
@ -553,10 +553,16 @@ public class TIFFIFD extends TIFFDirectory {
|
||||
|
||||
List<TIFFTagSet> tagSetList = getTagSetList();
|
||||
|
||||
// Configure essential tag variables if this is the primary IFD and
|
||||
// either all metadata are being ignored, or metadata are not being
|
||||
// ignored but both unknown tags are being ignored and the tag set
|
||||
// list does not contain the baseline tags.
|
||||
boolean ensureEssentialTags = false;
|
||||
TIFFTagSet baselineTagSet = null;
|
||||
if (isPrimaryIFD && ignoreUnknownFields
|
||||
&& !tagSetList.contains(BaselineTIFFTagSet.getInstance())) {
|
||||
if (isPrimaryIFD &&
|
||||
(ignoreMetadata ||
|
||||
(!readUnknownTags &&
|
||||
!tagSetList.contains(BaselineTIFFTagSet.getInstance())))) {
|
||||
ensureEssentialTags = true;
|
||||
initializeEssentialTags();
|
||||
baselineTagSet = BaselineTIFFTagSet.getInstance();
|
||||
@ -590,9 +596,12 @@ public class TIFFIFD extends TIFFDirectory {
|
||||
tag = baselineTagSet.getTag(tagNumber);
|
||||
}
|
||||
|
||||
// Ignore unknown fields, fields with unknown type, and fields
|
||||
// Ignore non-essential fields, unknown fields unless forcibly
|
||||
// being read, fields with unknown type, and fields
|
||||
// with count out of int range.
|
||||
if((tag == null && ignoreUnknownFields)
|
||||
if((ignoreMetadata &&
|
||||
(!ensureEssentialTags || !essentialTags.contains(tagNumber)))
|
||||
|| (tag == null && !readUnknownTags)
|
||||
|| (tag != null && !tag.isDataTypeOK(type))
|
||||
|| longCount > Integer.MAX_VALUE) {
|
||||
// Skip the value/offset so as to leave the stream
|
||||
@ -701,7 +710,8 @@ public class TIFFIFD extends TIFFDirectory {
|
||||
tagSets.add(tag.getTagSet());
|
||||
TIFFIFD subIFD = new TIFFIFD(tagSets);
|
||||
|
||||
subIFD.initialize(stream, false, ignoreUnknownFields);
|
||||
subIFD.initialize(stream, false, ignoreMetadata,
|
||||
readUnknownTags);
|
||||
TIFFField f = new TIFFField(tag, type, e.offset, subIFD);
|
||||
addTIFFField(f);
|
||||
} else {
|
||||
|
||||
@ -82,9 +82,10 @@ public class TIFFImageMetadata extends IIOMetadata {
|
||||
}
|
||||
|
||||
public void initializeFromStream(ImageInputStream stream,
|
||||
boolean ignoreUnknownFields)
|
||||
boolean ignoreMetadata,
|
||||
boolean readUnknownTags)
|
||||
throws IOException {
|
||||
rootIFD.initialize(stream, true, ignoreUnknownFields);
|
||||
rootIFD.initialize(stream, true, ignoreMetadata, readUnknownTags);
|
||||
}
|
||||
|
||||
public void addShortOrLongField(int tagNumber, long value) {
|
||||
|
||||
@ -305,16 +305,19 @@ public class TIFFImageReader extends ImageReader {
|
||||
try {
|
||||
// Create an object to store the image metadata
|
||||
List<TIFFTagSet> tagSets;
|
||||
boolean readUnknownTags = false;
|
||||
if (imageReadParam instanceof TIFFImageReadParam) {
|
||||
tagSets
|
||||
= ((TIFFImageReadParam) imageReadParam).getAllowedTagSets();
|
||||
TIFFImageReadParam tp = (TIFFImageReadParam)imageReadParam;
|
||||
tagSets = tp.getAllowedTagSets();
|
||||
readUnknownTags = tp.getReadUnknownTags();
|
||||
} else {
|
||||
tagSets = new ArrayList<TIFFTagSet>(1);
|
||||
tagSets.add(BaselineTIFFTagSet.getInstance());
|
||||
}
|
||||
|
||||
this.imageMetadata = new TIFFImageMetadata(tagSets);
|
||||
imageMetadata.initializeFromStream(stream, ignoreMetadata);
|
||||
imageMetadata.initializeFromStream(stream, ignoreMetadata,
|
||||
readUnknownTags);
|
||||
} catch (IIOException iioe) {
|
||||
throw iioe;
|
||||
} catch (IOException ioe) {
|
||||
|
||||
@ -3015,7 +3015,7 @@ public class TIFFImageWriter extends ImageWriter {
|
||||
List<TIFFTagSet> tagSets = new ArrayList<TIFFTagSet>(1);
|
||||
tagSets.add(BaselineTIFFTagSet.getInstance());
|
||||
TIFFIFD rootIFD = new TIFFIFD(tagSets);
|
||||
rootIFD.initialize(stream, true, true);
|
||||
rootIFD.initialize(stream, true, false, false);
|
||||
stream.reset();
|
||||
|
||||
return rootIFD;
|
||||
|
||||
@ -216,22 +216,27 @@ second on the inferred color space.</p>
|
||||
|
||||
<h4><a name="MetadataIssuesRead"/>Metadata Issues</h4>
|
||||
|
||||
By default all fields in the TIFF image file directory (IFD) are loaded into
|
||||
the native image metadata object. In cases where the IFD includes fields which
|
||||
contain large amounts of data this could be very inefficient. Which fields
|
||||
are loaded may be controlled by setting which TIFF tags the reader is allowed
|
||||
to recognize and whether it is ignoring metadata. The reader is informed to
|
||||
disregard metadata as usual via the <code>ignoreMetadata</code> parameter of
|
||||
By default all recognized fields in the TIFF image file directory (IFD) are
|
||||
loaded into the native image metadata object. Which fields are loaded may be
|
||||
controlled by setting which TIFF tags the reader is allowed to recognize,
|
||||
whether to read fields with unrecognized tags, and whether to ignore all
|
||||
metadata. The reader is informed to disregard all metadata as usual via the
|
||||
<code>ignoreMetadata</code> parameter of
|
||||
<code>ImageReader.setInput(Object,boolean,boolean)</code>. It is
|
||||
informed of which <a href="../../plugins/tiff/TIFFTag.html">TIFFTag</a>s to
|
||||
recognize or not to recognize via
|
||||
<code>TIFFImageReadParam.addAllowedTagSet(TIFFTagSet)</code>
|
||||
and
|
||||
<code>TIFFImageReadParam.addAllowedTagSet(TIFFTagSet)</code> and
|
||||
<code>TIFFImageReadParam.removeAllowedTagSet(TIFFTagSet)</code>.
|
||||
If <code>ignoreMetadata</code> is <code>true</code>, then the reader will
|
||||
load into the native image metadata object only those fields which have a
|
||||
<code>TIFFTag</code> contained in the one of the allowed
|
||||
<code>TIFFTagSet</code>s.
|
||||
If <code>ignoreMetadata</code> is <code>true</code>, then only metadata
|
||||
essential to reading the image will be loaded into the native image metadata
|
||||
object. If <code>ignoreMetadata</code> is <code>false</code>, then the reader
|
||||
will by default load into the native image metadata object only those fields
|
||||
which are either essential to reading the image or have a <code>TIFFTag</code>
|
||||
contained in the one of the allowed <code>TIFFTagSet</code>s. Reading of
|
||||
fields with tags not in the allowed <code>TIFFTagSet</code>s may be forced
|
||||
by passing in a <code>TIFFImageReadParam</code> on which
|
||||
<code>TIFFImageReadParam.setReadUnknownTags(boolean)</code> has been
|
||||
invoked with parameter <code>true</code>.
|
||||
|
||||
<p>Use of a <a href="../../plugins/tiff/TIFFDirectory.html">TIFFDirectory</a>
|
||||
object may simplify gaining access to metadata values. An instance of
|
||||
|
||||
@ -46,6 +46,10 @@ import javax.imageio.ImageReadParam;
|
||||
* {@code ExifParentTIFFTagSet}, and {@code GeoTIFFTagSet}
|
||||
* are included.
|
||||
*
|
||||
* <p> Forcing reading of fields corresponding to {@code TIFFTag}s
|
||||
* not in any of the allowed {@code TIFFTagSet}s may be effected via
|
||||
* {@link #setReadUnknownTags setReadUnknownTags}.
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
public final class TIFFImageReadParam extends ImageReadParam {
|
||||
@ -53,6 +57,8 @@ public final class TIFFImageReadParam extends ImageReadParam {
|
||||
private final List<TIFFTagSet> allowedTagSets =
|
||||
new ArrayList<TIFFTagSet>(4);
|
||||
|
||||
private boolean readUnknownTags = false;
|
||||
|
||||
/**
|
||||
* Constructs a {@code TIFFImageReadParam}. Tags defined by
|
||||
* the {@code TIFFTagSet}s {@code BaselineTIFFTagSet},
|
||||
@ -117,4 +123,27 @@ public final class TIFFImageReadParam extends ImageReadParam {
|
||||
public List<TIFFTagSet> getAllowedTagSets() {
|
||||
return allowedTagSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to read fields corresponding to {@code TIFFTag}s not in
|
||||
* the allowed {@code TIFFTagSet}s. The default setting is {@code false}.
|
||||
* If the TIFF {@code ImageReader} is ignoring metadata, then a setting
|
||||
* of {@code true} is overridden as all metadata are ignored except those
|
||||
* essential to reading the image itself.
|
||||
*
|
||||
* @param readUnknownTags Whether to read fields of unrecognized tags
|
||||
*/
|
||||
public void setReadUnknownTags(boolean readUnknownTags) {
|
||||
this.readUnknownTags = readUnknownTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the setting of whether to read fields corresponding to unknown
|
||||
* {@code TIFFTag}s.
|
||||
*
|
||||
* @return Whether to read fields of unrecognized tags
|
||||
*/
|
||||
public boolean getReadUnknownTags() {
|
||||
return readUnknownTags;
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ public class MultiPageImageTIFFFieldTest {
|
||||
ImageReader reader = getTIFFReader();
|
||||
|
||||
ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME));
|
||||
reader.setInput(s, false, true);
|
||||
reader.setInput(s, false, false);
|
||||
|
||||
int ni = reader.getNumImages(true);
|
||||
check(ni == 2, "invalid number of images");
|
||||
|
||||
269
jdk/test/javax/imageio/plugins/tiff/ReadUnknownTagsTest.java
Normal file
269
jdk/test/javax/imageio/plugins/tiff/ReadUnknownTagsTest.java
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8154058
|
||||
* @author a.stepanov
|
||||
* @summary Some checks for ignoring metadata
|
||||
* @run main ReadUnknownTagsTest
|
||||
*/
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import javax.imageio.*;
|
||||
import javax.imageio.metadata.*;
|
||||
|
||||
import javax.imageio.stream.*;
|
||||
import javax.imageio.plugins.tiff.*;
|
||||
|
||||
|
||||
public class ReadUnknownTagsTest {
|
||||
|
||||
private final static int SZ = 50;
|
||||
private final static Color C = Color.RED;
|
||||
|
||||
private final static int DESCRIPTION_TAG =
|
||||
BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION;
|
||||
private final static String DESCRIPTION = "A Test Image";
|
||||
|
||||
private final static int FAX_TAG = FaxTIFFTagSet.TAG_CLEAN_FAX_DATA;
|
||||
private final static short FAX_DATA =
|
||||
FaxTIFFTagSet.CLEAN_FAX_DATA_ERRORS_UNCORRECTED;
|
||||
|
||||
private final boolean ignoreMetadata;
|
||||
private final boolean readUnknownTags;
|
||||
|
||||
public ReadUnknownTagsTest(boolean ignoreMetadata,
|
||||
boolean readUnknownTags) {
|
||||
this.ignoreMetadata = ignoreMetadata;
|
||||
this.readUnknownTags = readUnknownTags;
|
||||
}
|
||||
|
||||
private ImageWriter getTIFFWriter() {
|
||||
|
||||
java.util.Iterator<ImageWriter> writers =
|
||||
ImageIO.getImageWritersByFormatName("TIFF");
|
||||
if (!writers.hasNext()) {
|
||||
throw new RuntimeException("No writers available for TIFF format");
|
||||
}
|
||||
return writers.next();
|
||||
}
|
||||
|
||||
private ImageReader getTIFFReader() {
|
||||
|
||||
java.util.Iterator<ImageReader> readers =
|
||||
ImageIO.getImageReadersByFormatName("TIFF");
|
||||
if (!readers.hasNext()) {
|
||||
throw new RuntimeException("No readers available for TIFF format");
|
||||
}
|
||||
return readers.next();
|
||||
}
|
||||
|
||||
|
||||
private void writeImage() throws Exception {
|
||||
|
||||
String fn = "test-" + ignoreMetadata + ".tiff";
|
||||
OutputStream s = new BufferedOutputStream(new FileOutputStream(fn));
|
||||
try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) {
|
||||
|
||||
ImageWriter writer = getTIFFWriter();
|
||||
writer.setOutput(ios);
|
||||
|
||||
BufferedImage img = new BufferedImage(SZ, SZ,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
Graphics g = img.getGraphics();
|
||||
g.setColor(C);
|
||||
g.fillRect(0, 0, SZ, SZ);
|
||||
g.dispose();
|
||||
|
||||
ImageWriteParam param = writer.getDefaultWriteParam();
|
||||
|
||||
IIOMetadata md = writer.getDefaultImageMetadata(
|
||||
new ImageTypeSpecifier(img), param);
|
||||
|
||||
TIFFDirectory dir = TIFFDirectory.createFromMetadata(md);
|
||||
|
||||
TIFFTag descTag =
|
||||
BaselineTIFFTagSet.getInstance().getTag(DESCRIPTION_TAG);
|
||||
dir.addTIFFField(new TIFFField(descTag, TIFFTag.TIFF_ASCII, 1,
|
||||
new String[] {DESCRIPTION}));
|
||||
|
||||
TIFFTag faxTag = FaxTIFFTagSet.getInstance().getTag(FAX_TAG);
|
||||
dir.addTIFFField(new TIFFField(faxTag, FAX_DATA));
|
||||
|
||||
writer.write(new IIOImage(img, null, dir.getAsMetadata()));
|
||||
|
||||
ios.flush();
|
||||
writer.dispose();
|
||||
}
|
||||
s.close();
|
||||
}
|
||||
|
||||
private void readAndCheckImage() throws Exception {
|
||||
|
||||
ImageReader reader = getTIFFReader();
|
||||
|
||||
String fn = "test-" + ignoreMetadata + ".tiff";
|
||||
ImageInputStream s = ImageIO.createImageInputStream(new File(fn));
|
||||
|
||||
reader.setInput(s, false, ignoreMetadata);
|
||||
|
||||
int ni = reader.getNumImages(true);
|
||||
check(ni == 1, "invalid number of images");
|
||||
|
||||
|
||||
TIFFImageReadParam param = new TIFFImageReadParam();
|
||||
// fax data are allowed by default
|
||||
param.removeAllowedTagSet(FaxTIFFTagSet.getInstance());
|
||||
|
||||
// readUnknownTags setting
|
||||
if (param.getReadUnknownTags()) {
|
||||
throw new RuntimeException("Default readUnknownTags is not false");
|
||||
}
|
||||
param.setReadUnknownTags(readUnknownTags);
|
||||
if (param.getReadUnknownTags() != readUnknownTags) {
|
||||
throw new RuntimeException("Incorrect readUnknownTags setting "
|
||||
+ "\"" + readUnknownTags + "\"");
|
||||
}
|
||||
|
||||
// read images and metadata
|
||||
IIOImage i = reader.readAll(0, param);
|
||||
BufferedImage bi = (BufferedImage) i.getRenderedImage();
|
||||
|
||||
check(bi.getWidth() == SZ, "invalid width");
|
||||
check(bi.getHeight() == SZ, "invalid height");
|
||||
Color c = new Color(bi.getRGB(SZ / 2, SZ / 2));
|
||||
check(c.equals(C), "invalid color");
|
||||
|
||||
IIOMetadata metadata = i.getMetadata();
|
||||
|
||||
//
|
||||
// Verify presence of image metadata
|
||||
//
|
||||
if (metadata == null) {
|
||||
throw new RuntimeException("No image metadata retrieved");
|
||||
}
|
||||
|
||||
TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata);
|
||||
|
||||
//
|
||||
// Verify presence of essential ImageWidth field regardless of
|
||||
// settings of ignoreMetadata and readUnknownTags
|
||||
//
|
||||
int failures = 0;
|
||||
if (!dir.containsTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH)) {
|
||||
System.err.println("Metadata is missing essential ImageWidth tag");
|
||||
failures++;
|
||||
} else {
|
||||
TIFFField widthField =
|
||||
dir.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH);
|
||||
System.out.printf("ImageWidth: %d%n", widthField.getAsLong(0));
|
||||
}
|
||||
|
||||
//
|
||||
// Verify presence of non-essential baseline ImageDescription field
|
||||
// if and only if ignoreMetadata == false
|
||||
//
|
||||
boolean hasDescription = dir.containsTIFFField(DESCRIPTION_TAG);
|
||||
System.out.println("ImageDescription (" + !ignoreMetadata + "): "
|
||||
+ hasDescription);
|
||||
if (ignoreMetadata && hasDescription) {
|
||||
System.err.println
|
||||
("Description metadata present despite ignoreMetadata");
|
||||
failures++;
|
||||
} else if (!ignoreMetadata && !hasDescription) {
|
||||
System.err.println
|
||||
("Description metadata absent despite !ignoreMetadata");
|
||||
failures++;
|
||||
}
|
||||
|
||||
//
|
||||
// Verify presence of CleanFaxData field if and only if
|
||||
// ignoreMetadata == false and readUnknownTags == true
|
||||
//
|
||||
boolean shouldHaveFaxField = !ignoreMetadata && readUnknownTags;
|
||||
boolean hasFaxField = dir.containsTIFFField(FAX_TAG);
|
||||
System.out.println("CleanFaxData (" + shouldHaveFaxField + "): "
|
||||
+ hasFaxField);
|
||||
|
||||
if (ignoreMetadata) {
|
||||
if (hasFaxField) {
|
||||
System.err.println
|
||||
("Fax metadata present despite ignoreMetadata");
|
||||
failures++;
|
||||
}
|
||||
} else { // !ignoreMetadata
|
||||
if (!readUnknownTags && hasFaxField) {
|
||||
System.err.println
|
||||
("Fax metadata present despite !readUnknownTags");
|
||||
failures++;
|
||||
} else if (readUnknownTags && !hasFaxField) {
|
||||
System.err.println
|
||||
("Fax metadata absent despite readUnknownTags");
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
|
||||
if (failures > 0) {
|
||||
throw new RuntimeException("Test failed for ignoreMetadata "
|
||||
+ ignoreMetadata + " and readUnknownTags " + readUnknownTags);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
writeImage();
|
||||
readAndCheckImage();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void check(boolean ok, String msg) {
|
||||
if (!ok) { throw new RuntimeException(msg); }
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int failures = 0;
|
||||
|
||||
System.out.println();
|
||||
for (boolean ignoreMetadata : new boolean[] {false, true}) {
|
||||
for (boolean readUnknownTags : new boolean[] {false, true}) {
|
||||
try {
|
||||
System.out.printf
|
||||
("ignoreMetadata: %s, readUnknownTags: %s%n",
|
||||
ignoreMetadata, readUnknownTags);
|
||||
(new ReadUnknownTagsTest(ignoreMetadata,
|
||||
readUnknownTags)).run();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
failures++;
|
||||
} finally {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,7 +159,7 @@ public class TIFFImageReadParamTest {
|
||||
ImageReader reader = getTIFFReader();
|
||||
|
||||
ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME));
|
||||
reader.setInput(s, false, true);
|
||||
reader.setInput(s, false, false);
|
||||
|
||||
int ni = reader.getNumImages(true);
|
||||
check(ni == 1, "invalid number of images: " + ni);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user