diff --git a/build.gradle b/build.gradle index 165bfb0..f4e9585 100644 --- a/build.gradle +++ b/build.gradle @@ -97,16 +97,23 @@ dependencies { compile group: 'junit', name: 'junit', version: '4.12' compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.6' - testCompile group: "org.loadui", name: "testFx", version: "3.1.2" - testCompile 'org.testfx:testfx-core:4.0.1-alpha' - testRuntime 'org.testfx:openjfx-monocle:1.8.0_20' +// testCompile group: "org.loadui", name: "testFx", version: "3.1.2" +// testCompile 'org.testfx:testfx-core:4.0.1-alpha' +// testRuntime 'org.testfx:openjfx-monocle:1.8.0_20' + testCompile group: 'org.loadui', name: 'testFx', version: '3.1.2' + + testCompile group: 'org.testfx', name: 'testfx-core', version: '4.0.8-alpha' + +} +test { + testLogging.showStandardStreams = true } jfx { mainClass = 'Main' vendor = 'arxa' - //bundler = 'windows.app' -// bundleArguments = [ -// 'runtime': 'C:\\Program Files\\Java\\jdk1.8.0_144\\jre' -// ] + bundler = 'windows.app' + bundleArguments = [ + 'runtime': 'C:\\Program Files\\Java\\jdk1.8.0_144\\jre' + ] } \ No newline at end of file diff --git a/src/main/java/Entities/ApplicationPaths.java b/src/main/java/Entities/ApplicationPaths.java index 4819e03..7b341fd 100644 --- a/src/main/java/Entities/ApplicationPaths.java +++ b/src/main/java/Entities/ApplicationPaths.java @@ -12,6 +12,7 @@ public class ApplicationPaths { public static Caller CALLER; public static String USER_DIR; + public static String TEST_RESOURCES; public static String RESOURCES_NATIVES; public static String RESOURCES_OCR; public static String RESOURCES_OCR_TESSDATA; @@ -32,6 +33,7 @@ public static void setApplicationPaths() CALLER = Caller.IDE; try { USER_DIR = Paths.get(new File(".").getCanonicalPath(),"src","main","resources").toFile().getPath(); + TEST_RESOURCES = Paths.get(new File(".").getCanonicalPath(),"src","test","resources").toFile().getPath(); } catch (IOException e) { System.out.println("Couldn't create IDE directories"); Platform.exit(); diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 5d05530..04837ac 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -18,6 +18,7 @@ public void start(Stage stage) throws Exception Parent root = loader.load(); stage.setTitle("VideoText Extractor"); stage.setScene(new Scene(root, 680, 450)); + stage.setResizable(false); stage.show(); stage.setOnCloseRequest(e -> Platform.exit()); diff --git a/src/main/java/Processors/FileProcessor.java b/src/main/java/Processors/FileProcessor.java index 0c2fcad..44cc5ab 100644 --- a/src/main/java/Processors/FileProcessor.java +++ b/src/main/java/Processors/FileProcessor.java @@ -5,10 +5,13 @@ import Entities.Controllers; import ViewControllers.MainController; import javafx.application.Platform; +import javafx.scene.Node; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.stage.FileChooser; import javafx.stage.Stage; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.SystemUtils; import org.jetbrains.annotations.Contract; import org.opencv.core.Core; @@ -27,6 +30,7 @@ public class FileProcessor { + public static Node node; /** * Allows the user to choose a file through a file dialog * and then validates if the File is valid, if it's playable @@ -35,24 +39,31 @@ public class FileProcessor */ public static void validateVideoFile(File videoFile) { - if (videoFile == null) return; + Alert alert; if (!FileProcessor.validateVideoFileName(videoFile)){ - new Alert(Alert.AlertType.WARNING, "ERROR on loading file\n"+ - "Couldn't load file specified", ButtonType.OK).showAndWait(); + alert = new Alert(Alert.AlertType.WARNING, "ERROR on loading file\n"+ + "Couldn't load file specified", ButtonType.OK); + alert.showAndWait(); return; } if (!Player.playVideo(videoFile)){ - new Alert(Alert.AlertType.WARNING, "ERROR on playing the video file\n"+ - "Please choose a valid .mp4 video file", ButtonType.OK).showAndWait(); + alert = new Alert(Alert.AlertType.WARNING, "ERROR on playing the video file",ButtonType.OK); + alert.showAndWait(); return; } if (!FileProcessor.createDirectories(videoFile)){ - new Alert(Alert.AlertType.WARNING, "ERROR on creating directories\n"+ - "Failed to create directories", ButtonType.OK).showAndWait(); + alert = new Alert(Alert.AlertType.WARNING, "ERROR on creating directories\n"+ + "Failed to create directories", ButtonType.OK); + alert.showAndWait(); return; } - MainController.setCurrentVideoFile(videoFile); MainController.resizeStageSlowly(1150, true); + MainController.setCurrentVideoFile(videoFile); + Controllers.getMainController().progressIndicator.setVisible(false); + Controllers.getMainController().progressBar.setVisible(false); + Controllers.getMainController().extractButton.setVisible(true); + Controllers.getMainController().textArea.setVisible(true); + Controllers.getMainController().textArea.clear(); } /** @@ -82,7 +93,8 @@ public static boolean createDirectories(File chosenFile) @Contract("null -> false") public static boolean validateVideoFileName(File filename) { - return filename != null && filename.exists(); + return filename != null && filename.exists() && filename.canRead() + && FilenameUtils.getExtension(filename.getPath()).equalsIgnoreCase("mp4"); } /** @@ -116,6 +128,8 @@ public static void loadLibraries() Controllers.getLogController().logTextArea.appendText("Loaded OpenH264 for Windows 32 bit\n"); } else if (bit == 64){ + System.loadLibrary("opencv_ffmpeg320_64"); + Controllers.getLogController().logTextArea.appendText("Loaded FFMPEG for Windows 64 bit\n"); System.loadLibrary("opencv_320_64"); Controllers.getLogController().logTextArea.appendText("Loaded OpenCV for Windows 64 bit\n"); System.loadLibrary("openh264-1.6.0-win64msvc"); diff --git a/src/main/java/Processors/Player.java b/src/main/java/Processors/Player.java index 64b1c69..81933d4 100644 --- a/src/main/java/Processors/Player.java +++ b/src/main/java/Processors/Player.java @@ -26,7 +26,7 @@ public static boolean playVideo(File videoFile) mediaView.fitWidthProperty().bind(Controllers.getMainController().videoPane.widthProperty()); mediaPlayer.play(); return true; - } catch (Exception e) { + } catch (Throwable e) { return false; } } diff --git a/src/main/java/Processors/VideoProcessor.java b/src/main/java/Processors/VideoProcessor.java index b30dbcc..5480c20 100644 --- a/src/main/java/Processors/VideoProcessor.java +++ b/src/main/java/Processors/VideoProcessor.java @@ -6,6 +6,8 @@ import ViewControllers.MainController; import javafx.application.Platform; import javafx.concurrent.Task; +import javafx.scene.control.Alert; +import javafx.scene.control.ButtonType; import org.bytedeco.javacpp.BytePointer; import org.bytedeco.javacpp.lept; import org.bytedeco.javacpp.tesseract; @@ -37,17 +39,22 @@ public class VideoProcessor private static Thread thread; private static boolean extractUniqueWords; private static List uniqueWords; + private static boolean frameIsOpened; public static void processVideoFile(File videoFile) { - VideoCapture cap = new VideoCapture(videoFile.getPath()); + VideoCapture cap = new VideoCapture(videoFile.getAbsolutePath()); + frameIsOpened = cap.read(input); + VideoWriter videoWriter = new VideoWriter(Paths.get(ApplicationPaths.RESOURCES_OUTPUTS, ApplicationPaths.UNIQUE_FOLDER_NAME, "Video", "video.mp4").toAbsolutePath().toString(), VideoWriter.fourcc('X', '2','6','4'), cap.get(Videoio.CAP_PROP_FPS), new Size(cap.get(Videoio.CAP_PROP_FRAME_WIDTH), cap.get(Videoio.CAP_PROP_FRAME_HEIGHT)), true); - if (cap.isOpened()) - { + if (!frameIsOpened){ + new Alert(Alert.AlertType.ERROR, "ERROR: Failed to read video frames\nTry another video file. If the error persists, contact the developer", + ButtonType.OK).showAndWait(); + } else { Task task = new Task() { @Nullable @@ -60,7 +67,6 @@ public static void processVideoFile(File videoFile) OcrProcessor.initializeOcr(ocrApi); double frames = (int) cap.get(Videoio.CAP_PROP_FRAME_COUNT); - boolean open1 = cap.read(input); int currentFrame = 1; input.copyTo(inputPainted); Size kernel = StructuringElement.getStructuringElement(input.height()*input.width()); @@ -68,7 +74,7 @@ public static void processVideoFile(File videoFile) Platform.runLater(() -> { Controllers.getLogController().logTextArea.appendText("[Structuring Element: "+kernel.height+" x "+kernel.width+"]\n"); }); - while (open1 && !thread.isInterrupted()) + while (frameIsOpened && !thread.isInterrupted()) { ImageWriter.writeStep(input); /* @@ -166,7 +172,7 @@ default value (-1, -1) means that the anchor is at the element center. // using the last detected text areas videoWriter.write(inputPainted); } - open1 = cap.read(input); + frameIsOpened = cap.read(input); currentFrame++; input.copyTo(inputPainted); diff --git a/src/main/java/ViewControllers/MainController.java b/src/main/java/ViewControllers/MainController.java index b06a8b9..1da9c7f 100644 --- a/src/main/java/ViewControllers/MainController.java +++ b/src/main/java/ViewControllers/MainController.java @@ -53,13 +53,14 @@ public void initialize() initializeViews(); ApplicationPaths.checkCaller(); + textArea.setVisible(false); // TestFx will fail otherwise for some reason videoIcon.setCursor(Cursor.HAND); extractButton.setCursor(Cursor.HAND); // When dragging something, allow it to be copied/moved only if it's a mp4 file videoPane.setOnDragOver(event -> { if (event.getDragboard().getFiles().get(0).isFile()){ - if (FilenameUtils.getExtension(event.getDragboard().getFiles().get(0).getPath()).equals("mp4")) { + if (FilenameUtils.getExtension(event.getDragboard().getFiles().get(0).getPath()).equalsIgnoreCase("mp4")){ event.acceptTransferModes(TransferMode.COPY_OR_MOVE); } } @@ -74,8 +75,6 @@ public void initialize() VideoProcessor.getThread().interrupt(); } } - textArea.clear(); - progressIndicator.setVisible(false); FileProcessor.validateVideoFile(event.getDragboard().getFiles().get(0)); event.setDropCompleted(true); event.consume(); @@ -96,8 +95,6 @@ public void initialize() VideoProcessor.getThread().interrupt(); } } - textArea.clear(); - progressIndicator.setVisible(false); FileProcessor.validateVideoFile(FileProcessor.showFileDialog()); }); @@ -139,8 +136,12 @@ public void initialize() videoPane.getChildren().clear(); videoPane.getChildren().add(videoIcon); videoIcon.setVisible(true); - resizeStageSlowly(680, false); textArea.clear(); + textArea.setVisible(false); + progressIndicator.setVisible(false); + progressIndicator.setVisible(false); + extractButton.setVisible(false); + resizeStageSlowly(680, false); }); playOriginal.setOnAction(event -> { @@ -162,7 +163,6 @@ public void initialize() * @param maximize Flag that indicates whether to expand or collapse the stage's width */ public static void resizeStageSlowly(double desiredSize, boolean maximize){ - Controllers.getMainController().extractButton.setVisible(true); Timer animTimer = new Timer(); animTimer.scheduleAtFixedRate(new TimerTask() { @Override @@ -218,11 +218,6 @@ public void initializeViews(){ settingsStage.setScene(new Scene(root, 400, 250)); } - @Contract(pure = true) - public static File getCurrentVideoFile() { - return currentVideoFile; - } - public static void setCurrentVideoFile(File currentVideoFile) { MainController.currentVideoFile = currentVideoFile; } diff --git a/src/main/resources/Views/main.fxml b/src/main/resources/Views/main.fxml index 6efc497..e498522 100644 --- a/src/main/resources/Views/main.fxml +++ b/src/main/resources/Views/main.fxml @@ -45,7 +45,7 @@ -