Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (101)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (309)
Collections:
Other Resources:
JDK 17 java.desktop.jmod - Desktop Module
JDK 17 java.desktop.jmod is the JMOD file for JDK 17 Desktop module.
JDK 17 Desktop module compiled class files are stored in \fyicenter\jdk-17.0.5\jmods\java.desktop.jmod.
JDK 17 Desktop module compiled class files are also linked and stored in the \fyicenter\jdk-17.0.5\lib\modules JImage file.
JDK 17 Desktop module source code files are stored in \fyicenter\jdk-17.0.5\lib\src.zip\java.desktop.
You can click and view the content of each source code file in the list below.
✍: FYIcenter
⏎ com/sun/imageio/plugins/tiff/TIFFIFD.java
/* * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package com.sun.imageio.plugins.tiff; import java.io.EOFException; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.imageio.IIOException; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; import javax.imageio.plugins.tiff.BaselineTIFFTagSet; import javax.imageio.plugins.tiff.TIFFDirectory; import javax.imageio.plugins.tiff.TIFFField; import javax.imageio.plugins.tiff.TIFFTag; import javax.imageio.plugins.tiff.TIFFTagSet; public class TIFFIFD extends TIFFDirectory { private static final long MAX_SAMPLES_PER_PIXEL = 0xffff; private static final long MAX_ASCII_SIZE = 0xffff; private long stripOrTileByteCountsPosition = -1; private long stripOrTileOffsetsPosition = -1; private long lastPosition = -1; // // A set of tag numbers corresponding to tags essential to decoding // the image and metadata required to interpret its samples. // private static volatile Set<Integer> essentialTags = null; private static void initializeEssentialTags() { Set<Integer> tags = essentialTags; if (tags == null) { essentialTags = tags = Set.of( BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE, BaselineTIFFTagSet.TAG_COLOR_MAP, BaselineTIFFTagSet.TAG_COMPRESSION, BaselineTIFFTagSet.TAG_EXTRA_SAMPLES, BaselineTIFFTagSet.TAG_FILL_ORDER, BaselineTIFFTagSet.TAG_ICC_PROFILE, BaselineTIFFTagSet.TAG_IMAGE_LENGTH, BaselineTIFFTagSet.TAG_IMAGE_WIDTH, BaselineTIFFTagSet.TAG_JPEG_AC_TABLES, BaselineTIFFTagSet.TAG_JPEG_DC_TABLES, BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT, BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, BaselineTIFFTagSet.TAG_JPEG_PROC, BaselineTIFFTagSet.TAG_JPEG_Q_TABLES, BaselineTIFFTagSet.TAG_JPEG_RESTART_INTERVAL, BaselineTIFFTagSet.TAG_JPEG_TABLES, BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION, BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION, BaselineTIFFTagSet.TAG_PREDICTOR, BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE, BaselineTIFFTagSet.TAG_ROWS_PER_STRIP, BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL, BaselineTIFFTagSet.TAG_SAMPLE_FORMAT, BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS, BaselineTIFFTagSet.TAG_STRIP_OFFSETS, BaselineTIFFTagSet.TAG_T4_OPTIONS, BaselineTIFFTagSet.TAG_T6_OPTIONS, BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS, BaselineTIFFTagSet.TAG_TILE_LENGTH, BaselineTIFFTagSet.TAG_TILE_OFFSETS, BaselineTIFFTagSet.TAG_TILE_WIDTH, BaselineTIFFTagSet.TAG_Y_CB_CR_COEFFICIENTS, BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING ); } } /** * Converts a {@code TIFFDirectory} to a {@code TIFFIFD}. */ public static TIFFIFD getDirectoryAsIFD(TIFFDirectory dir) { if(dir instanceof TIFFIFD) { return (TIFFIFD)dir; } TIFFIFD ifd = new TIFFIFD(Arrays.asList(dir.getTagSets()), dir.getParentTag()); TIFFField[] fields = dir.getTIFFFields(); int numFields = fields.length; for(int i = 0; i < numFields; i++) { TIFFField f = fields[i]; TIFFTag tag = f.getTag(); if(tag.isIFDPointer()) { TIFFDirectory subDir = null; if (f.hasDirectory()) { subDir = f.getDirectory(); } else if (f.getData() instanceof TIFFDirectory) { subDir = (TIFFDirectory)f.getData(); } if (subDir != null) { TIFFDirectory subIFD = getDirectoryAsIFD(subDir); f = new TIFFField(tag, f.getType(), (long)f.getCount(), subIFD); } else { f = null; } } if (f != null) { ifd.addTIFFField(f); } } return ifd; } public static TIFFTag getTag(int tagNumber, List<TIFFTagSet> tagSets) { for (TIFFTagSet tagSet : tagSets) { TIFFTag tag = tagSet.getTag(tagNumber); if (tag != null) { return tag; } } return null; } public static TIFFTag getTag(String tagName, List<TIFFTagSet> tagSets) { for (TIFFTagSet tagSet : tagSets) { TIFFTag tag = tagSet.getTag(tagName); if (tag != null) { return tag; } } return null; } private static void writeTIFFFieldToStream(TIFFField field, ImageOutputStream stream) throws IOException { int count = field.getCount(); Object data = field.getData(); switch (field.getType()) { case TIFFTag.TIFF_ASCII: for (int i = 0; i < count; i++) { String s = ((String[])data)[i]; int length = s.length(); for (int j = 0; j < length; j++) { stream.writeByte(s.charAt(j) & 0xff); } stream.writeByte(0); } break; case TIFFTag.TIFF_UNDEFINED: case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: stream.write((byte[])data); break; case TIFFTag.TIFF_SHORT: stream.writeChars((char[])data, 0, ((char[])data).length); break; case TIFFTag.TIFF_SSHORT: stream.writeShorts((short[])data, 0, ((short[])data).length); break; case TIFFTag.TIFF_SLONG: stream.writeInts((int[])data, 0, ((int[])data).length); break; case TIFFTag.TIFF_LONG: for (int i = 0; i < count; i++) { stream.writeInt((int)(((long[])data)[i])); } break; case TIFFTag.TIFF_IFD_POINTER: stream.writeInt(0); // will need to be backpatched break; case TIFFTag.TIFF_FLOAT: stream.writeFloats((float[])data, 0, ((float[])data).length); break; case TIFFTag.TIFF_DOUBLE: stream.writeDoubles((double[])data, 0, ((double[])data).length); break; case TIFFTag.TIFF_SRATIONAL: for (int i = 0; i < count; i++) { stream.writeInt(((int[][])data)[i][0]); stream.writeInt(((int[][])data)[i][1]); } break; case TIFFTag.TIFF_RATIONAL: for (int i = 0; i < count; i++) { long num = ((long[][])data)[i][0]; long den = ((long[][])data)[i][1]; stream.writeInt((int)num); stream.writeInt((int)den); } break; default: // error } } public TIFFIFD(List<TIFFTagSet> tagSets, TIFFTag parentTag) { super(tagSets.toArray(new TIFFTagSet[tagSets.size()]), parentTag); } public TIFFIFD(List<TIFFTagSet> tagSets) { this(tagSets, null); } public List<TIFFTagSet> getTagSetList() { return Arrays.asList(getTagSets()); } /** * Returns an {@code Iterator} over the TIFF fields. The * traversal is in the order of increasing tag number. */ // Note: the sort is guaranteed for low fields by the use of an // array wherein the index corresponds to the tag number and for // the high fields by the use of a TreeMap with tag number keys. public Iterator<TIFFField> iterator() { return Arrays.asList(getTIFFFields()).iterator(); } /** * Read the value of a field. The {@code data} parameter should be * an array of length 1 of Object. * * @param stream the input stream * @param type the type as read from the stream * @param count the count read from the stream * @param data a container for the data * @return the updated count * @throws IOException */ private static int readFieldValue(ImageInputStream stream, int type, int count, Object[] data) throws IOException { Object obj; final int UNIT_SIZE = 1024000; switch (type) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: case TIFFTag.TIFF_UNDEFINED: case TIFFTag.TIFF_ASCII: if (type == TIFFTag.TIFF_ASCII) { byte[] bvalues = new byte[count]; stream.readFully(bvalues, 0, count); // Can be multiple strings ArrayList<String> v = new ArrayList<>(); boolean inString = false; int prevIndex = 0; for (int index = 0; index <= count; index++) { if (index < count && bvalues[index] != 0) { if (!inString) { // start of string prevIndex = index; inString = true; } } else { // null or special case at end of string if (inString) { // end of string String s = new String(bvalues, prevIndex, index - prevIndex, StandardCharsets.US_ASCII); v.add(s); inString = false; } } } count = v.size(); String[] strings; if (count != 0) { strings = new String[count]; for (int c = 0; c < count; c++) { strings[c] = v.get(c); } } else { // This case has been observed when the value of // 'count' recorded in the field is non-zero but // the value portion contains all nulls. count = 1; strings = new String[]{""}; } obj = strings; } else { if (count < UNIT_SIZE) { byte[] bvalues = new byte[count]; stream.readFully(bvalues, 0, count); obj = bvalues; } else { int bytesToRead = count; int bytesRead = 0; List<byte[]> bufs = new ArrayList<>(); while (bytesToRead != 0) { int sz = Math.min(bytesToRead, UNIT_SIZE); byte[] unit = new byte[sz]; stream.readFully(unit, 0, sz); bufs.add(unit); bytesRead += sz; bytesToRead -= sz; } byte[] tagData = new byte[bytesRead]; int copiedBytes = 0; for (byte[] ba : bufs) { System.arraycopy(ba, 0, tagData, copiedBytes, ba.length); copiedBytes += ba.length; } obj = tagData; } } break; case TIFFTag.TIFF_SHORT: final int SHORT_TILE_SIZE = UNIT_SIZE / TIFFTag.getSizeOfType(TIFFTag.TIFF_SHORT); if (count < SHORT_TILE_SIZE) { char[] cvalues = new char[count]; for (int j = 0; j < count; j++) { cvalues[j] = (char) (stream.readUnsignedShort()); } obj = cvalues; } else { int charsToRead = count; int charsRead = 0; List<char[]> bufs = new ArrayList<>(); while (charsToRead != 0) { int sz = Math.min(charsToRead, SHORT_TILE_SIZE); char[] unit = new char[sz]; for (int i = 0; i < sz ; i++) { unit[i] = (char) (stream.readUnsignedShort()); } bufs.add(unit); charsRead += sz; charsToRead -= sz; } char[] tagData = new char[charsRead]; int copiedChars = 0; for (char[] ca : bufs) { System.arraycopy(ca, 0, tagData, copiedChars, ca.length); copiedChars += ca.length; } obj = tagData; } break; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: final int LONG_TILE_SIZE = UNIT_SIZE / TIFFTag.getSizeOfType(TIFFTag.TIFF_LONG); if (count < LONG_TILE_SIZE) { long[] lvalues = new long[count]; for (int j = 0; j < count; j++) { lvalues[j] = stream.readUnsignedInt(); } obj = lvalues; } else { int longsToRead = count; int longsRead = 0; List<long[]> bufs = new ArrayList<>(); while (longsToRead != 0) { int sz = Math.min(longsToRead, LONG_TILE_SIZE); long[] unit = new long[sz]; for (int i = 0; i < sz ; i++) { unit[i] = stream.readUnsignedInt(); } bufs.add(unit); longsRead += sz; longsToRead -= sz; } long[] tagData = new long[longsRead]; int copiedLongs = 0; for (long[] la : bufs) { System.arraycopy(la, 0, tagData, copiedLongs, la.length); copiedLongs += la.length; } obj = tagData; } break; case TIFFTag.TIFF_RATIONAL: final int RATIONAL_TILE_SIZE = UNIT_SIZE / TIFFTag.getSizeOfType(TIFFTag.TIFF_RATIONAL); if (count < RATIONAL_TILE_SIZE) { long[][] llvalues = new long[count][2]; for (int j = 0; j < count; j++) { llvalues[j][0] = stream.readUnsignedInt(); llvalues[j][1] = stream.readUnsignedInt(); } obj = llvalues; } else { int rationalsToRead = count; int rationalsRead = 0; List<long[]> bufs = new ArrayList<>(); while (rationalsToRead != 0) { int sz = Math.min(rationalsToRead, RATIONAL_TILE_SIZE); long[] unit = new long[sz * 2]; for (int i = 0; i < (sz * 2) ; i++) { unit[i] = stream.readUnsignedInt(); } bufs.add(unit); rationalsRead += sz; rationalsToRead -= sz; } long[][] tagData = new long[rationalsRead][2]; int copiedRationals = 0; for (long[] la : bufs) { for (int i = 0; i < la.length; i = i + 2) { tagData[copiedRationals + i][0] = la[i]; tagData[copiedRationals + i][1] = la[i + 1]; } copiedRationals += (la.length / 2); } obj = tagData; } break; case TIFFTag.TIFF_SSHORT: final int SSHORT_TILE_SIZE = UNIT_SIZE / TIFFTag.getSizeOfType(TIFFTag.TIFF_SSHORT); if (count < SSHORT_TILE_SIZE) { short[] svalues = new short[count]; for (int j = 0; j < count; j++) { svalues[j] = stream.readShort(); } obj = svalues; } else { int shortsToRead = count; int shortsRead = 0; List<short[]> bufs = new ArrayList<>(); while (shortsToRead != 0) { int sz = Math.min(shortsToRead, SSHORT_TILE_SIZE); short[] unit = new short[sz]; stream.readFully(unit, 0, sz); bufs.add(unit); shortsRead += sz; shortsToRead -= sz; } short[] tagData = new short[shortsRead]; int copiedShorts = 0; for (short[] sa : bufs) { System.arraycopy(sa, 0, tagData, copiedShorts, sa.length); copiedShorts += sa.length; } obj = tagData; } break; case TIFFTag.TIFF_SLONG: final int INT_TILE_SIZE = UNIT_SIZE / TIFFTag.getSizeOfType(TIFFTag.TIFF_SLONG); if (count < INT_TILE_SIZE) { int[] ivalues = new int[count]; for (int j = 0; j < count; j++) { ivalues[j] = stream.readInt(); } obj = ivalues; } else { int intsToRead = count; int intsRead = 0; List<int[]> bufs = new ArrayList<>(); while (intsToRead != 0) { int sz = Math.min(intsToRead, INT_TILE_SIZE); int[] unit = new int[sz]; stream.readFully(unit, 0, sz); bufs.add(unit); intsRead += sz; intsToRead -= sz; } int[] tagData = new int[intsRead]; int copiedInts = 0; for (int[] ia : bufs) { System.arraycopy(ia, 0, tagData, copiedInts, ia.length); copiedInts += ia.length; } obj = tagData; } break; case TIFFTag.TIFF_SRATIONAL: final int SRATIONAL_TILE_SIZE = UNIT_SIZE / TIFFTag.getSizeOfType(TIFFTag.TIFF_SRATIONAL); if (count < SRATIONAL_TILE_SIZE) { int[][] iivalues = new int[count][2]; for (int j = 0; j < count; j++) { iivalues[j][0] = stream.readInt(); iivalues[j][1] = stream.readInt(); } obj = iivalues; } else { int srationalsToRead = count; int srationalsRead = 0; List<int[]> bufs = new ArrayList<>(); while (srationalsToRead != 0) { int sz = Math.min(srationalsToRead, SRATIONAL_TILE_SIZE); int[] unit = new int[sz * 2]; stream.readFully(unit, 0, (sz * 2)); bufs.add(unit); srationalsRead += sz; srationalsToRead -= sz; } int[][] tagData = new int[srationalsRead][2]; int copiedSrationals = 0; for (int[] ia : bufs) { for (int i = 0; i < ia.length; i = i + 2) { tagData[copiedSrationals + i][0] = ia[i]; tagData[copiedSrationals + i][1] = ia[i + 1]; } copiedSrationals += (ia.length / 2); } obj = tagData; } break; case TIFFTag.TIFF_FLOAT: final int FLOAT_TILE_SIZE = UNIT_SIZE / TIFFTag.getSizeOfType(TIFFTag.TIFF_FLOAT); if (count < FLOAT_TILE_SIZE) { float[] fvalues = new float[count]; for (int j = 0; j < count; j++) { fvalues[j] = stream.readFloat(); } obj = fvalues; } else { int floatsToRead = count; int floatsRead = 0; List<float[]> bufs = new ArrayList<>(); while (floatsToRead != 0) { int sz = Math.min(floatsToRead, FLOAT_TILE_SIZE); float[] unit = new float[sz]; stream.readFully(unit, 0, sz); bufs.add(unit); floatsRead += sz; floatsToRead -= sz; } float[] tagData = new float[floatsRead]; int copiedFloats = 0; for (float[] fa : bufs) { System.arraycopy(fa, 0, tagData, copiedFloats, fa.length); copiedFloats += fa.length; } obj = tagData; } break; case TIFFTag.TIFF_DOUBLE: final int DOUBLE_TILE_SIZE = UNIT_SIZE / TIFFTag.getSizeOfType(TIFFTag.TIFF_DOUBLE); if (count < DOUBLE_TILE_SIZE) { double[] dvalues = new double[count]; for (int j = 0; j < count; j++) { dvalues[j] = stream.readDouble(); } obj = dvalues; } else { int doublesToRead = count; int doublesRead = 0; List<double[]> bufs = new ArrayList<>(); while (doublesToRead != 0) { int sz = Math.min(doublesToRead, DOUBLE_TILE_SIZE); double[] unit = new double[sz]; stream.readFully(unit, 0, sz); bufs.add(unit); doublesRead += sz; doublesToRead -= sz; } double[] tagData = new double[doublesRead]; int copiedDoubles = 0; for (double[] da : bufs) { System.arraycopy(da, 0, tagData, copiedDoubles, da.length); copiedDoubles += da.length; } obj = tagData; } break; default: obj = null; break; } data[0] = obj; return count; } // // Class to represent an IFD entry where the actual content is at an offset // in the stream somewhere outside the IFD itself. This occurs when the // value cannot be contained within four bytes. Seeking is required to read // such field values. // private static class TIFFIFDEntry { public final TIFFTag tag; public final int type; public final int count; public final long offset; TIFFIFDEntry(TIFFTag tag, int type, int count, long offset) { this.tag = tag; this.type = type; this.count = count; this.offset = offset; } } // // Retrieve the value of a baseline field as a long. // private long getFieldAsLong(int tagNumber) { TIFFField f = getTIFFField(tagNumber); return f == null ? -1 : f.getAsLong(0); } // // Retrieve the value of a baseline field as an int. // private int getFieldAsInt(int tagNumber) { TIFFField f = getTIFFField(tagNumber); return f == null ? -1 : f.getAsInt(0); } // // Calculate the number of bytes in each strip or tile. This method // is to be used if and only if no fields exist which provide this // information. The parameter must be empty and if the method succeeds // will contain a single element. // private boolean calculateByteCounts(int expectedSize, List<TIFFField> byteCounts) { if (!byteCounts.isEmpty()) { throw new IllegalArgumentException("byteCounts is not empty"); } // must be interleaved if (getFieldAsInt(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION) == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) { return false; } // must be uncompressed if (getFieldAsInt(BaselineTIFFTagSet.TAG_COMPRESSION) != BaselineTIFFTagSet.COMPRESSION_NONE) { return false; } // must have image dimensions long w = getFieldAsLong(BaselineTIFFTagSet.TAG_IMAGE_WIDTH); if (w < 0) { return false; } long h = getFieldAsLong(BaselineTIFFTagSet.TAG_IMAGE_LENGTH); if (h < 0) { return false; } long tw = getFieldAsLong(BaselineTIFFTagSet.TAG_TILE_WIDTH); if (tw < 0) { tw = w; } long th = getFieldAsLong(BaselineTIFFTagSet.TAG_TILE_LENGTH); if (th < 0) { th = getFieldAsLong(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP); if (th < 0) { th = h; } } int[] bitsPerSample = null; TIFFField f = getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); if (f != null) { bitsPerSample = f.getAsInts(); } else { int samplesPerPixel = getFieldAsInt(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL); if (samplesPerPixel < 0) { samplesPerPixel = 1; } bitsPerSample = new int[samplesPerPixel]; Arrays.fill(bitsPerSample, 8); } int bitsPerPixel = 0; for (int bps : bitsPerSample) { bitsPerPixel += bps; } int bytesPerRow = (int)(tw*bitsPerPixel + 7)/8; int bytesPerPacket = (int)th*bytesPerRow; long nx = (w + tw - 1)/tw; long ny = (h + th - 1)/th; if (nx*ny != expectedSize) { return false; } boolean isTiled = getTIFFField(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS) != null; int tagNumber; if (isTiled) { tagNumber = BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS; } else { tagNumber = BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS; } TIFFTag t = BaselineTIFFTagSet.getInstance().getTag(tagNumber); f = getTIFFField(tagNumber); if (f != null) { removeTIFFField(tagNumber); } int numPackets = (int)(nx*ny); long[] packetByteCounts = new long[numPackets]; Arrays.fill(packetByteCounts, bytesPerPacket); // if the strip or tile width does not exceed the image width and the // image height is not a multiple of the strip or tile height, then // truncate the estimate of the byte count of the last strip to avoid // reading past the end of the data if (tw <= w && h % th != 0) { int numRowsInLastStrip = (int)(h - (ny - 1)*th); packetByteCounts[numPackets - 1] = numRowsInLastStrip*bytesPerRow; } f = new TIFFField(t, TIFFTag.TIFF_LONG, numPackets, packetByteCounts); addTIFFField(f); byteCounts.add(f); return true; } // // Verify that data pointed to outside of the IFD itself are within the // stream. To be called after all fields have been read and populated. // private void checkFieldOffsets(long streamLength) throws IIOException { if (streamLength < 0) { return; } // StripOffsets List<TIFFField> offsets = new ArrayList<>(); TIFFField f = getTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS); int count = 0; if (f != null) { count = f.getCount(); offsets.add(f); } // TileOffsets f = getTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS); if (f != null) { int sz = offsets.size(); int newCount = f.getCount(); if (sz > 0 && newCount != count) { throw new IIOException ("StripOffsets count != TileOffsets count"); } if (sz == 0) { count = newCount; } offsets.add(f); } List<TIFFField> byteCounts = new ArrayList<>(); if (offsets.size() > 0) { // StripByteCounts f = getTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS); if (f != null) { if (f.getCount() != count) { throw new IIOException ("StripByteCounts count != number of offsets"); } byteCounts.add(f); } // TileByteCounts f = getTIFFField(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS); if (f != null) { if (f.getCount() != count) { throw new IIOException ("TileByteCounts count != number of offsets"); } byteCounts.add(f); } if (byteCounts.size() > 0) { for (TIFFField offset : offsets) { for (TIFFField byteCount : byteCounts) { for (int i = 0; i < count; i++) { long dataOffset = offset.getAsLong(i); long dataByteCount = byteCount.getAsLong(i); if (dataOffset + dataByteCount > streamLength) { throw new IIOException ("Data segment out of stream"); } } } } } } // JPEGInterchangeFormat and JPEGInterchangeFormatLength TIFFField jpegOffset = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT); if (jpegOffset != null) { TIFFField jpegLength = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); if (jpegLength != null) { if (jpegOffset.getAsLong(0) + jpegLength.getAsLong(0) > streamLength) { throw new IIOException ("JPEGInterchangeFormat data out of stream"); } } } // Ensure there is at least a data pointer for JPEG interchange format or // both data offsets and byte counts for other compression types. if (jpegOffset == null && (offsets.size() == 0 || byteCounts.size() == 0)) { boolean throwException = true; if (offsets.size() != 0 && byteCounts.size() == 0) { // Attempt to calculate missing byte counts int expectedSize = offsets.get(0).getCount(); throwException = !calculateByteCounts(expectedSize, byteCounts); } if (throwException) { throw new IIOException ("Insufficient data offsets or byte counts"); } } // JPEGQTables - one 64-byte table for each offset. f = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_Q_TABLES); if (f != null) { long[] tableOffsets = f.getAsLongs(); for (long off : tableOffsets) { if (off + 64 > streamLength) { throw new IIOException("JPEGQTables data out of stream"); } } } // JPEGDCTables f = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_DC_TABLES); if (f != null) { long[] tableOffsets = f.getAsLongs(); for (long off : tableOffsets) { if (off + 16 > streamLength) { throw new IIOException("JPEGDCTables data out of stream"); } } } // JPEGACTables f = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_AC_TABLES); if (f != null) { long[] tableOffsets = f.getAsLongs(); for (long off : tableOffsets) { if (off + 16 > streamLength) { throw new IIOException("JPEGACTables data out of stream"); } } } } // Stream position initially at beginning, left at end // 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 ignoreMetadata, boolean readUnknownTags) throws IOException { removeTIFFFields(); long streamLength = stream.length(); boolean haveStreamLength = streamLength != -1; 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 && (ignoreMetadata || (!readUnknownTags && !tagSetList.contains(BaselineTIFFTagSet.getInstance())))) { ensureEssentialTags = true; initializeEssentialTags(); baselineTagSet = BaselineTIFFTagSet.getInstance(); } List<Object> entries = new ArrayList<>(); Object[] entryData = new Object[1]; // allocate once for later reuse. // Read the IFD entries, loading the field values which are no more than // four bytes long, and storing the 4-byte offsets for the others. int numEntries = stream.readUnsignedShort(); for (int i = 0; i < numEntries; i++) { // Read tag number, value type, and value count. int tagNumber = stream.readUnsignedShort(); int type = stream.readUnsignedShort(); int sizeOfType; try { sizeOfType = TIFFTag.getSizeOfType(type); } catch (IllegalArgumentException ignored) { // Continue with the next IFD entry. stream.skipBytes(4); continue; } long longCount = stream.readUnsignedInt(); // Get the associated TIFFTag. TIFFTag tag = getTag(tagNumber, tagSetList); if (tag == null && ensureEssentialTags && essentialTags.contains(tagNumber)) { tag = baselineTagSet.getTag(tagNumber); } // Ignore non-essential fields, unknown fields unless forcibly // being read, fields with unknown type, and fields // with count out of int range. 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 // position at the start of the next IFD entry. stream.skipBytes(4); // Continue with the next IFD entry. continue; } int count = (int)longCount; if (tag == null) { tag = new TIFFTag(TIFFTag.UNKNOWN_TAG_NAME, tagNumber, 1 << type, count); } else { int expectedCount = tag.getCount(); if (expectedCount > 0) { // If the tag count is positive then the tag defines a // specific, fixed count that the field must match. if (count != expectedCount) { throw new IIOException("Unexpected count " + count + " for " + tag.getName() + " field"); } } else if (type == TIFFTag.TIFF_ASCII) { // Clamp the size of ASCII fields of unspecified length // to a maximum value. int asciiSize = TIFFTag.getSizeOfType(TIFFTag.TIFF_ASCII); if (count*asciiSize > MAX_ASCII_SIZE) { count = (int)(MAX_ASCII_SIZE/asciiSize); } } } long longSize = longCount*sizeOfType; if (longSize > Integer.MAX_VALUE) { // Continue with the next IFD entry. stream.skipBytes(4); continue; } int size = (int)longSize; if (size > 4 || tag.isIFDPointer()) { // The IFD entry value is a pointer to the actual field value. long offset = stream.readUnsignedInt(); // Check whether the the field value is within the stream. if (haveStreamLength && offset + size > streamLength) { continue; } // Add a TIFFIFDEntry as a placeholder. This avoids a mark, // seek to the data, and a reset. entries.add(new TIFFIFDEntry(tag, type, count, offset)); } else { // The IFD entry value is the actual field value of no more than // four bytes. Object obj = null; try { // Read the field value and update the count. count = readFieldValue(stream, type, count, entryData); obj = entryData[0]; } catch (EOFException eofe) { // The TIFF 6.0 fields have tag numbers less than or equal // to 532 (ReferenceBlackWhite) or equal to 33432 (Copyright). // If there is an error reading a baseline tag, then re-throw // the exception and fail; otherwise continue with the next // field. if (BaselineTIFFTagSet.getInstance().getTag(tagNumber) == null) { throw eofe; } } // If the field value is smaller than four bytes then skip // the remaining, unused bytes. if (size < 4) { stream.skipBytes(4 - size); } // Add the populated TIFFField to the list of entries. entries.add(new TIFFField(tag, type, count, obj)); } } // After reading the IFD entries the stream is positioned at an unsigned // four byte integer containing either the offset of the next IFD or // zero if this is the last IFD. long nextIFDOffset = stream.getStreamPosition(); Object[] fieldData = new Object[1]; for (Object entry : entries) { if (entry instanceof TIFFField) { // Add the populated field directly. addTIFFField((TIFFField)entry); } else { TIFFIFDEntry e = (TIFFIFDEntry)entry; TIFFTag tag = e.tag; int tagNumber = tag.getNumber(); int type = e.type; int count = e.count; stream.seek(e.offset); if (tag.isIFDPointer()) { List<TIFFTagSet> tagSets = new ArrayList<TIFFTagSet>(1); tagSets.add(tag.getTagSet()); TIFFIFD subIFD = new TIFFIFD(tagSets); subIFD.initialize(stream, false, ignoreMetadata, readUnknownTags); TIFFField f = new TIFFField(tag, type, e.offset, subIFD); addTIFFField(f); } else { if (tagNumber == BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS || tagNumber == BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS || tagNumber == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH) { this.stripOrTileByteCountsPosition = stream.getStreamPosition(); } else if (tagNumber == BaselineTIFFTagSet.TAG_STRIP_OFFSETS || tagNumber == BaselineTIFFTagSet.TAG_TILE_OFFSETS || tagNumber == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) { this.stripOrTileOffsetsPosition = stream.getStreamPosition(); } Object obj = null; try { count = readFieldValue(stream, type, count, fieldData); obj = fieldData[0]; } catch (EOFException eofe) { // The TIFF 6.0 fields have tag numbers less than or equal // to 532 (ReferenceBlackWhite) or equal to 33432 (Copyright). // If there is an error reading a baseline tag, then re-throw // the exception and fail; otherwise continue with the next // field. if (BaselineTIFFTagSet.getInstance().getTag(tagNumber) != null) { throw eofe; } } if (obj == null) { continue; } TIFFField f = new TIFFField(tag, type, count, obj); addTIFFField(f); } } } if(isPrimaryIFD && haveStreamLength) { checkFieldOffsets(streamLength); } stream.seek(nextIFDOffset); this.lastPosition = stream.getStreamPosition(); } public void writeToStream(ImageOutputStream stream) throws IOException { int numFields = getNumTIFFFields(); stream.writeShort(numFields); long nextSpace = stream.getStreamPosition() + 12*numFields + 4; Iterator<TIFFField> iter = iterator(); while (iter.hasNext()) { TIFFField f = iter.next(); TIFFTag tag = f.getTag(); int type = f.getType(); int count = f.getCount(); // Deal with unknown tags if (type == 0) { type = TIFFTag.TIFF_UNDEFINED; } int size = count*TIFFTag.getSizeOfType(type); if (type == TIFFTag.TIFF_ASCII) { int chars = 0; for (int i = 0; i < count; i++) { chars += f.getAsString(i).length() + 1; } count = chars; size = count; } int tagNumber = f.getTagNumber(); stream.writeShort(tagNumber); stream.writeShort(type); stream.writeInt(count); // Write a dummy value to fill space stream.writeInt(0); stream.mark(); // Mark beginning of next field stream.skipBytes(-4); long pos; if (size > 4 || tag.isIFDPointer()) { // Ensure IFD or value is written on a word boundary nextSpace = (nextSpace + 3) & ~0x3; stream.writeInt((int)nextSpace); stream.seek(nextSpace); pos = nextSpace; if (tag.isIFDPointer() && f.hasDirectory()) { TIFFIFD subIFD = getDirectoryAsIFD(f.getDirectory()); subIFD.writeToStream(stream); nextSpace = subIFD.lastPosition; } else { writeTIFFFieldToStream(f, stream); nextSpace = stream.getStreamPosition(); } } else { pos = stream.getStreamPosition(); writeTIFFFieldToStream(f, stream); } // If we are writing the data for the // StripByteCounts, TileByteCounts, StripOffsets, // TileOffsets, JPEGInterchangeFormat, or // JPEGInterchangeFormatLength fields, record the current stream // position for backpatching if (tagNumber == BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS || tagNumber == BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS || tagNumber == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH) { this.stripOrTileByteCountsPosition = pos; } else if (tagNumber == BaselineTIFFTagSet.TAG_STRIP_OFFSETS || tagNumber == BaselineTIFFTagSet.TAG_TILE_OFFSETS || tagNumber == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) { this.stripOrTileOffsetsPosition = pos; } stream.reset(); // Go to marked position of next field } this.lastPosition = nextSpace; } public long getStripOrTileByteCountsPosition() { return stripOrTileByteCountsPosition; } public long getStripOrTileOffsetsPosition() { return stripOrTileOffsetsPosition; } public long getLastPosition() { return lastPosition; } void setPositions(long stripOrTileOffsetsPosition, long stripOrTileByteCountsPosition, long lastPosition) { this.stripOrTileOffsetsPosition = stripOrTileOffsetsPosition; this.stripOrTileByteCountsPosition = stripOrTileByteCountsPosition; this.lastPosition = lastPosition; } /** * Returns a {@code TIFFIFD} wherein all fields from the * {@code BaselineTIFFTagSet} are copied by value and all other * fields copied by reference. */ public TIFFIFD getShallowClone() { // Get the baseline TagSet. TIFFTagSet baselineTagSet = BaselineTIFFTagSet.getInstance(); // If the baseline TagSet is not included just return. List<TIFFTagSet> tagSetList = getTagSetList(); if(!tagSetList.contains(baselineTagSet)) { return this; } // Create a new object. TIFFIFD shallowClone = new TIFFIFD(tagSetList, getParentTag()); // Get the tag numbers in the baseline set. Set<Integer> baselineTagNumbers = baselineTagSet.getTagNumbers(); // Iterate over the fields in this IFD. Iterator<TIFFField> fields = iterator(); while(fields.hasNext()) { // Get the next field. TIFFField field = fields.next(); // Get its tag number. Integer tagNumber = Integer.valueOf(field.getTagNumber()); // Branch based on membership in baseline set. TIFFField fieldClone; if(baselineTagNumbers.contains(tagNumber)) { // Copy by value. Object fieldData = field.getData(); int fieldType = field.getType(); try { switch (fieldType) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: case TIFFTag.TIFF_UNDEFINED: fieldData = ((byte[])fieldData).clone(); break; case TIFFTag.TIFF_ASCII: fieldData = ((String[])fieldData).clone(); break; case TIFFTag.TIFF_SHORT: fieldData = ((char[])fieldData).clone(); break; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: fieldData = ((long[])fieldData).clone(); break; case TIFFTag.TIFF_RATIONAL: fieldData = ((long[][])fieldData).clone(); break; case TIFFTag.TIFF_SSHORT: fieldData = ((short[])fieldData).clone(); break; case TIFFTag.TIFF_SLONG: fieldData = ((int[])fieldData).clone(); break; case TIFFTag.TIFF_SRATIONAL: fieldData = ((int[][])fieldData).clone(); break; case TIFFTag.TIFF_FLOAT: fieldData = ((float[])fieldData).clone(); break; case TIFFTag.TIFF_DOUBLE: fieldData = ((double[])fieldData).clone(); break; default: // Shouldn't happen but do nothing ... } } catch(Exception e) { // Ignore it and copy by reference ... } fieldClone = new TIFFField(field.getTag(), fieldType, field.getCount(), fieldData); } else { // Copy by reference. fieldClone = field; } // Add the field to the clone. shallowClone.addTIFFField(fieldClone); } // Set positions. shallowClone.setPositions(stripOrTileOffsetsPosition, stripOrTileByteCountsPosition, lastPosition); return shallowClone; } }
⏎ com/sun/imageio/plugins/tiff/TIFFIFD.java
Or download all of them as a single archive file:
File name: java.desktop-17.0.5-src.zip File size: 9152233 bytes Release date: 2022-09-13 Download
⇒ JDK 17 java.instrument.jmod - Instrument Module
2023-09-16, 33417👍, 0💬
Popular Posts:
JDK 11 java.sql.jmod is the JMOD file for JDK 11 SQL (Structured Query Language) module. JDK 11 SQL ...
Apache Axis2 is the core engine for Web services. It is a complete re-design and re-write of the wid...
Saxon is an open source product available under the Mozilla Public License. It provides implementati...
How to read XML document with XML Schema validation from socket connections with the socket\DelayedI...
What Is fop.jar? I got it from the fop-2.7-bin.zip. fop.jar in fop-2.7-bin.zip is the JAR file for F...