From 0c830f085f9e8c13fbe60d0b392d0987b0bb4821 Mon Sep 17 00:00:00 2001 From: Trilok Shahi Date: Thu, 13 Mar 2014 10:33:16 -0400 Subject: [PATCH] dataresult thumbnail code --- .../DataResultViewerThumbnail.java | 2 +- .../corecomponents/ThumbnailViewChildren.java | 4 +- .../autopsy/coreutils/ImageUtils.java | 161 +++++++++++++++++- 3 files changed, 154 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index c1557e37dd..4788a15a38 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -295,7 +295,7 @@ import org.sleuthkit.datamodel.TskCoreException; if (selectedNode == null) { return false; } - + Children ch = selectedNode.getChildren(); for (Node n : ch.getNodes()) { if (ThumbnailViewChildren.isSupported(n)) { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java index d8131ccbc6..b8ec86a54e 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java @@ -122,8 +122,6 @@ class ThumbnailViewChildren extends Children.Keys { pageNums[i] = i + 1; } setKeys(pageNums); - - } @Override @@ -208,4 +206,4 @@ class ThumbnailViewChildren extends Children.Keys { } } } -} +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java index f1fa3714ee..ae1d1cc33b 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java @@ -25,15 +25,20 @@ package org.sleuthkit.autopsy.coreutils; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; +import javafx.embed.swing.SwingFXUtils; import javax.imageio.ImageIO; import javax.swing.ImageIcon; +import org.apache.commons.io.FilenameUtils; import org.openide.util.Exceptions; +import org.sleuthkit.autopsy.actions.AddContentTagAction; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corelibs.ScalrWrapper; import org.sleuthkit.datamodel.AbstractFile; @@ -43,7 +48,10 @@ import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; - +import org.opencv.highgui.VideoCapture; +import org.opencv.core.Mat; +import org.opencv.core.Range; +import org.opencv.core.Core; /** * Utilities for creating and manipulating thumbnail and icon images. * @author jwallace @@ -53,9 +61,13 @@ public class ImageUtils { public static final int ICON_SIZE_MEDIUM = 100; public static final int ICON_SIZE_LARGE = 200; private static final Logger logger = Logger.getLogger(ImageUtils.class.getName()); - private static final Image DEFAULT_ICON = new ImageIcon("/org/sleuthkit/autopsy/images/file-icon.png").getImage(); - private static final List SUPP_EXTENSIONS = Arrays.asList(ImageIO.getReaderFileSuffixes()); - private static final List SUPP_MIME_TYPES = Arrays.asList(ImageIO.getReaderMIMETypes()); + private static final Image DEFAULT_ICON = new ImageIcon("/org/sleuthkit/autopsy/images/home_tree.png").getImage(); + private static List SUPP_EXTENSIONS = new ArrayList<>(Arrays.asList(ImageIO.getReaderFileSuffixes())); //final + private static List SUPP_MIME_TYPES = new ArrayList<>(Arrays.asList(ImageIO.getReaderMIMETypes())); // final + private static List VIDEO_SUPP_EXTENSIONS = new ArrayList<>(); //final + private static List VIDEO_SUPP_MIME_TYPES = new ArrayList<>(); // final + + private static boolean temp_add =false; /** * Get the default Icon, which is the icon for a file. * @return @@ -71,6 +83,30 @@ public class ImageUtils { * @return */ public static boolean thumbnailSupported(Content content) { + if (temp_add == false) { + SUPP_EXTENSIONS.add("avi"); + SUPP_EXTENSIONS.add("mp4"); + SUPP_EXTENSIONS.add("wmv"); + SUPP_MIME_TYPES.add("video/avi"); + SUPP_MIME_TYPES.add("video/msvideo"); + SUPP_MIME_TYPES.add("video/x-msvideo"); + SUPP_MIME_TYPES.add("video/mp4"); + SUPP_MIME_TYPES.add("video/x-ms-wmv"); + SUPP_MIME_TYPES.add("video/x-msvideo"); + SUPP_MIME_TYPES.add("video/x-msvideo"); + + VIDEO_SUPP_EXTENSIONS.add("avi"); + VIDEO_SUPP_EXTENSIONS.add("mp4"); + VIDEO_SUPP_EXTENSIONS.add("wmv"); + VIDEO_SUPP_MIME_TYPES.add("video/avi"); + VIDEO_SUPP_MIME_TYPES.add("video/msvideo"); + VIDEO_SUPP_MIME_TYPES.add("video/x-msvideo"); + VIDEO_SUPP_MIME_TYPES.add("video/mp4"); + VIDEO_SUPP_MIME_TYPES.add("video/x-ms-wmv"); + VIDEO_SUPP_MIME_TYPES.add("video/x-msvideo"); + VIDEO_SUPP_MIME_TYPES.add("video/x-msvideo"); + temp_add=true; + } if (content instanceof AbstractFile == false) { return false; } @@ -116,7 +152,8 @@ public class ImageUtils { * @return */ public static Image getIcon(Content content, int iconSize) { - Image icon; + Image icon=null; + // If a thumbnail file is already saved locally File file = getFile(content.getId()); if (file.exists()) { @@ -134,8 +171,24 @@ public class ImageUtils { icon = DEFAULT_ICON; } } else { // Make a new icon - icon = generateAndSaveIcon(content, iconSize); + AbstractFile f = (AbstractFile) content; + final String extension = f.getNameExtension(); + + // if we have an extension, check it + if (extension.equals("") == false) + { + // Note: thumbnail generator only supports JPG, GIF, and PNG for now + if (VIDEO_SUPP_EXTENSIONS.contains(extension)) + { + icon = generateVideoIcon(content, iconSize); + } + } + else + { + icon = generateAndSaveIcon(content, iconSize); + } } + if (icon==null) return DEFAULT_ICON; return icon; } @@ -198,7 +251,73 @@ public class ImageUtils { } return false; } - + private static Image generateVideoIcon(Content content, int iconSize) { + Image icon = null; + + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + try { + if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")){ + System.loadLibrary("opencv_ffmpeg248_64"); + }else{ + System.loadLibrary("opencv_ffmpeg248"); + System.loadLibrary("opencv_java248"); + + } + }catch (UnsatisfiedLinkError e) { + Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "OpenCV Native code library failed to load", e); + return DEFAULT_ICON; + } + File file = getFile(content.getId()); + String ext = FilenameUtils.getExtension(file.getName()).toLowerCase(); + String fileName = content.getId() + (ext.isEmpty() ? "" : "." + ext); + java.io.File jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), fileName); + Image image; //final image to be returned + + try { + //createFile(); // create entire file in TEMP + copyFileUsingStream(content,jFile); //create small file in TEMP + }catch(Exception ex) { + return DEFAULT_ICON; + } + fileName = jFile.toString(); //store filepath as String + VideoCapture videoFile= new VideoCapture(); // will contain the video + + if(!videoFile.open(fileName))return DEFAULT_ICON; + double fps = videoFile.get(5); // gets frame per second + double totalFrames = videoFile.get(7); // gets total frames + if (fps==0||totalFrames==0 ) return DEFAULT_ICON; + double milliseconds= 1000*(totalFrames/fps); //total milliseconds + if (milliseconds <= 0) return DEFAULT_ICON; + + + Mat mat = new Mat(); + double timestamp = (milliseconds<500)? milliseconds:500; //default time to check for is 500ms, unless the files is extremely small + + if(!videoFile.set(0,timestamp))return DEFAULT_ICON; + if(! videoFile.read(mat)) return DEFAULT_ICON; //if the image for some reason is bad, return default icon + + byte[] data = new byte[mat.rows()*mat.cols()*(int)(mat.elemSize())]; + mat.get(0, 0, data); + + if (mat.channels() == 3) + { + for (int k = 0; k < data.length; k += 3) + { + byte temp = data[k]; + data[k] = data[k + 2]; + data[k + 2] = temp; + } + } + BufferedImage B_image = new BufferedImage(mat.cols(), mat.rows(), BufferedImage.TYPE_3BYTE_BGR); + B_image.getRaster().setDataElements(0, 0, mat.cols(), mat.rows(), data); + + // image = SwingFXUtils.toFXImage(B_image, null); //convert bufferedImage to Image + videoFile.release(); // close the file + // if (image==null) return DEFAULT_ICON; + if (B_image==null) return DEFAULT_ICON; + else return B_image; + + } private static Image generateAndSaveIcon(Content content, int iconSize) { Image icon = null; @@ -215,7 +334,8 @@ public class ImageUtils { } } catch (IOException ex) { logger.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex); - } + } + if (icon==null) return DEFAULT_ICON; return icon; } @@ -233,7 +353,7 @@ public class ImageUtils { return null; } BufferedImage biScaled = ScalrWrapper.resizeFast(bi, iconSize); - + if (biScaled==null) return (BufferedImage)DEFAULT_ICON; return biScaled; } catch (OutOfMemoryError e) { logger.log(Level.WARNING, "Could not scale image (too large): " + content.getName(), e); @@ -251,5 +371,28 @@ public class ImageUtils { } } + + } + public static void copyFileUsingStream(Content file,java.io.File jFile) throws IOException { + InputStream is = new ReadContentInputStream(file); + // copy the file data to the temporary file + + OutputStream os = new FileOutputStream(jFile); + byte[] buffer = new byte[8192]; + int length; + int counter =0; + try { + while ((length = is.read(buffer)) != -1) + { + os.write(buffer, 0, length); + counter++; + if (counter== 63) break; //after saving 500 KB (63*8192) + } + + } finally { + is.close(); + os.close(); + } + } }