boolean localTileCache= false;
//
// creating the image to use for the successive
// subsampling
//
TileCache baseTC= JAI.getDefaultInstance().getTileCache();
if(baseTC==null){
localTileCache=true;
final long tilecacheSize=super.getTileCacheSize();
baseTC= JAI.createTileCache();
baseTC.setMemoryCapacity(tilecacheSize);
baseTC.setMemoryThreshold(0.75f);
}
//
// CHECK INPUT DIRECTORIES/FILES
//
if(sourcePath==null)
{
fireEvent("Provided sourcePath is null", overallProgress);
return;
}
// getting an image input stream to the file
final File file = new File(sourcePath);
final File[] files;
int numFiles = 1;
StringBuilder message;
if(!file.canRead()||!file.exists())
{
fireEvent("Provided file "+file.getAbsolutePath()+" cannot be read or does not exist", 100);
return;
}
if (file.isDirectory()) {
if(wildcardString==null){
fireEvent("Provided wildcardString is null", 100);
return;
}
final FileFilter fileFilter = new WildcardFileFilter(wildcardString);
files = file.listFiles(fileFilter);
numFiles = files.length;
if (numFiles <= 0) {
message = new StringBuilder("No files to process!");
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(message.toString());
}
fireEvent(message.toString(), 100);
}
} else
files = new File[] { file };
if(files==null||files.length==0)
{
fireEvent("Unable to find input files for the provided wildcard "+wildcardString+ " and input path "+sourcePath,100);
return;
}
// setting step
overallProgressStep=100*1.0/numFiles;
//
// ADDING OVERVIEWS TO ALL FOUND FILES
//
for (fileBeingProcessed = 0; fileBeingProcessed < numFiles; fileBeingProcessed++) {
message = new StringBuilder("Managing file ").append(fileBeingProcessed).append(" of ").append(files[fileBeingProcessed]).append(" files");
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(message.toString());
}
overallProgress=overallProgressStep*fileBeingProcessed;
fireEvent(message.toString(),overallProgress);
if (getStopThread()) {
message = new StringBuilder("Stopping requested at file ").append(fileBeingProcessed).append(" of ").append(numFiles).append(" files");
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(message.toString());
}
fireEvent(message.toString(),overallProgress);
return;
}
ImageInputStream stream=null;
ImageWriter writer =null;
ImageOutputStream streamOut=null;
RenderedOp currentImage = null;
RenderedOp newImage=null;
try{
File localFile=files[fileBeingProcessed];
//
// get a stream
//
stream = ImageIO.createImageInputStream(localFile);
if(stream==null)
{
message = new StringBuilder("Unable to create an input stream for file").append(files[fileBeingProcessed]);
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.severe(message.toString());
}
fireEvent(message.toString(),overallProgress);
break;
}
stream.mark();
//
// get a reader
//
final Iterator<ImageReader> it = ImageIO.getImageReaders(stream);
if (!it.hasNext()) {
message = new StringBuilder("Unable to find a reader for file").append(files[fileBeingProcessed]);
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.severe(message.toString());
}
fireEvent(message.toString(),overallProgress);
break;
}
final ImageReader reader = (ImageReader) it.next();
stream.reset();
stream.mark();
// is it a geotiff reader or not?
if(!reader.getFormatName().toLowerCase().startsWith("tif")){
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.info("Discarding input file "+files[fileBeingProcessed] + " since it is not a proper tif file.");
}
continue;
}
//
// set input
//
reader.setInput(stream);
ImageLayout layout = null;
// tiling the image if needed
int actualTileW = reader.getTileWidth(0);
int actualTileH = reader.getTileHeight(0);
if (!reader.isImageTiled(0)||
(reader.isImageTiled(0) && (actualTileH != tileH && tileH != -1)|| (actualTileW != tileW && tileW != -1))) {
message = new StringBuilder("Retiling image ").append(fileBeingProcessed);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(message.toString());
}
fireEvent(message.toString(),
overallProgress);
layout = Utils.createTiledLayout(tileW, tileH, 0, 0);
}
stream.reset();
reader.reset();
reader.dispose();
//
// output image stream
//
if(externalOverviews){
// create a sibling file
localFile= new File(localFile.getParent(),FilenameUtils.getBaseName(localFile.getAbsolutePath())+".tif.ovr");
}
streamOut = ImageIOExt.createImageOutputStream(null, localFile);
if (streamOut == null) {
message = new StringBuilder(
"Unable to acquire an ImageOutputStream for the file ")
.append(files[fileBeingProcessed].toString());
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.severe(message.toString());
}
fireEvent(message.toString(),100);
break;
}
//
// Preparing to write the set of images. First of all I write
// the first image `
//
// getting a writer for this reader
writer = TIFF_IMAGE_WRITER_SPI.createWriterInstance();
writer.setOutput(streamOut);
writer.addIIOWriteProgressListener(writeProgressListener);
writer.addIIOWriteWarningListener(writeProgressListener);
ImageWriteParam param = writer.getDefaultWriteParam();
//
// setting tiling on the first image using writing parameters
//
if (tileH != -1 & tileW != -1) {
param.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
param.setTiling(tileW, tileH, 0, 0);
} else {
param.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
param.setTiling(actualTileW, actualTileH, 0, 0);
}
if (this.compressionScheme != null && !Double.isNaN(compressionRatio)) {
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionType(compressionScheme);
param.setCompressionQuality((float) this.compressionRatio);
}
final RenderingHints newHints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
newHints.add(new RenderingHints(JAI.KEY_TILE_CACHE,baseTC));
// read base image
ParameterBlock pbjRead = new ParameterBlock();
pbjRead.add(stream);
pbjRead.add(Integer.valueOf(0));
pbjRead.add(Boolean.FALSE);
pbjRead.add(Boolean.FALSE);
pbjRead.add(Boolean.FALSE);
pbjRead.add(null);
pbjRead.add(null);
pbjRead.add(null);
pbjRead.add(null);
currentImage = JAI.create("ImageRead", pbjRead,newHints);
message = new StringBuilder("Read original image ").append(fileBeingProcessed);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(message.toString());
}
fireEvent(message.toString(),overallProgress);
int i=0;
//
// OVERVIEWS CYLE
//
for (overviewInProcess = 0; overviewInProcess < numSteps; overviewInProcess++) {
message = new StringBuilder("Subsampling step ").append(overviewInProcess+1).append(" of image ").append(fileBeingProcessed);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(message.toString());
}
fireEvent(message.toString(),overallProgress);
// paranoiac check
if (currentImage.getWidth() / downsampleStep <= 0|| currentImage.getHeight() / downsampleStep <= 0)
break;
// SCALE
// subsampling the input image using the chosen algorithm
final SubsampleAlgorithm algorithm=SubsampleAlgorithm.valueOf(scaleAlgorithm);
switch (algorithm) {
case Average:
newImage = Utils.scaleAverage(currentImage,baseTC,downsampleStep,borderExtender);
break;
case Filtered:
newImage = Utils.filteredSubsample(currentImage,baseTC,downsampleStep,lowPassFilter);
break;
case Bilinear:
newImage = Utils.subsample(currentImage,baseTC,new InterpolationBilinear(),downsampleStep,borderExtender);
break;
case Bicubic:
newImage = Utils.subsample(currentImage,baseTC,new InterpolationBicubic(2),downsampleStep,borderExtender);
break;
case Nearest:
newImage = Utils.subsample(currentImage,baseTC, new InterpolationNearest(),downsampleStep,borderExtender);
break;
default:
throw new IllegalArgumentException("Invalid scaling algorithm "+scaleAlgorithm);//cannot get here
}
//set relevant metadata
IIOMetadata imageMetadata = null;
if (writer instanceof TIFFImageWriter){
imageMetadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(newImage), param);
if (imageMetadata != null)
((TIFFImageMetadata)imageMetadata).addShortOrLongField(BaselineTIFFTagSet.TAG_NEW_SUBFILE_TYPE, BaselineTIFFTagSet.NEW_SUBFILE_TYPE_REDUCED_RESOLUTION);
}
// write out
if(!externalOverviews || i>0)
writer.writeInsert(-1, new IIOImage(newImage, null, imageMetadata), param);
else
writer.write(null,new IIOImage(newImage, null, imageMetadata), param);
message = new StringBuilder("Step ").append(
overviewInProcess+1).append(" of image ").append(
fileBeingProcessed).append(" done!");
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(message.toString());
}
fireEvent(message.toString(),overallProgress);
// switching images
currentImage.dispose(); //dispose old image
currentImage = newImage;
i++;
}
overallProgress=100;
// close message
message = new StringBuilder("Done with image ")
.append(fileBeingProcessed);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(message.toString());
}
fireEvent(message.toString(),overallProgress);
}catch (Throwable e) {
fireException(e);
}finally{
// clean up
// clean caches if they are local
if(localTileCache&&baseTC!=null)
try{
baseTC.flush();
} catch (Exception e) {
}
//
// free everything