use of it.geosolutions.imageio.plugins.tiff.TIFFField in project imageio-ext by geosolutions-it.
the class TIFFImageReader method initializeFromMetadata.
/**
* Initializes these instance variables from the image metadata:
* <pre>
* compression
* width
* height
* samplesPerPixel
* numBands
* colorMap
* photometricInterpretation
* sampleFormat
* bitsPerSample
* extraSamples
* tileOrStripWidth
* tileOrStripHeight
* </pre>
*/
private void initializeFromMetadata() {
if (initialized)
return;
//
// Planar Config
//
this.planarConfiguration = getPlanarConfiguration();
//
// Compression
//
compression = getCompression();
// Whether key dimensional information is absent.
boolean isMissingDimension = false;
//
// ImageWidth -> width
//
TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH);
if (f != null) {
this.width = f.getAsInt(0);
} else {
processWarningOccurred("ImageWidth field is missing.");
isMissingDimension = true;
}
//
// ImageLength -> height
//
f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_LENGTH);
if (f != null) {
this.height = f.getAsInt(0);
} else {
processWarningOccurred("ImageLength field is missing.");
isMissingDimension = true;
}
//
// Tiling
//
tileOrStripWidth = getTileOrStripWidth();
tileOrStripHeight = getTileOrStripHeight();
f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_WIDTH);
isImageTiled = f != null;
//
// SamplesPerPixel
//
f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL);
if (f != null) {
samplesPerPixel = f.getAsInt(0);
} else {
samplesPerPixel = 1;
isMissingDimension = true;
}
// If any dimension is missing and there is a JPEG stream available
// get the information from it.
int defaultBitDepth = 1;
if (isMissingDimension && (f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT)) != null) {
Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName("JPEG");
if (iter != null && iter.hasNext()) {
ImageReader jreader = iter.next();
try {
stream.mark();
stream.seek(f.getAsLong(0));
jreader.setInput(stream);
if (imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH) == null) {
this.width = jreader.getWidth(0);
}
if (imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_LENGTH) == null) {
this.height = jreader.getHeight(0);
}
ImageTypeSpecifier imageType = jreader.getRawImageType(0);
if (imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL) == null) {
this.samplesPerPixel = imageType.getSampleModel().getNumBands();
}
stream.reset();
defaultBitDepth = imageType.getColorModel().getComponentSize(0);
} catch (IOException e) {
// Ignore it and proceed: an error will occur later.
}
jreader.dispose();
}
}
if (samplesPerPixel < 1) {
processWarningOccurred("Samples per pixel < 1!");
}
//
// SamplesPerPixel -> numBands
//
numBands = samplesPerPixel;
//
// ColorMap
//
this.colorMap = null;
f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_COLOR_MAP);
if (f != null) {
// Grab color map
colorMap = f.getAsChars();
}
//
// PhotometricInterpretation
//
f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
if (f == null) {
if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE || compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_4 || compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) {
processWarningOccurred("PhotometricInterpretation field is missing; " + "assuming WhiteIsZero");
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO;
} else if (this.colorMap != null) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR;
} else if (samplesPerPixel == 3 || samplesPerPixel == 4) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB;
} else {
processWarningOccurred("PhotometricInterpretation field is missing; " + "assuming BlackIsZero");
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO;
}
} else {
photometricInterpretation = f.getAsInt(0);
}
//
// SampleFormat
//
boolean replicateFirst = false;
int first = -1;
f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT);
sampleFormat = new int[samplesPerPixel];
replicateFirst = false;
if (f == null) {
replicateFirst = true;
first = BaselineTIFFTagSet.SAMPLE_FORMAT_UNDEFINED;
} else if (f.getCount() != samplesPerPixel) {
replicateFirst = true;
first = f.getAsInt(0);
}
for (int i = 0; i < samplesPerPixel; i++) {
sampleFormat[i] = replicateFirst ? first : f.getAsInt(i);
if (sampleFormat[i] != BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER && sampleFormat[i] != BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER && sampleFormat[i] != BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT && sampleFormat[i] != BaselineTIFFTagSet.SAMPLE_FORMAT_UNDEFINED) {
processWarningOccurred("Illegal value for SAMPLE_FORMAT, assuming SAMPLE_FORMAT_UNDEFINED");
sampleFormat[i] = BaselineTIFFTagSet.SAMPLE_FORMAT_UNDEFINED;
}
}
//
// BitsPerSample
//
f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
this.bitsPerSample = new int[samplesPerPixel];
replicateFirst = false;
if (f == null) {
replicateFirst = true;
first = defaultBitDepth;
} else if (f.getCount() != samplesPerPixel) {
replicateFirst = true;
first = f.getAsInt(0);
}
for (int i = 0; i < samplesPerPixel; i++) {
// Replicate initial value if not enough values provided
bitsPerSample[i] = replicateFirst ? first : f.getAsInt(i);
if (DEBUG) {
System.out.println("bitsPerSample[" + i + "] = " + bitsPerSample[i]);
}
}
//
// ExtraSamples
//
this.extraSamples = null;
f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES);
if (f != null) {
extraSamples = f.getAsInts();
}
//
// NoData (if any, leveraging on GDAL tag)
//
this.noData = null;
f = imageMetadata.getTIFFField(PrivateTIFFTagSet.TAG_GDAL_NODATA);
if (f != null) {
String value = f.getAsString(0);
if ("nan".equalsIgnoreCase(value)) {
noData = Double.NaN;
} else {
noData = Double.parseDouble(value);
}
}
// signal that this image is initialized
initialized = true;
// cache the page info for later reuse
pagesInfo.put(currIndex, new PageInfo(imageMetadata, bigtiff, bitsPerSample, colorMap, compression, height, numBands, photometricInterpretation, width, tileOrStripWidth, tileOrStripHeight, planarConfiguration, isImageTiled, samplesPerPixel, sampleFormat, extraSamples, noData));
}
use of it.geosolutions.imageio.plugins.tiff.TIFFField in project imageio-ext by geosolutions-it.
the class TIFFImageReader method defineDatasetLayout.
/**
* Method used for populating reader's {@link DatasetLayout}
*
* @throws IIOException
*/
private void defineDatasetLayout() throws IIOException {
if (!(layout.getNumInternalOverviews() == -1 && layout.getNumInternalMasks() == -1)) {
return;
}
// Initialize
readHeader();
// Getting Image Number
int numImg;
try {
numImg = getNumImages(true);
} catch (IOException e) {
throw new IIOException(e.getMessage(), e);
}
// Extracting the TIFF Tag NewSubfileType from each Image
int numOverviews = 0;
int numMasks = 0;
int numMaskOverView = 0;
// If not all the Images Metadata have been loaded, loop through images in order to add them
// if(pagesInfo != null && (numImg != pagesInfo.size())){
// Getting current Index which will be restored at the end of the operation
int currentIdx = currIndex;
// Loop the images
for (int i = 0; i < numImg; i++) {
// Seek to the image index i
seekToImage(i);
// Getting PageInfo
PageInfo info = pagesInfo.get(i);
// Getting Metadata
TIFFImageMetadata metadata = info.imageMetadata.get();
// Getting TIFF TAG_NEW_SUBFILE_TYPE
TIFFField f = metadata.getTIFFField(BaselineTIFFTagSet.TAG_NEW_SUBFILE_TYPE);
// Checking if exists
if (f != null) {
Object data = f.getData();
// Checking if the data is LONG
if (data instanceof long[]) {
long ldata = ((long[]) data)[0];
numMasks += ((ldata & BaselineTIFFTagSet.NEW_SUBFILE_TYPE_TRANSPARENCY) > 0) ? 1 : 0;
numOverviews += ((ldata & BaselineTIFFTagSet.NEW_SUBFILE_TYPE_REDUCED_RESOLUTION) > 0) ? 1 : 0;
numMaskOverView += ((ldata & BaselineTIFFTagSet.NEW_SUBFILE_TYPE_REDUCED_RESOLUTION) > 0 && (ldata & BaselineTIFFTagSet.NEW_SUBFILE_TYPE_TRANSPARENCY) > 0) ? 1 : 0;
}
}
}
// Restore current Index
seekToImage(currentIdx);
// Setting Masks number and Overviews number
layout.setNumInternalMasks(numMasks);
layout.setNumInternalOverviews(numOverviews - numMaskOverView);
}
use of it.geosolutions.imageio.plugins.tiff.TIFFField in project imageio-ext by geosolutions-it.
the class TIFFImageReader method read.
public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
prepareRead(imageIndex, param);
// prepare for reading
this.theImage = getDestination(param, getImageTypes(imageIndex), width, height, noData);
srcXSubsampling = imageReadParam.getSourceXSubsampling();
srcYSubsampling = imageReadParam.getSourceYSubsampling();
Point p = imageReadParam.getDestinationOffset();
dstXOffset = p.x;
dstYOffset = p.y;
// This could probably be made more efficient...
Rectangle srcRegion = new Rectangle(0, 0, 0, 0);
Rectangle destRegion = new Rectangle(0, 0, 0, 0);
computeRegions(imageReadParam, width, height, theImage, srcRegion, destRegion);
// Initial source pixel, taking source region and source
// subsamplimg offsets into account
sourceXOffset = srcRegion.x;
sourceYOffset = srcRegion.y;
pixelsToRead = destRegion.width * destRegion.height;
pixelsRead = 0;
processImageStarted(imageIndex);
processImageProgress(0.0f);
tilesAcross = (width + tileOrStripWidth - 1) / tileOrStripWidth;
tilesDown = (height + tileOrStripHeight - 1) / tileOrStripHeight;
// Attempt to get decompressor and color converted from the read param
TIFFColorConverter colorConverter = null;
if (imageReadParam instanceof TIFFImageReadParam) {
TIFFImageReadParam tparam = (TIFFImageReadParam) imageReadParam;
this.decompressor = tparam.getTIFFDecompressor();
colorConverter = tparam.getColorConverter();
}
// If we didn't find one, use a standard decompressor
if (this.decompressor == null) {
if (compression == BaselineTIFFTagSet.COMPRESSION_NONE) {
// Get the fillOrder field.
TIFFField fillOrderField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER);
// Set the decompressor based on the fill order.
if (fillOrderField != null && fillOrderField.getAsInt(0) == 2) {
this.decompressor = new TIFFLSBDecompressor();
} else {
this.decompressor = new TIFFNullDecompressor();
}
} else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) {
// Try to create the codecLib decompressor.
if (PackageUtil.isCodecLibAvailable()) {
try {
this.decompressor = new TIFFCodecLibFaxDecompressor(compression);
if (DEBUG) {
System.out.println("Using codecLib T.6 decompressor");
}
} catch (RuntimeException re) {
if (DEBUG) {
System.out.println(re);
}
}
}
// Fall back to the Java decompressor.
if (this.decompressor == null) {
if (DEBUG) {
System.out.println("Using Java T.6 decompressor");
}
this.decompressor = new TIFFFaxDecompressor();
}
} else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_4) {
if (PackageUtil.isCodecLibAvailable()) {
// Try to create the codecLib decompressor.
try {
this.decompressor = new TIFFCodecLibFaxDecompressor(compression);
if (DEBUG) {
System.out.println("Using codecLib T.4 decompressor");
}
} catch (RuntimeException re) {
if (DEBUG) {
System.out.println(re);
}
}
}
// Fall back to the Java decompressor.
if (this.decompressor == null) {
if (DEBUG) {
System.out.println("Using Java T.4 decompressor");
}
this.decompressor = new TIFFFaxDecompressor();
}
} else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE) {
this.decompressor = new TIFFFaxDecompressor();
} else if (compression == BaselineTIFFTagSet.COMPRESSION_PACKBITS) {
if (DEBUG) {
System.out.println("Using TIFFPackBitsDecompressor");
}
this.decompressor = new TIFFPackBitsDecompressor();
} else if (compression == BaselineTIFFTagSet.COMPRESSION_LZW) {
if (DEBUG) {
System.out.println("Using TIFFLZWDecompressor");
}
TIFFField predictorField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_PREDICTOR);
int predictor = ((predictorField == null) ? BaselineTIFFTagSet.PREDICTOR_NONE : predictorField.getAsInt(0));
this.decompressor = new TIFFLZWDecompressor(predictor);
} else if (compression == BaselineTIFFTagSet.COMPRESSION_JPEG) {
this.decompressor = new TIFFJPEGDecompressor();
} else if (compression == BaselineTIFFTagSet.COMPRESSION_ZLIB || compression == BaselineTIFFTagSet.COMPRESSION_DEFLATE) {
TIFFField predictorField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_PREDICTOR);
int predictor = ((predictorField == null) ? BaselineTIFFTagSet.PREDICTOR_NONE : predictorField.getAsInt(0));
this.decompressor = new TIFFDeflateDecompressor(predictor);
} else if (compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) {
TIFFField JPEGProcField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_PROC);
if (JPEGProcField == null) {
processWarningOccurred("JPEGProc field missing; assuming baseline sequential JPEG process.");
} else if (JPEGProcField.getAsInt(0) != BaselineTIFFTagSet.JPEG_PROC_BASELINE) {
throw new IIOException("Old-style JPEG supported for baseline sequential JPEG process only!");
}
this.decompressor = new TIFFOldJPEGDecompressor();
// throw new IIOException("Old-style JPEG not supported!");
} else {
throw new IIOException("Unsupported compression type (tag number = " + compression + ")!");
}
if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR && compression != BaselineTIFFTagSet.COMPRESSION_JPEG && compression != BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) {
boolean convertYCbCrToRGB = theImage.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_RGB;
TIFFDecompressor wrappedDecompressor = this.decompressor instanceof TIFFNullDecompressor ? null : this.decompressor;
this.decompressor = new TIFFYCbCrDecompressor(wrappedDecompressor, convertYCbCrToRGB);
}
}
if (DEBUG) {
System.out.println("\nDecompressor class = " + decompressor.getClass().getName() + "\n");
}
if (colorConverter == null) {
if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB && theImage.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_RGB) {
colorConverter = new TIFFCIELabColorConverter();
} else if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR && !(this.decompressor instanceof TIFFYCbCrDecompressor) && compression != BaselineTIFFTagSet.COMPRESSION_JPEG && compression != BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) {
colorConverter = new TIFFYCbCrColorConverter(imageMetadata);
}
}
decompressor.setReader(this);
decompressor.setMetadata(imageMetadata);
decompressor.setImage(theImage);
decompressor.setPhotometricInterpretation(photometricInterpretation);
decompressor.setCompression(compression);
decompressor.setSamplesPerPixel(samplesPerPixel);
decompressor.setBitsPerSample(bitsPerSample);
decompressor.setSampleFormat(sampleFormat);
decompressor.setExtraSamples(extraSamples);
decompressor.setColorMap(colorMap);
decompressor.setColorConverter(colorConverter);
decompressor.setSourceXOffset(sourceXOffset);
decompressor.setSourceYOffset(sourceYOffset);
decompressor.setSubsampleX(srcXSubsampling);
decompressor.setSubsampleY(srcYSubsampling);
decompressor.setDstXOffset(dstXOffset);
decompressor.setDstYOffset(dstYOffset);
decompressor.setSourceBands(sourceBands);
decompressor.setDestinationBands(destinationBands);
// Compute bounds on the tile indices for this source region.
int minTileX = TIFFImageWriter.XToTileX(srcRegion.x, 0, tileOrStripWidth);
int minTileY = TIFFImageWriter.YToTileY(srcRegion.y, 0, tileOrStripHeight);
int maxTileX = TIFFImageWriter.XToTileX(srcRegion.x + srcRegion.width - 1, 0, tileOrStripWidth);
int maxTileY = TIFFImageWriter.YToTileY(srcRegion.y + srcRegion.height - 1, 0, tileOrStripHeight);
boolean isAbortRequested = false;
if (planarConfiguration == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) {
decompressor.setPlanar(true);
int[] sb = new int[1];
int[] db = new int[1];
for (int tj = minTileY; tj <= maxTileY; tj++) {
for (int ti = minTileX; ti <= maxTileX; ti++) {
for (int band = 0; band < numBands; band++) {
sb[0] = sourceBands[band];
decompressor.setSourceBands(sb);
db[0] = destinationBands[band];
decompressor.setDestinationBands(db);
// doing any actual decoding.
if (abortRequested()) {
isAbortRequested = true;
break;
}
decodeTile(ti, tj, band);
}
if (isAbortRequested)
break;
reportProgress();
}
if (isAbortRequested)
break;
}
} else {
for (int tj = minTileY; tj <= maxTileY; tj++) {
for (int ti = minTileX; ti <= maxTileX; ti++) {
// doing any actual decoding.
if (abortRequested()) {
isAbortRequested = true;
break;
}
decodeTile(ti, tj, -1);
reportProgress();
}
if (isAbortRequested)
break;
}
}
if (isAbortRequested) {
processReadAborted();
} else {
processImageComplete();
}
return theImage;
}
use of it.geosolutions.imageio.plugins.tiff.TIFFField in project imageio-ext by geosolutions-it.
the class TIFFImageReader method getPlanarConfiguration.
private int getPlanarConfiguration() {
TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION);
if (f != null) {
int planarConfigurationValue = f.getAsInt(0);
if (planarConfigurationValue == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) {
// ascertain whether the value is correctly Planar.
if (compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG && imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) != null) {
// JPEG interchange format cannot have
// PlanarConfiguration value Chunky so reset.
processWarningOccurred("PlanarConfiguration \"Planar\" value inconsistent with JPEGInterchangeFormat; resetting to \"Chunky\".");
planarConfigurationValue = BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY;
} else {
TIFFField offsetField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS);
if (offsetField == null) {
// Tiles
offsetField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS);
int tw = tileOrStripWidth;
int th = tileOrStripHeight;
int tAcross = (width + tw - 1) / tw;
int tDown = (height + th - 1) / th;
int tilesPerImage = tAcross * tDown;
long[] offsetArray = offsetField.getAsLongs();
if (offsetArray != null && offsetArray.length == tilesPerImage) {
// Length of offsets array is
// TilesPerImage for Chunky and
// SamplesPerPixel*TilesPerImage for Planar.
processWarningOccurred("PlanarConfiguration \"Planar\" value inconsistent with TileOffsets field value count; resetting to \"Chunky\".");
planarConfigurationValue = BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY;
}
} else {
// Strips
int rowsPerStrip = tileOrStripHeight;
int stripsPerImage = (height + rowsPerStrip - 1) / rowsPerStrip;
long[] offsetArray = offsetField.getAsLongs();
if (offsetArray != null && offsetArray.length == stripsPerImage) {
// Length of offsets array is
// StripsPerImage for Chunky and
// SamplesPerPixel*StripsPerImage for Planar.
processWarningOccurred("PlanarConfiguration \"Planar\" value inconsistent with StripOffsets field value count; resetting to \"Chunky\".");
planarConfigurationValue = BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY;
}
}
}
}
return planarConfigurationValue;
}
return BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY;
}
use of it.geosolutions.imageio.plugins.tiff.TIFFField in project imageio-ext by geosolutions-it.
the class TIFFImageReader method getTileOrStripHeight.
// Returns tile height if image is tiled, else strip height
private int getTileOrStripHeight() {
int h = -1;
TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_LENGTH);
if (f != null) {
h = f.getAsInt(0);
} else {
f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP);
// Default for ROWS_PER_STRIP is 2^32 - 1, i.e., infinity
h = (f == null) ? -1 : f.getAsInt(0);
}
return (h == -1) ? height : h;
}
Aggregations