Search in sources :

Example 1 with Predictor

use of org.apache.sis.internal.geotiff.Predictor in project sis by apache.

the class NativeMetadata method read.

/**
 * Reads the tree table content. This method assumes that the caller already verified that the
 * file is a GeoTIFF file. Tags are keys are added in the order they are declared in the file.
 */
final DefaultTreeTable read(final Reader reader) throws IOException {
    input = reader.input;
    isClassic = reader.intSizeExpansion == 0;
    final int offsetSize = Integer.BYTES << reader.intSizeExpansion;
    final DefaultTreeTable table = new DefaultTreeTable(CODE, NAME, VALUE);
    final TreeTable.Node root = table.getRoot();
    root.setValue(NAME, "TIFF");
    input.mark();
    try {
        input.seek(addExact(reader.origin, isClassic ? 2 * Short.BYTES : 4 * Short.BYTES));
        final Set<Long> doneIFD = new HashSet<>();
        long nextIFD;
        /*
             * Following loop is a simplified copy of `Reader.getImageFileDirectory(int)` method,
             * without the "deferred entries" mechanism. Instead we seek immediately.
             */
        int imageNumber = 0;
        while ((nextIFD = readInt(false)) != 0) {
            if (!doneIFD.add(nextIFD)) {
                // Safety against infinite recursivity.
                break;
            }
            final TreeTable.Node image = root.newChild();
            image.setValue(NAME, vocabulary.getString(Vocabulary.Keys.Image_1, imageNumber));
            input.seek(Math.addExact(reader.origin, nextIFD));
            for (long remaining = readInt(true); --remaining >= 0; ) {
                final short tag = (short) input.readUnsignedShort();
                // May be null.
                final Type type = Type.valueOf(input.readShort());
                final long count = readInt(false);
                final long size = (type != null) ? Math.multiplyExact(type.size, count) : 0;
                final long next = addExact(input.getStreamPosition(), offsetSize);
                boolean visible;
                /*
                     * Exclude the tags about location of tiles in the GeoTIFF files.
                     * Values of those tags are potentially large and rarely useful for human reading.
                     * This switch is only about tags to skip; special handlings of some tags are done later.
                     */
                switch(tag) {
                    case Tags.TileOffsets:
                    case Tags.StripOffsets:
                    case Tags.TileByteCounts:
                    case Tags.StripByteCounts:
                        visible = false;
                        break;
                    default:
                        visible = (size != 0);
                        break;
                }
                if (visible) {
                    if (size > offsetSize) {
                        final long offset = readInt(false);
                        input.seek(Math.addExact(reader.origin, offset));
                    }
                    /*
                         * Some tags need to be handle in a special way. The main cases are GeoTIFF keys.
                         * But other cases exist (e.g. GEO_METADATA and GDAL_METADATA).
                         */
                    Object value = null;
                    XMLMetadata children = null;
                    switch(tag) {
                        case Tags.GeoKeyDirectory:
                            {
                                // Flush previous keys if any (should never happen).
                                writeGeoKeys();
                                keyDirectory = type.readVector(input, count);
                                value = "GeoTIFF";
                                break;
                            }
                        case Tags.GeoDoubleParams:
                            {
                                numericParameters = type.readVector(input, count);
                                visible = false;
                                break;
                            }
                        case Tags.GeoAsciiParams:
                            {
                                setAsciiParameters(type.readString(input, count, reader.store.encoding));
                                visible = false;
                                break;
                            }
                        case Tags.GDAL_METADATA:
                        case Tags.GEO_METADATA:
                            {
                                children = new XMLMetadata(reader, type, count, tag);
                                if (children.isEmpty()) {
                                    // Fallback on showing array of numerical values.
                                    value = type.readVector(input, count);
                                }
                                break;
                            }
                        default:
                            {
                                value = type.readObject(input, count);
                                if (value instanceof Vector) {
                                    final Vector v = (Vector) value;
                                    switch(v.size()) {
                                        case 0:
                                            value = null;
                                            break;
                                        case 1:
                                            value = v.get(0);
                                            break;
                                    }
                                }
                                /*
                                 * Replace a few numerical values by a more readable string when available.
                                 * We currently perform this replacement only for tags for which we defined
                                 * an enumeration.
                                 */
                                switch(tag) {
                                    case Tags.Compression:
                                        value = toString(value, Compression::valueOf, Compression.UNKNOWN);
                                        break;
                                    case Tags.Predictor:
                                        value = toString(value, Predictor::valueOf, Predictor.UNKNOWN);
                                        break;
                                }
                            }
                    }
                    if (visible) {
                        final String name = Tags.name(tag);
                        final TreeTable.Node node;
                        if (children != null) {
                            node = new XMLMetadata.Root(children, (DefaultTreeTable.Node) image, name);
                        } else {
                            node = image.newChild();
                            node.setValue(NAME, name);
                            node.setValue(VALUE, value);
                        }
                        node.setValue(CODE, Short.toUnsignedInt(tag));
                        if (tag == Tags.GeoKeyDirectory) {
                            geoNode = node;
                        }
                    }
                }
                input.seek(next);
            }
            imageNumber++;
        }
    } catch (ArithmeticException e) {
        // Can not seek that far.
        throw new IOException(e);
    } finally {
        input.reset();
    }
    writeGeoKeys();
    return table;
}
Also used : Compression(org.apache.sis.internal.geotiff.Compression) Predictor(org.apache.sis.internal.geotiff.Predictor) TreeTable(org.apache.sis.util.collection.TreeTable) DefaultTreeTable(org.apache.sis.util.collection.DefaultTreeTable) IOException(java.io.IOException) DefaultTreeTable(org.apache.sis.util.collection.DefaultTreeTable) Vector(org.apache.sis.math.Vector) HashSet(java.util.HashSet)

Aggregations

IOException (java.io.IOException)1 HashSet (java.util.HashSet)1 Compression (org.apache.sis.internal.geotiff.Compression)1 Predictor (org.apache.sis.internal.geotiff.Predictor)1 Vector (org.apache.sis.math.Vector)1 DefaultTreeTable (org.apache.sis.util.collection.DefaultTreeTable)1 TreeTable (org.apache.sis.util.collection.TreeTable)1