Merge pull request #2624 from millmanorama/2404-animated-GIFs

2404 animated GIFs
This commit is contained in:
Richard Cordovano 2017-03-22 13:15:43 -04:00 committed by GitHub
commit 3f02a3f03e

View File

@ -160,7 +160,7 @@ public class ImageUtils {
private static FileTypeDetector fileTypeDetector; private static FileTypeDetector fileTypeDetector;
/** /**
*Thread/Executor that saves generated thumbnails to disk in the background * Thread/Executor that saves generated thumbnails to disk in the background
*/ */
private static final Executor imageSaver private static final Executor imageSaver
= Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder() = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder()
@ -297,12 +297,27 @@ public class ImageUtils {
* @param content the content to generate a thumbnail for * @param content the content to generate a thumbnail for
* @param iconSize the size (one side of a square) in pixels to generate * @param iconSize the size (one side of a square) in pixels to generate
* *
* @return a thumbnail for the given image or a default one if there was a * @return A thumbnail for the given image or a default one if there was a
* problem making a thumbnail. * problem making a thumbnail.
*/ */
public static BufferedImage getThumbnail(Content content, int iconSize) { public static BufferedImage getThumbnail(Content content, int iconSize) {
if (content instanceof AbstractFile) { if (content instanceof AbstractFile) {
AbstractFile file = (AbstractFile) content; AbstractFile file = (AbstractFile) content;
if (ImageUtils.isGIF(file)) {
/*
* Intercepting the image reading code for GIFs here allows us
* to rescale easily, but we lose animations.
*/
try (BufferedInputStream bufferedReadContentStream = getBufferedReadContentStream(file);) {
final BufferedImage image = ImageIO.read(bufferedReadContentStream);
if (image != null) {
return ScalrWrapper.resizeHighQuality(image, iconSize, iconSize);
}
} catch (IOException iOException) {
LOGGER.log(Level.WARNING, "Failed to get thumbnail for " + getContentPathSafe(content), iOException); //NON-NLS
}
return DEFAULT_THUMBNAIL;
}
Task<javafx.scene.image.Image> thumbnailTask = newGetThumbnailTask(file, iconSize, true); Task<javafx.scene.image.Image> thumbnailTask = newGetThumbnailTask(file, iconSize, true);
thumbnailTask.run(); thumbnailTask.run();
@ -310,11 +325,22 @@ public class ImageUtils {
return SwingFXUtils.fromFXImage(thumbnailTask.get(), null); return SwingFXUtils.fromFXImage(thumbnailTask.get(), null);
} catch (InterruptedException | ExecutionException ex) { } catch (InterruptedException | ExecutionException ex) {
LOGGER.log(Level.WARNING, "Failed to get thumbnail for " + getContentPathSafe(content), ex); //NON-NLS LOGGER.log(Level.WARNING, "Failed to get thumbnail for " + getContentPathSafe(content), ex); //NON-NLS
return DEFAULT_THUMBNAIL;
} }
} else {
return DEFAULT_THUMBNAIL;
} }
return DEFAULT_THUMBNAIL;
}
/**
* Get a BufferedInputStream wrapped around a ReadContentStream for the
* given AbstractFile.
*
* @param file The AbstractFile to get a stream for.
*
* @return A BufferedInputStream wrapped around a ReadContentStream for the
* given AbstractFile
*/
private static BufferedInputStream getBufferedReadContentStream(AbstractFile file) {
return new BufferedInputStream(new ReadContentInputStream(file));
} }
/** /**
@ -334,12 +360,12 @@ public class ImageUtils {
} }
/** /**
* Get the location of the cached thumbnail for a file with the given fileID * Get the location,as a java File, of the cached thumbnail for an file with
* as a java File. The returned File may not exist on disk yet. * the given fileID . The returned File may not exist on disk yet.
* *
* @param fileID the fileID to get the cached thumbnail location for * @param fileID the fileID to get the cached thumbnail location for
* *
* @return a File object representing the location of the cached thumbnail. * @return A File object representing the location of the cached thumbnail.
* This file may not actually exist(yet). Returns null if there was * This file may not actually exist(yet). Returns null if there was
* any problem getting the file, such as no case was open. * any problem getting the file, such as no case was open.
*/ */
@ -542,33 +568,30 @@ public class ImageUtils {
* @see #getImageHeight(org.sleuthkit.datamodel.AbstractFile) * @see #getImageHeight(org.sleuthkit.datamodel.AbstractFile)
*/ */
private static <T> T getImageProperty(AbstractFile file, final String errorTemplate, PropertyExtractor<T> propertyExtractor) throws IOException { private static <T> T getImageProperty(AbstractFile file, final String errorTemplate, PropertyExtractor<T> propertyExtractor) throws IOException {
try (InputStream inputStream = new BufferedInputStream(new ReadContentInputStream(file));) { try (InputStream inputStream = getBufferedReadContentStream(file);
try (ImageInputStream input = ImageIO.createImageInputStream(inputStream)) { ImageInputStream input = ImageIO.createImageInputStream(inputStream)) {
if (input == null) { if (input == null) {
IIOException iioException = new IIOException("Could not create ImageInputStream."); IIOException iioException = new IIOException("Could not create ImageInputStream.");
LOGGER.log(Level.WARNING, errorTemplate + iioException.toString(), getContentPathSafe(file)); LOGGER.log(Level.WARNING, errorTemplate + iioException.toString(), getContentPathSafe(file));
throw iioException; throw iioException;
} }
Iterator<ImageReader> readers = ImageIO.getImageReaders(input); Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
if (readers.hasNext()) { if (readers.hasNext()) {
ImageReader reader = readers.next(); ImageReader reader = readers.next();
reader.setInput(input); reader.setInput(input);
try { try {
return propertyExtractor.extract(reader);
return propertyExtractor.extract(reader); } catch (IOException ex) {
} catch (IOException ex) { LOGGER.log(Level.WARNING, errorTemplate + ex.toString(), getContentPathSafe(file));
LOGGER.log(Level.WARNING, errorTemplate + ex.toString(), getContentPathSafe(file)); throw ex;
throw ex; } finally {
} finally { reader.dispose();
reader.dispose();
}
} else {
IIOException iioException = new IIOException("No ImageReader found.");
LOGGER.log(Level.WARNING, errorTemplate + iioException.toString(), getContentPathSafe(file));
throw iioException;
} }
} else {
IIOException iioException = new IIOException("No ImageReader found.");
LOGGER.log(Level.WARNING, errorTemplate + iioException.toString(), getContentPathSafe(file));
throw iioException;
} }
} }
} }
@ -785,7 +808,7 @@ public class ImageUtils {
protected javafx.scene.image.Image readImage() throws IOException { protected javafx.scene.image.Image readImage() throws IOException {
if (ImageUtils.isGIF(file)) { if (ImageUtils.isGIF(file)) {
//use JavaFX to directly read GIF to preserve potential animation //use JavaFX to directly read GIF to preserve potential animation
javafx.scene.image.Image image = new javafx.scene.image.Image(new BufferedInputStream(new ReadContentInputStream(file))); javafx.scene.image.Image image = new javafx.scene.image.Image(getBufferedReadContentStream(file));
if (image.isError() == false) { if (image.isError() == false) {
return image; return image;
} }