in endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java [1236:1362]
final boolean validateMandatoryTags() throws DataStoreContentException {
if (isValidated) return false;
if (imageWidth < 0) throw missingTag((short) TAG_IMAGE_WIDTH);
if (imageHeight < 0) throw missingTag((short) TAG_IMAGE_LENGTH);
final short offsetsTag, byteCountsTag;
switch (tileTagFamily) {
case JPEG: // Handled as strips.
case STRIP: {
if (tileWidth < 0) tileWidth = Math.toIntExact(imageWidth);
if (tileHeight < 0) tileHeight = Math.toIntExact(imageHeight);
offsetsTag = TAG_STRIP_OFFSETS;
byteCountsTag = TAG_STRIP_BYTE_COUNTS;
break;
}
case TILE: {
offsetsTag = TAG_TILE_OFFSETS;
byteCountsTag = TAG_TILE_BYTE_COUNTS;
break;
}
default: {
throw new DataStoreContentException(reader.resources().getString(
Resources.Keys.InconsistentTileStrip_1, filename()));
}
}
if (tileOffsets == null) {
throw missingTag(offsetsTag);
}
if (samplesPerPixel == 0) {
samplesPerPixel = 1;
missingTag((short) TAG_SAMPLES_PER_PIXEL, 1, false, false);
}
if (bitsPerSample == 0) {
bitsPerSample = 1;
missingTag((short) TAG_BITS_PER_SAMPLE, 1, false, false);
}
if (colorMap != null) {
ensureSameLength((short) TAG_COLOR_MAP, (short) TAG_BITS_PER_SAMPLE, colorMap.size(), 3 * (1 << bitsPerSample));
}
if (sampleFormat != FLOAT) {
long minValue, maxValue;
if (sampleFormat == UNSIGNED) {
minValue = 0L;
maxValue = -1L; // All bits set to 1.
} else {
minValue = Long.MIN_VALUE;
maxValue = Long.MAX_VALUE;
}
final int shift = Long.SIZE - bitsPerSample;
if (shift >= 0 && shift < Long.SIZE) {
minValue >>>= shift;
maxValue >>>= shift;
if (minValue < maxValue) { // Exclude the unsigned long case since we cannot represent it.
minValues = extremum(minValues, Vector.createSequence(minValue, 0, samplesPerPixel), false);
maxValues = extremum(maxValues, Vector.createSequence(maxValue, 0, samplesPerPixel), true);
}
}
}
/*
* All of tile width, height and length information should be provided. But if only one of them is missing,
* we can compute it provided that the file does not use any compression method. If there is a compression,
* then we set a bit for preventing the `switch` block to perform a calculation but we let the code performs
* the other checks in order to get an exception thrown with a better message.
*/
int missing = !isPlanar && compression.equals(Compression.NONE) ? 0 : 0b1000;
if (tileWidth < 0) missing |= 0b0001;
if (tileHeight < 0) missing |= 0b0010;
if (tileByteCounts == null) missing |= 0b0100;
switch (missing) {
case 0:
case 0b1000: { // Every thing is ok.
break;
}
case 0b0001: { // Compute missing tile width.
tileWidth = computeTileSize(tileHeight);
missingTag((short) TAG_TILE_WIDTH, tileWidth, true, true);
break;
}
case 0b0010: { // Compute missing tile height.
tileHeight = computeTileSize(tileWidth);
missingTag((short) TAG_TILE_LENGTH, tileHeight, true, true);
break;
}
case 0b0100: { // Compute missing tile byte count in uncompressed case.
final long tileByteCount = pixelToByteCount(Math.multiplyExact(tileWidth, tileHeight));
if (tileByteCount == 0) {
throw missingTag(byteCountsTag);
}
final long[] tileByteCountArray = new long[tileOffsets.size()];
Arrays.fill(tileByteCountArray, tileByteCount);
tileByteCounts = Vector.create(tileByteCountArray, true);
missingTag(byteCountsTag, tileByteCount, true, true);
break;
}
default: {
final short tag;
switch (Integer.lowestOneBit(missing)) {
case 0b0001: tag = TAG_TILE_WIDTH; break;
case 0b0010: tag = TAG_TILE_LENGTH; break;
default: tag = byteCountsTag; break;
}
throw missingTag(tag);
}
}
/*
* Report an error if the tile offset and tile byte count vectors do not have the same length.
* Then ensure that the number of tiles is equal to the expected number.
*/
ensureSameLength(byteCountsTag, offsetsTag, tileByteCounts.size(), tileOffsets.size());
long expectedCount = getNumTiles();
if (isPlanar) {
expectedCount = Math.multiplyExact(expectedCount, samplesPerPixel);
}
final int actualCount = Math.min(tileOffsets.size(), tileByteCounts.size());
if (actualCount != expectedCount) {
throw new DataStoreContentException(reader.resources().getString(Resources.Keys.UnexpectedTileCount_3,
filename(), expectedCount, actualCount));
}
/*
* If a "grid to CRS" conversion has been specified with only the scale factor,
* we need to compute the translation terms now.
*/
if (referencing != null && !referencing.validateMandatoryTags()) {
listeners.warning(missingTag((short) TAG_MODEL_TIE_POINT));
}
isValidated = true;
return true;
}