Autopsy  4.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ImageUtils.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2012-16 Basis Technology Corp.
5  *
6  * Copyright 2012 42six Solutions.
7  * Contact: aebadirad <at> 42six <dot> com
8  * Project Contact/Architect: carrier <at> sleuthkit <dot> org
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 package org.sleuthkit.autopsy.coreutils;
23 
24 import com.google.common.collect.ImmutableSortedSet;
25 import com.google.common.io.Files;
26 import java.awt.Image;
27 import java.awt.image.BufferedImage;
28 import java.io.BufferedInputStream;
29 import java.io.File;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.nio.file.Paths;
33 import java.text.MessageFormat;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.Iterator;
39 import java.util.List;
40 import static java.util.Objects.nonNull;
41 import java.util.SortedSet;
42 import java.util.TreeSet;
43 import java.util.concurrent.ExecutionException;
44 import java.util.concurrent.Executor;
45 import java.util.concurrent.Executors;
46 import java.util.logging.Level;
47 import javafx.concurrent.Task;
48 import javafx.embed.swing.SwingFXUtils;
49 import javax.annotation.Nonnull;
50 import javax.annotation.Nullable;
51 import javax.imageio.IIOException;
52 import javax.imageio.ImageIO;
53 import javax.imageio.ImageReadParam;
54 import javax.imageio.ImageReader;
55 import javax.imageio.event.IIOReadProgressListener;
56 import javax.imageio.stream.ImageInputStream;
57 import org.apache.commons.lang3.ObjectUtils;
58 import org.apache.commons.lang3.StringUtils;
59 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
60 import org.opencv.core.Core;
61 import org.openide.util.NbBundle;
66 import org.sleuthkit.datamodel.AbstractFile;
67 import org.sleuthkit.datamodel.Content;
68 import org.sleuthkit.datamodel.ReadContentInputStream;
69 import org.sleuthkit.datamodel.TskCoreException;
70 
75 public class ImageUtils {
76 
77  private static final Logger LOGGER = Logger.getLogger(ImageUtils.class.getName());
78 
82  private static final String FORMAT = "png"; //NON-NLS
83 
84  public static final int ICON_SIZE_SMALL = 50;
85  public static final int ICON_SIZE_MEDIUM = 100;
86  public static final int ICON_SIZE_LARGE = 200;
87 
88  private static final BufferedImage DEFAULT_THUMBNAIL;
89 
90  private static final List<String> GIF_EXTENSION_LIST = Arrays.asList("gif");
91  private static final SortedSet<String> GIF_MIME_SET = ImmutableSortedSet.copyOf(new String[]{"image/gif"});
92 
93  private static final List<String> SUPPORTED_IMAGE_EXTENSIONS = new ArrayList<>();
94  private static final SortedSet<String> SUPPORTED_IMAGE_MIME_TYPES;
95 
96  private static final boolean openCVLoaded;
97 
98  static {
99  ImageIO.scanForPlugins();
100  BufferedImage tempImage;
101  try {
102  tempImage = ImageIO.read(ImageUtils.class.getResourceAsStream("/org/sleuthkit/autopsy/images/file-icon.png"));//NON-NLS
103  } catch (IOException ex) {
104  LOGGER.log(Level.SEVERE, "Failed to load default icon.", ex); //NON-NLS
105  tempImage = null;
106  }
107  DEFAULT_THUMBNAIL = tempImage;
108 
109  //load opencv libraries
110  boolean openCVLoadedTemp;
111  try {
112  System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
113  if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")) { //NON-NLS
114  System.loadLibrary("opencv_ffmpeg248_64"); //NON-NLS
115  } else {
116  System.loadLibrary("opencv_ffmpeg248"); //NON-NLS
117  }
118 
119  openCVLoadedTemp = true;
120  } catch (UnsatisfiedLinkError e) {
121  openCVLoadedTemp = false;
122  LOGGER.log(Level.SEVERE, "OpenCV Native code library failed to load", e); //NON-NLS
123  //TODO: show warning bubble
124 
125  }
126 
127  openCVLoaded = openCVLoadedTemp;
128  SUPPORTED_IMAGE_EXTENSIONS.addAll(Arrays.asList(ImageIO.getReaderFileSuffixes()));
129  SUPPORTED_IMAGE_EXTENSIONS.add("tec"); // Add JFIF .tec files
130  SUPPORTED_IMAGE_MIME_TYPES = new TreeSet<>(Arrays.asList(ImageIO.getReaderMIMETypes()));
131  /*
132  * special cases and variants that we support, but don't get registered
133  * with ImageIO automatically
134  */
135  SUPPORTED_IMAGE_MIME_TYPES.addAll(Arrays.asList(
136  "image/x-rgb", //NON-NLS
137  "image/x-ms-bmp", //NON-NLS
138  "image/x-portable-graymap", //NON-NLS
139  "image/x-portable-bitmap", //NON-NLS
140  "application/x-123")); //TODO: is this correct? -jm //NON-NLS
141  SUPPORTED_IMAGE_MIME_TYPES.removeIf("application/octet-stream"::equals); //NON-NLS
142  }
143 
148 
152  private static final Executor imageSaver
153  = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder()
154  .namingPattern("thumbnail-saver-%d").build()); //NON-NLS
155 
156  public static List<String> getSupportedImageExtensions() {
157  return Collections.unmodifiableList(SUPPORTED_IMAGE_EXTENSIONS);
158  }
159 
160  public static SortedSet<String> getSupportedImageMimeTypes() {
161  return Collections.unmodifiableSortedSet(SUPPORTED_IMAGE_MIME_TYPES);
162  }
163 
170  public static Image getDefaultThumbnail() {
171  return DEFAULT_THUMBNAIL;
172  }
173 
184  public static boolean thumbnailSupported(Content content) {
185 
186  if (!(content instanceof AbstractFile)) {
187  return false;
188  }
189  AbstractFile file = (AbstractFile) content;
190 
192  || isImageThumbnailSupported(file);
193  }
194 
203  public static boolean isImageThumbnailSupported(AbstractFile file) {
204  return isMediaThumbnailSupported(file, "image/", SUPPORTED_IMAGE_MIME_TYPES, SUPPORTED_IMAGE_EXTENSIONS) || hasImageFileHeader(file);//NON-NLS
205  }
206 
215  public static boolean isGIF(AbstractFile file) {
216  return isMediaThumbnailSupported(file, null, GIF_MIME_SET, GIF_EXTENSION_LIST);
217  }
218 
239  static boolean isMediaThumbnailSupported(AbstractFile file, String mimeTypePrefix, final Collection<String> supportedMimeTypes, final List<String> supportedExtension) {
240  if (false == file.isFile() || file.getSize() <= 0) {
241  return false;
242  }
243 
244  String extension = file.getNameExtension();
245 
246  if (StringUtils.isNotBlank(extension) && supportedExtension.contains(extension)) {
247  return true;
248  } else {
249  try {
250  String mimeType = getFileTypeDetector().detect(file);
251  if (StringUtils.isNotBlank(mimeTypePrefix) && mimeType.startsWith(mimeTypePrefix)) {
252  return true;
253  }
254  return supportedMimeTypes.contains(mimeType);
255  } catch (FileTypeDetectorInitException | TskCoreException ex) {
256  LOGGER.log(Level.SEVERE, "Error determining MIME type of " + getContentPathSafe(file), ex);//NON-NLS
257  return false;
258  }
259  }
260  }
261 
274  if (fileTypeDetector == null) {
275  fileTypeDetector = new FileTypeDetector();
276  }
277  return fileTypeDetector;
278  }
279 
290  public static BufferedImage getThumbnail(Content content, int iconSize) {
291  if (content instanceof AbstractFile) {
292  AbstractFile file = (AbstractFile) content;
293 
294  Task<javafx.scene.image.Image> thumbnailTask = newGetThumbnailTask(file, iconSize, true);
295  thumbnailTask.run();
296  try {
297  return SwingFXUtils.fromFXImage(thumbnailTask.get(), null);
298  } catch (InterruptedException | ExecutionException ex) {
299  LOGGER.log(Level.WARNING, "Failed to get thumbnail for {0}: " + ex.toString(), getContentPathSafe(content)); //NON-NLS
300  return DEFAULT_THUMBNAIL;
301  }
302  } else {
303  return DEFAULT_THUMBNAIL;
304  }
305  }
306 
318  @Nullable
319  public static File getCachedThumbnailFile(Content content, int iconSize) {
320  getThumbnail(content, iconSize);
321  return getCachedThumbnailLocation(content.getId());
322  }
323 
334  private static File getCachedThumbnailLocation(long fileID) {
335  try {
336  String cacheDirectory = Case.getCurrentCase().getCacheDirectory();
337  return Paths.get(cacheDirectory, "thumbnails", fileID + ".png").toFile(); //NON-NLS
338  } catch (IllegalStateException e) {
339  LOGGER.log(Level.WARNING, "Could not get cached thumbnail location. No case is open."); //NON-NLS
340  return null;
341  }
342  }
343 
352  public static boolean hasImageFileHeader(AbstractFile file) {
353  return isJpegFileHeader(file) || isPngFileHeader(file);
354  }
355 
363  public static boolean isJpegFileHeader(AbstractFile file) {
364  if (file.getSize() < 100) {
365  return false;
366  }
367 
368  try {
369  byte[] fileHeaderBuffer = readHeader(file, 2);
370  /*
371  * Check for the JPEG header. Since Java bytes are signed, we cast
372  * them to an int first.
373  */
374  return (((fileHeaderBuffer[0] & 0xff) == 0xff) && ((fileHeaderBuffer[1] & 0xff) == 0xd8));
375  } catch (TskCoreException ex) {
376  //ignore if can't read the first few bytes, not a JPEG
377  return false;
378  }
379  }
380 
390  private static long getJfifStartOfImageOffset(AbstractFile file) {
391  byte[] fileHeaderBuffer;
392  long length;
393  try {
394  length = file.getSize();
395  if (length % 2 != 0) {
396  length -= 1; // Make it an even number so we can parse two bytes at a time
397  }
398  if (length >= 1024) {
399  length = 1024;
400  }
401  fileHeaderBuffer = readHeader(file, (int) length); // read up to first 1024 bytes
402  } catch (TskCoreException ex) {
403  // Couldn't read header. Let ImageIO try it.
404  return 0;
405  }
406 
407  if (fileHeaderBuffer != null) {
408  for (int index = 0; index < length; index += 2) {
409  // Look for Start Of Image marker and return the index when it's found
410  if ((fileHeaderBuffer[index] == (byte) 0xFF) && (fileHeaderBuffer[index + 1] == (byte) 0xD8)) {
411  return index;
412  }
413  }
414  }
415 
416  // Didn't match JFIF. Let ImageIO try to open it from offset 0.
417  return 0;
418  }
419 
427  public static boolean isPngFileHeader(AbstractFile file) {
428  if (file.getSize() < 10) {
429  return false;
430  }
431 
432  try {
433  byte[] fileHeaderBuffer = readHeader(file, 8);
434  /*
435  * Check for the png header. Since Java bytes are signed, we cast
436  * them to an int first.
437  */
438  return (((fileHeaderBuffer[1] & 0xff) == 0x50) && ((fileHeaderBuffer[2] & 0xff) == 0x4E)
439  && ((fileHeaderBuffer[3] & 0xff) == 0x47) && ((fileHeaderBuffer[4] & 0xff) == 0x0D)
440  && ((fileHeaderBuffer[5] & 0xff) == 0x0A) && ((fileHeaderBuffer[6] & 0xff) == 0x1A)
441  && ((fileHeaderBuffer[7] & 0xff) == 0x0A));
442 
443  } catch (TskCoreException ex) {
444  //ignore if can't read the first few bytes, not an png
445  return false;
446  }
447  }
448 
449  private static byte[] readHeader(AbstractFile file, int buffLength) throws TskCoreException {
450  byte[] fileHeaderBuffer = new byte[buffLength];
451  int bytesRead = file.read(fileHeaderBuffer, 0, buffLength);
452 
453  if (bytesRead != buffLength) {
454  //ignore if can't read the first few bytes, not an image
455  throw new TskCoreException("Could not read " + buffLength + " bytes from " + file.getName());//NON-NLS
456  }
457  return fileHeaderBuffer;
458  }
459 
470  static public int getImageWidth(AbstractFile file) throws IOException {
471  return getImageProperty(file,
472  "ImageIO could not determine width of {0}: ", //NON-NLS
473  imageReader -> imageReader.getWidth(0)
474  );
475  }
476 
487  static public int getImageHeight(AbstractFile file) throws IOException {
488  return getImageProperty(file,
489  "ImageIO could not determine height of {0}: ", //NON-NLS
490  imageReader -> imageReader.getHeight(0)
491  );
492  }
493 
502  @FunctionalInterface
503  private static interface PropertyExtractor<T> {
504 
505  public T extract(ImageReader reader) throws IOException;
506  }
507 
529  private static <T> T getImageProperty(AbstractFile file, final String errorTemplate, PropertyExtractor<T> propertyExtractor) throws IOException {
530  try (InputStream inputStream = new BufferedInputStream(new ReadContentInputStream(file));) {
531  try (ImageInputStream input = ImageIO.createImageInputStream(inputStream)) {
532  if (input == null) {
533  IIOException iioException = new IIOException("Could not create ImageInputStream.");
534  LOGGER.log(Level.WARNING, errorTemplate + iioException.toString(), getContentPathSafe(file));
535  throw iioException;
536  }
537  Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
538 
539  if (readers.hasNext()) {
540  ImageReader reader = readers.next();
541  reader.setInput(input);
542  try {
543 
544  return propertyExtractor.extract(reader);
545  } catch (IOException ex) {
546  LOGGER.log(Level.WARNING, errorTemplate + ex.toString(), getContentPathSafe(file));
547  throw ex;
548  } finally {
549  reader.dispose();
550  }
551  } else {
552  IIOException iioException = new IIOException("No ImageReader found.");
553  LOGGER.log(Level.WARNING, errorTemplate + iioException.toString(), getContentPathSafe(file));
554 
555  throw iioException;
556  }
557  }
558  }
559  }
560 
577  public static Task<javafx.scene.image.Image> newGetThumbnailTask(AbstractFile file, int iconSize, boolean defaultOnFailure) {
578  return new GetThumbnailTask(file, iconSize, defaultOnFailure);
579  }
580 
584  static private class GetThumbnailTask extends ReadImageTaskBase {
585 
586  private static final String FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION = "Failed to read {0} for thumbnail generation."; //NON-NLS
587 
588  private final int iconSize;
589  private final File cacheFile;
590  private final boolean defaultOnFailure;
591 
592  @NbBundle.Messages({"# {0} - file name",
593  "GetOrGenerateThumbnailTask.loadingThumbnailFor=Loading thumbnail for {0}",
594  "# {0} - file name",
595  "GetOrGenerateThumbnailTask.generatingPreviewFor=Generating preview for {0}"})
596  private GetThumbnailTask(AbstractFile file, int iconSize, boolean defaultOnFailure) {
597  super(file);
598  updateMessage(Bundle.GetOrGenerateThumbnailTask_loadingThumbnailFor(file.getName()));
599  this.iconSize = iconSize;
600  this.defaultOnFailure = defaultOnFailure;
601  this.cacheFile = getCachedThumbnailLocation(file.getId());
602  }
603 
604  @Override
605  protected javafx.scene.image.Image call() throws Exception {
606  if (isGIF(file)) {
607  return readImage();
608  }
609  if (isCancelled()) {
610  return null;
611  }
612  // If a thumbnail file is already saved locally, just read that.
613  if (cacheFile != null && cacheFile.exists()) {
614  try {
615  BufferedImage cachedThumbnail = ImageIO.read(cacheFile);
616  if (nonNull(cachedThumbnail) && cachedThumbnail.getWidth() == iconSize) {
617  return SwingFXUtils.toFXImage(cachedThumbnail, null);
618  }
619  } catch (Exception ex) {
620  LOGGER.log(Level.WARNING, "ImageIO had a problem reading the cached thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
621  cacheFile.delete(); //since we can't read the file we might as well delete it.
622  }
623  }
624 
625  if (isCancelled()) {
626  return null;
627  }
628 
629  //There was no correctly-sized cached thumbnail so make one.
630  BufferedImage thumbnail = null;
632  if (openCVLoaded) {
633  updateMessage(Bundle.GetOrGenerateThumbnailTask_generatingPreviewFor(file.getName()));
634  thumbnail = VideoUtils.generateVideoThumbnail(file, iconSize);
635  }
636  if (null == thumbnail) {
637  if (defaultOnFailure) {
638  thumbnail = DEFAULT_THUMBNAIL;
639  } else {
640  throw new IIOException("Failed to generate a thumbnail for " + getContentPathSafe(file));//NON-NLS
641  }
642  }
643 
644  } else {
645  //read the image into a buffered image.
646  //TODO: I don't like this, we just converted it from BufferedIamge to fx Image -jm
647  BufferedImage bufferedImage = SwingFXUtils.fromFXImage(readImage(), null);
648  if (null == bufferedImage) {
649  String msg = MessageFormat.format(FAILED_TO_READ_IMAGE_FOR_THUMBNAIL_GENERATION, getContentPathSafe(file));
650  LOGGER.log(Level.WARNING, msg);
651  throw new IIOException(msg);
652  }
653  updateProgress(-1, 1);
654 
655  //resize, or if that fails, crop it
656  try {
657  thumbnail = ScalrWrapper.resizeFast(bufferedImage, iconSize);
658  } catch (IllegalArgumentException | OutOfMemoryError e) {
659  // if resizing does not work due to extreme aspect ratio or oom, crop the image instead.
660  LOGGER.log(Level.WARNING, "Cropping {0}, because it could not be scaled: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
661 
662  final int height = bufferedImage.getHeight();
663  final int width = bufferedImage.getWidth();
664  if (iconSize < height || iconSize < width) {
665  final int cropHeight = Math.min(iconSize, height);
666  final int cropWidth = Math.min(iconSize, width);
667  try {
668  thumbnail = ScalrWrapper.cropImage(bufferedImage, cropWidth, cropHeight);
669  } catch (Exception cropException) {
670  LOGGER.log(Level.WARNING, "Could not crop {0}: " + cropException.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
671  }
672  }
673  } catch (Exception e) {
674  LOGGER.log(Level.WARNING, "Could not scale {0}: " + e.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
675  throw e;
676  }
677  }
678 
679  if (isCancelled()) {
680  return null;
681  }
682 
683  updateProgress(-1, 1);
684 
685  //if we got a valid thumbnail save it
686  if ((cacheFile != null) && thumbnail != null && DEFAULT_THUMBNAIL != thumbnail) {
687  saveThumbnail(thumbnail);
688  }
689 
690  return SwingFXUtils.toFXImage(thumbnail, null);
691  }
692 
698  private void saveThumbnail(BufferedImage thumbnail) {
699  imageSaver.execute(() -> {
700  try {
701  Files.createParentDirs(cacheFile);
702  if (cacheFile.exists()) {
703  cacheFile.delete();
704  }
705  ImageIO.write(thumbnail, FORMAT, cacheFile);
706  } catch (IllegalArgumentException | IOException ex) {
707  LOGGER.log(Level.WARNING, "Could not write thumbnail for {0}: " + ex.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
708  }
709  });
710  }
711  }
712 
726  public static Task<javafx.scene.image.Image> newReadImageTask(AbstractFile file) {
727  return new ReadImageTask(file);
728  }
729 
733  @NbBundle.Messages({
734  "# {0} - file name",
735  "ReadImageTask.mesageText=Reading image: {0}"})
736  static private class ReadImageTask extends ReadImageTaskBase {
737 
738  ReadImageTask(AbstractFile file) {
739  super(file);
740  updateMessage(Bundle.ReadImageTask_mesageText(file.getName()));
741  }
742 
743  @Override
744  protected javafx.scene.image.Image call() throws Exception {
745  return readImage();
746  }
747  }
748 
752  static private abstract class ReadImageTaskBase extends Task<javafx.scene.image.Image> implements IIOReadProgressListener {
753 
754  private static final String IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT = "ImageIO could not read {0}. It may be unsupported or corrupt"; //NON-NLS
755  final AbstractFile file;
756 // private ImageReader reader;
757 
758  ReadImageTaskBase(AbstractFile file) {
759  this.file = file;
760  }
761 
762  protected javafx.scene.image.Image readImage() throws IOException {
763  if (ImageUtils.isGIF(file)) {
764  //use JavaFX to directly read GIF to preserve potential animation
765  javafx.scene.image.Image image = new javafx.scene.image.Image(new BufferedInputStream(new ReadContentInputStream(file)));
766  if (image.isError() == false) {
767  return image;
768  }
769  } else if (file.getNameExtension().equalsIgnoreCase("tec")) { //NON-NLS
770  ReadContentInputStream readContentInputStream = new ReadContentInputStream(file);
771  // Find first Start Of Image marker
772  readContentInputStream.seek(getJfifStartOfImageOffset(file));
773  //use JavaFX to directly read .tec files
774  javafx.scene.image.Image image = new javafx.scene.image.Image(new BufferedInputStream(readContentInputStream));
775  if (image.isError() == false) {
776  return image;
777  }
778  }
779  //fall through to default image reading code if there was an error
780  if (isCancelled()) {
781  return null;
782  }
783 
784  return getImageProperty(file, "ImageIO could not read {0}: ",
785  imageReader -> {
786  imageReader.addIIOReadProgressListener(ReadImageTaskBase.this);
787  /*
788  * This is the important part, get or create a
789  * ImageReadParam, create a destination image to hold
790  * the decoded result, then pass that image with the
791  * param.
792  */
793  ImageReadParam param = imageReader.getDefaultReadParam();
794  BufferedImage bufferedImage = imageReader.getImageTypes(0).next().createBufferedImage(imageReader.getWidth(0), imageReader.getHeight(0));
795  param.setDestination(bufferedImage);
796  try {
797  bufferedImage = imageReader.read(0, param); //should always be same bufferedImage object
798  } catch (IOException iOException) {
799  LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT + ": " + iOException.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
800  } finally {
801  imageReader.removeIIOReadProgressListener(ReadImageTaskBase.this);
802  }
803  if (isCancelled()) {
804  return null;
805  }
806  return SwingFXUtils.toFXImage(bufferedImage, null);
807  }
808  );
809  }
810 
811  @Override
812  public void imageProgress(ImageReader reader, float percentageDone) {
813  //update this task with the progress reported by ImageReader.read
814  updateProgress(percentageDone, 100);
815  if (isCancelled()) {
816  reader.removeIIOReadProgressListener(this);
817  reader.abort();
818  reader.dispose();
819  }
820  }
821 
822  @Override
823  protected void succeeded() {
824  super.succeeded();
825  try {
826  javafx.scene.image.Image fxImage = get();
827  if (fxImage == null) {
828  LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT, ImageUtils.getContentPathSafe(file));
829  } else if (fxImage.isError()) {
830  //if there was somekind of error, log it
831  LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT + ": " + ObjectUtils.toString(fxImage.getException()), ImageUtils.getContentPathSafe(file));
832  }
833  } catch (InterruptedException | ExecutionException ex) {
834  failed();
835  }
836  }
837 
838  @Override
839  protected void failed() {
840  super.failed();
841  LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT + ": " + ObjectUtils.toString(getException()), ImageUtils.getContentPathSafe(file));
842  }
843 
844  @Override
845  public void imageComplete(ImageReader source) {
846  updateProgress(100, 100);
847  }
848 
849  @Override
850  public void imageStarted(ImageReader source, int imageIndex) {
851  }
852 
853  @Override
854  public void sequenceStarted(ImageReader source, int minIndex) {
855  }
856 
857  @Override
858  public void sequenceComplete(ImageReader source) {
859  }
860 
861  @Override
862  public void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex) {
863  }
864 
865  @Override
866  public void thumbnailProgress(ImageReader source, float percentageDone) {
867  }
868 
869  @Override
870  public void thumbnailComplete(ImageReader source) {
871  }
872 
873  @Override
874  public void readAborted(ImageReader source) {
875  }
876  }
877 
886  static String getContentPathSafe(Content content) {
887  try {
888  return content.getUniquePath();
889  } catch (TskCoreException tskCoreException) {
890  String contentName = content.getName();
891  LOGGER.log(Level.SEVERE, "Failed to get unique path for " + contentName, tskCoreException); //NON-NLS
892  return contentName;
893  }
894  }
895 
904  @Deprecated
905  public static Image getDefaultIcon() {
906  return getDefaultThumbnail();
907  }
908 
919  @Deprecated
920 
921  public static File getFile(long id) {
922  return getCachedThumbnailLocation(id);
923  }
924 
938  @Nonnull
939  @Deprecated
940  public static BufferedImage getIcon(Content content, int iconSize) {
941  return getThumbnail(content, iconSize);
942  }
943 
958  @Nullable
959  @Deprecated
960  public static File getIconFile(Content content, int iconSize) {
961  return getCachedThumbnailFile(content, iconSize);
962 
963  }
964 
965 }
static File getIconFile(Content content, int iconSize)
static boolean isGIF(AbstractFile file)
static final List< String > SUPPORTED_IMAGE_EXTENSIONS
Definition: ImageUtils.java:93
static boolean isPngFileHeader(AbstractFile file)
static boolean thumbnailSupported(Content content)
void imageProgress(ImageReader reader, float percentageDone)
static Task< javafx.scene.image.Image > newGetThumbnailTask(AbstractFile file, int iconSize, boolean defaultOnFailure)
void imageStarted(ImageReader source, int imageIndex)
static synchronized BufferedImage resizeFast(BufferedImage input, int size)
static FileTypeDetector fileTypeDetector
static final SortedSet< String > GIF_MIME_SET
Definition: ImageUtils.java:91
static Task< javafx.scene.image.Image > newReadImageTask(AbstractFile file)
void sequenceStarted(ImageReader source, int minIndex)
static boolean isJpegFileHeader(AbstractFile file)
void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex)
GetThumbnailTask(AbstractFile file, int iconSize, boolean defaultOnFailure)
static int getImageHeight(AbstractFile file)
void thumbnailProgress(ImageReader source, float percentageDone)
static List< String > getSupportedImageExtensions()
static final BufferedImage DEFAULT_THUMBNAIL
Definition: ImageUtils.java:88
static long getJfifStartOfImageOffset(AbstractFile file)
static File getCachedThumbnailFile(Content content, int iconSize)
static boolean hasImageFileHeader(AbstractFile file)
static byte[] readHeader(AbstractFile file, int buffLength)
static File getCachedThumbnailLocation(long fileID)
synchronized static Logger getLogger(String name)
Definition: Logger.java:161
static int getImageWidth(AbstractFile file)
static< T > T getImageProperty(AbstractFile file, final String errorTemplate, PropertyExtractor< T > propertyExtractor)
static boolean isImageThumbnailSupported(AbstractFile file)
static BufferedImage getThumbnail(Content content, int iconSize)
static final List< String > GIF_EXTENSION_LIST
Definition: ImageUtils.java:90
synchronized static FileTypeDetector getFileTypeDetector()
static BufferedImage getIcon(Content content, int iconSize)
static boolean isVideoThumbnailSupported(AbstractFile file)
Definition: VideoUtils.java:97
static final SortedSet< String > SUPPORTED_IMAGE_MIME_TYPES
Definition: ImageUtils.java:94
static synchronized BufferedImage cropImage(BufferedImage input, int width, int height)
static SortedSet< String > getSupportedImageMimeTypes()

Copyright © 2012-2016 Basis Technology. Generated on: Mon Jan 2 2017
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.