package net.coobird.thumbnailator.tasks.io; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; import net.coobird.thumbnailator.ThumbnailParameter; import net.coobird.thumbnailator.tasks.UnsupportedFormatException; import net.coobird.thumbnailator.util.BufferedImages; import net.coobird.thumbnailator.util.ThumbnailatorUtils; /** * An {@link ImageSink} which writes the resulting thumbnail to a file. *
* Under certain circumstances, the destination file can change in the course * of processing. *
* This can occur in cases where the file extension does not
* match the output format set by the {@link #setOutputFormatName(String)}
* method. In this case, the file name will have a file extension corresponding
* to the output format set in the above method to be appended to the file
* name originally provided when instantiating the {@link FileImageSink} object.
*
* @author coobird
*
*/
public class FileImageSink extends AbstractImageSink
* Under certain circumstances, the {@link File} object can be replaced
* in the course of processing. This can occur in cases where the file
* extension has been changed due to incongruence between the extension
* and the desired output format.
*/
private File destinationFile;
private final boolean allowOverwrite;
/**
* Instantiates a {@link FileImageSink} with the file to which the thumbnail
* should be written to.
*
* The output format to use will be determined from the file extension.
* If another format should be used, then the
* {@link #setOutputFormatName(String)} should be called with the desired
* output format name.
*
* When the destination file exists, then this {@code FileImageSink} will
* overwrite the existing file.
*
* @param destinationFile The destination file.
* @throws NullPointerException If the specified file is {@code null}.
*/
public FileImageSink(File destinationFile)
{
this(destinationFile, true);
}
/**
* Instantiates a {@link FileImageSink} with the file to which the thumbnail
* should be written to.
*
* The output format to use will be determined from the file extension.
* If another format should be used, then the
* {@link #setOutputFormatName(String)} should be called with the desired
* output format name.
*
* @param destinationFile The destination file.
* @param allowOverwrite Whether or not the {@code FileImageSink}
* should overwrite the destination file if
* it already exists.
* @throws NullPointerException If the specified file is {@code null}.
*/
public FileImageSink(File destinationFile, boolean allowOverwrite)
{
super();
if (destinationFile == null)
{
throw new NullPointerException("File cannot be null.");
}
this.destinationFile = destinationFile;
this.outputFormat = getExtension(destinationFile);
this.allowOverwrite = allowOverwrite;
}
/**
* Instantiates a {@link FileImageSink} with the file to which the thumbnail
* should be written to.
*
* The output format to use will be determined from the file extension.
* If another format should be used, then the
* {@link #setOutputFormatName(String)} should be called with the desired
* output format name.
*
* When the destination file exists, then this {@code FileImageSink} will
* overwrite the existing file.
*
* @param destinationFilePath The destination file path.
* @throws NullPointerException If the specified file path is {@code null}.
*/
public FileImageSink(String destinationFilePath)
{
this(destinationFilePath, true);
}
/**
* Instantiates a {@link FileImageSink} with the file to which the thumbnail
* should be written to.
*
* The output format to use will be determined from the file extension.
* If another format should be used, then the
* {@link #setOutputFormatName(String)} should be called with the desired
* output format name.
*
* @param destinationFilePath The destination file path.
* @param allowOverwrite Whether or not the {@code FileImageSink}
* should overwrite the destination file if
* it already exists.
* @throws NullPointerException If the specified file path is {@code null}.
*/
public FileImageSink(String destinationFilePath, boolean allowOverwrite)
{
super();
if (destinationFilePath == null)
{
throw new NullPointerException("File cannot be null.");
}
this.destinationFile = new File(destinationFilePath);
this.outputFormat = getExtension(destinationFile);
this.allowOverwrite = allowOverwrite;
}
/**
* Determines whether an specified format name and file extension are
* for the same format.
*
* @param formatName Format name.
* @param fileExtension File extension.
* @return Returns {@code true} if the specified file
* extension is valid for the specified format.
*/
private static boolean isMatchingFormat(String formatName, String fileExtension)
{
if (formatName == null || fileExtension == null)
{
return false;
}
ImageWriter iw;
try
{
iw = ImageIO.getImageWritersByFormatName(formatName).next();
}
catch (NoSuchElementException e)
{
return false;
}
String[] suffixes = iw.getOriginatingProvider().getFileSuffixes();
for (String suffix : suffixes)
{
if (fileExtension.equalsIgnoreCase(suffix))
{
return true;
}
}
return false;
}
/**
* Returns the file extension of the given {@link File}.
*
* @param f The file.
* @return The extension of the file.
*/
private static String getExtension(File f)
{
String fileName = f.getName();
if (
fileName.indexOf('.') != -1
&& fileName.lastIndexOf('.') != fileName.length() - 1
)
{
int lastIndex = fileName.lastIndexOf('.');
return fileName.substring(lastIndex + 1);
}
return null;
}
@Override
public String preferredOutputFormatName()
{
String fileExtension = getExtension(destinationFile);
if (fileExtension != null)
{
Iterator
* If the final destination of the thumbnail changes in the course of
* writing the thumbnail. (For example, if the file extension for the given
* destination did not match the destination file format, then the correct
* file extension could be appended.)
*
* @return the destinationFile
*/
public File getSink()
{
return destinationFile;
}
}