David Owens David Owens - 22 days ago 4
Java Question

Invalid URL/Illegal Argument Exception when using directory path to create a new type "File" object

I'm using a directorychooser to select a directory of images in the DirectoryChooser() method, yet I get a illegal argument exception/Invalid URL exception when trying to select a directory.

ImageView imgView = new ImageView( strImageList[ count ].getPath() );


This^ is the code that corresponds to line 348 referenced in stacktrace

makeImageViewArr(folder.getAbsolutePath());


This^ is the code that corresponds to line 104 referenced in stacktrace

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Invalid URL: Invalid URL or resource not found
at javafx.scene.image.Image.validateUrl(Image.java:1118)
at javafx.scene.image.Image.<init>(Image.java:620)
at javafx.scene.image.ImageView.<init>(ImageView.java:166)
at ICGPixelReader.makeImageViewArr(ICGPixelReader.java:348)
at ICGPixelReader.DirectoryChooser(ICGPixelReader.java:104)
at ICGPixelReader.lambda$addElements1$0(ICGPixelReader.java:205)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8411)
at javafx.scene.control.Button.fire(Button.java:185)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
at javafx.scene.image.Image.validateUrl(Image.java:1110)
... 49 more


Heres the directoryChooser method

//Handles when user presses button to open file chooser and select
//the folder of images
private void DirectoryChooser(){
DirectoryChooser chooser = new DirectoryChooser();
chooser.setTitle("Open images folder");
folder = chooser.showDialog(window);

//Null directory check
if(folder == null){
System.out.println("Null directory");
}

//Else make the image array from that folder
else{
System.out.println(folder);
makeImageViewArr(folder.getAbsolutePath());
}
}
//END METHOD


This directory path is to be used as parameter for another method (the makeImageViewArr(String folderName) ) method.

//Makes imageView arraylist from all images in a given directory
private ArrayList<ImageView> makeImageViewArr(String folderName) {

System.out.println(folderName);
//transer file names from directory folder to string array
File imagesDir = new File(folderName);
File[] strImageList = imagesDir.listFiles();
myMouseHandler mouseHandler = new myMouseHandler();

//instantiate imageview arraylist
arrImageList = new ArrayList<ImageView>();

//get files from folder & start at 1 to ignore ds.Store
for( int count = 1; count < strImageList.length; count++ ) {
ImageView imgView = new ImageView( strImageList[ count ].getPath() );
imgView.setOnMouseClicked( mouseHandler );
imgView.setFitHeight(500);
imgView.setFitWidth(500);
imgView.setPreserveRation(true);
arrImageList.add( imgView );
}
return arrImageList;
}//END METHOD


More code

//Author: David Owens
//File: ICGPixelReader.java
//Date: 11/15/2016

import java.util.*;
import java.io.*;
import javax.imageio.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.input.*;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.DirectoryChooser;
import javafx.scene.paint.Color;
import javafx.scene.text.*;
import javafx.scene.image.*;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.HPos;

/*
* Class that launches desktop application that can
* get average pixel RGB values from a region
*/
public class ICGPixelReader extends Application {
private Stage window;
private Scene scene1, scene2;
private BorderPane pane;
private GridPane prompts;
private Button next, prev, confirm;
private Text imageFolder, saveFileLbl, regionSizeLbl;
private TextField imageFolderField, saveFileField, regionSizeField;
private File folder, icgData;
private File[] listOfFiles;
private int index, nudgeY, nudgeX, loopCount, xCord, yCord, regionSize,
clickedImgW, clickedImgH;
private String folderName, saveFile;
private Double avgGreen, avgRGB, avgRB, regionRB, regionRGB, gSubRGB,
lowNorm, maxGreen;
private ArrayList<ImageView> arrImageList, frameGrabs;
private ArrayList<Integer> xCordArray, yCordArray;
private ArrayList<Double> greenArray, rbArray, rgbArray, gSubRGBArray,
posOnly, normalizedArray;
private PixelWriter pxlWrtr;
private PrintWriter output;


//Main method
public static void main(String[] args) {
launch(args);
}

@Override //Override start method in Application class
public void start(Stage primaryStage) throws Exception {

//rename stage for ease of use
window = primaryStage;
makeArrays();
addElements1();
}//END METHOD

//Instantiate arrays to store pixel data for printing
private void makeArrays() {
rgbArray = new ArrayList<Double>();
rbArray = new ArrayList<Double>();
greenArray = new ArrayList<Double>();
gSubRGBArray = new ArrayList<Double>();
posOnly = new ArrayList<Double>();
normalizedArray = new ArrayList<Double>();
xCordArray = new ArrayList<Integer>();
yCordArray = new ArrayList<Integer>();
}//END METHOD

//Handles when user presses button to open file chooser and select
//the folder of images
private void DirectoryChooser(){
DirectoryChooser chooser = new DirectoryChooser();
chooser.setTitle("Open images folder");
folder = chooser.showDialog(window);

//Null directory check
if(folder == null){
System.out.println("Null directory");
}

//Else make the image array from that folder
else{
System.out.println(folder);
makeImageViewArr(folder.getAbsolutePath());
}
}
//END METHOD

//Handles pressing of confirm button and switches scene to main window
private void confirmPress() {

//check if folder actually exists
try {
makeImageViewArr(imageFolderField.getText());
}
catch (Exception ex)
{
System.out.println(ex);
addElements1();
}

//check to see if data is saved to csv
if(saveFileField.getText().contains(".csv")){
saveFile = saveFileField.getText();
}
else{
addElements1();
return;
}

//check for proper region size
if(Integer.parseInt(regionSizeField.getText() ) >= 2) {
regionSize = Integer.parseInt(regionSizeField.getText());
}
else{
addElements1();
return;
}
addElements2();
}//END METHOD

//handles case where prev button is pressed
private void prevPress() {
index--;
if(index < 0){
index = 0;
pane.setCenter(arrImageList.get(index));
}
else{
pane.setCenter(arrImageList.get(index));
}
updateImgNum();
}//END METHOD

//handles case where next button is pressed
private void nextPress() {
index++;
if( index > arrImageList.size() - 1){
index = arrImageList.size() - 1;
pane.setCenter(arrImageList.get(index));
}
else{
pane.setCenter(arrImageList.get(index));
}
updateImgNum();
}//END METHOD

//Builds first window where user selects the folder, save file, and
//the region size
private void addElements1() {

// Set the stage title
window.setTitle( "ICG Pixel Reader" );
window.setMinWidth(700);
window.setMaxWidth(700);
window.setMinHeight(275);
window.setMaxHeight(275);

//build frame
prompts = new GridPane();
prompts.setAlignment(Pos.CENTER);
prompts.setHgap(10);
prompts.setVgap(10);
prompts.setPadding( new Insets(25, 25, 25, 25));

//size and set scene
scene1 = new Scene(prompts, 700, 275);
window.setScene(scene1);

//make elements
ImageView name = new ImageView("name.png");
imageFolder = new Text("Image folder path:");
saveFileLbl = new Text("Save file name:");
regionSizeLbl = new Text("Region size:");
imageFolderField = new TextField();
saveFileField = new TextField();
regionSizeField = new TextField();
imageFolderField.setPromptText("Users/images/folder");
saveFileField.setPromptText("Example.csv");
regionSizeField.setPromptText("50");
imageFolderField.setPrefColumnCount(30);
confirm = new Button("Confirm");

Button directoryChooseButton = new Button("Choose source folder");
directoryChooseButton.setOnAction(e->{DirectoryChooser();});

confirm.setOnAction(e->{confirmPress();});
prompts.setHalignment(confirm, HPos.RIGHT);


//add elements to frame
prompts.add(directoryChooseButton, 1, 1, 2, 1);

//prompts.add(imageFolderField, 1, 1, 2, 1);
prompts.add(saveFileField, 1, 2, 2, 1);
prompts.add(regionSizeField, 1, 3, 2, 1);
//prompts.add(imageFolder, 0, 1);
prompts.add(saveFileLbl, 0, 2);
prompts.add(regionSizeLbl, 0, 3);
prompts.add(confirm, 2, 4);
prompts.add(name, 2, 5, 3, 1);
window.setScene(scene1);
window.show();
}//END METHOD

//Builds second window where images are displayed and user selects
//regions to analyze
private void addElements2() {

//make new pane
pane = new BorderPane();
pane.setPadding(new Insets(20));

// Create a scene and place it in the stage
Scene scene2 = new Scene(pane);

Text controls = new Text("\n-Click indicates bottom right corner of region. \n"
+ "\n-WASD to fine tune region once clicked \n"
+ "\n-Press G to get data from region after fine tuning \n"
+ "\n-Press P to write data to file");

//make buttons and assign handlers
prev = new Button("Prev");
next = new Button("Next");
prev.setOnAction(e->{ prevPress(); });
next.setOnAction(e->{ nextPress(); });
pane.setLeft(prev);
pane.setRight(next);

pane.setMargin(prev, new Insets(10));
pane.setMargin(next, new Insets(10));
pane.setMargin(controls, new Insets(10));

updateImgNum();

pane.setBottom(controls);

//always start with first image in folder
pane.setCenter(arrImageList.get(0));

//set center alignment
pane.setAlignment(prev, Pos.CENTER);
pane.setAlignment(next, Pos.CENTER);
pane.setAlignment(controls, Pos.CENTER);

//instantiate key handler
scene2.setOnKeyPressed(new myKeyHandler());

window.setScene(scene2);
window.setMaxWidth(scene2.getWidth());
window.setMinWidth(scene2.getWidth());
window.setMaxHeight(scene2.getHeight());
window.setMinHeight(scene2.getHeight());

window.show();
}//END METHOD

//Updates image number as user goes right or left
private void updateImgNum() {
Text imageNum = new Text("Image " + (index + 1));
pane.setTop(imageNum);
pane.setAlignment(imageNum, Pos.CENTER);
pane.setMargin(imageNum, new Insets(10));
}//END METHOD

//Lets user know the pixels were sampled in the GUI
private void sampleNotification() {
Text imageNum = new Text("Image " + (index + 1) + "\nSampled!");
pane.setTop(imageNum);
pane.setAlignment(imageNum, Pos.CENTER);
}//END METHOD

//Draws region boundary after user clicks on image
private void drawRegion(PixelWriter pxlWrtr, int xCord, int yCord) {

Image clickedImg = arrImageList.get(index).getImage();
PixelReader pxlRdr = clickedImg.getPixelReader();

//get image height/width for copy
int clickedImgW = (int) clickedImg.getWidth();
int clickedImgH = (int) clickedImg.getHeight();

//draw right vert boundary
for( int yTrack = (yCord + 1); yTrack > (yCord - regionSize ); yTrack--) {
if((yTrack > 0 && yCord < clickedImgH - 1)
&& ( xCord < clickedImgW - 1 )) {
pxlWrtr.setColor(xCord + 1, yTrack, Color.RED);
}
}

//draw left vert boundary
for( int yTrack = (yCord + 1); yTrack > (yCord - regionSize); yTrack--) {
if((yTrack > 0 && yCord < clickedImgH - 1)
&& (xCord - regionSize) >= 0) {
pxlWrtr.setColor(xCord - regionSize, yTrack, Color.RED);
}
}

//draw bottom boundary
for(int xTrack = (xCord + 1); xTrack >= (xCord - regionSize); xTrack--) {
if(xTrack > 0 && yCord < clickedImgH - 1) {
pxlWrtr.setColor(xTrack, yCord + 1, Color.RED);
}
}

//draw top boundary
for(int xTrack = (xCord + 1); xTrack >= (xCord - regionSize); xTrack--) {
if(xTrack >= 0 && (yCord - regionSize) >= 0 ) {
pxlWrtr.setColor(xTrack, yCord - regionSize, Color.RED);
}
}
}//END METHOD

//Makes imageView arraylist from all images in a given directory
private ArrayList<ImageView> makeImageViewArr(String folderName) {

System.out.println(folderName);
//transer file names from directory folder to string array
File imagesDir = new File(folderName);
File[] strImageList = imagesDir.listFiles();
myMouseHandler mouseHandler = new myMouseHandler();

//instantiate imageview arraylist
arrImageList = new ArrayList<ImageView>();

//get files from folder & start at 1 to ignore ds.Store
for( int count = 1; count < strImageList.length; count++ ) {
ImageView imgView = new ImageView( strImageList[ count ].getPath() );
imgView.setOnMouseClicked( mouseHandler );
imgView.setFitHeight(500);
imgView.setFitWidth(500);
imgView.setPreserveRation(true);
arrImageList.add( imgView );
}
return arrImageList;
}//END METHOD

//inner class for mouse input
public class myMouseHandler implements EventHandler<MouseEvent>
{
/* Method which handles & executes mouse clicks
*
* @param e KeyEvent the code from the mouse click
*
* returns none
*/
@Override
public void handle(MouseEvent e)
{
//reset image to erase previous box
pane.setCenter( arrImageList.get( index ) );

//get image that was clicked on and pixel reader from image
Image clickedImg = arrImageList.get( index ).getImage();
PixelReader pxlRdr = clickedImg.getPixelReader();

//get image height/width for copy
int clickedImgW = (int) clickedImg.getWidth();
int clickedImgH = (int) clickedImg.getHeight();

//get x and y coordinates from click
int xCord = (int) e.getX();
int yCord = (int) e.getY();

nudgeX = xCord;
nudgeY = yCord;

//create writeable image and pixelwriter to draw click region
WritableImage outlineImg = new WritableImage(pxlRdr,
clickedImgW, clickedImgH );
PixelWriter pxlWrtr;
pxlWrtr = outlineImg.getPixelWriter();

//draws region
drawRegion( pxlWrtr, xCord, yCord );

//display image with click boundary and link mouseHandler
//to refresh on next click
ImageView tempImg = new ImageView( outlineImg );
myMouseHandler mouseHandler = new myMouseHandler();
tempImg.setOnMouseClicked( mouseHandler );
pane.setCenter( tempImg );

//print relevant info about click region
System.out.println( "xCord: " + xCord );
System.out.println( "yCord: " + yCord + "\n" );
}//END METHOD
}//END INNER CLASS
}//END CLASS

Answer

You are passing the file path as a string to the ImageView constructor:

ImageView imgView = new ImageView( strImageList[ count ].getPath() );

However, the ImageView constructor taking a String is expecting a URL. As stated in the documentation:

Allocates a new ImageView object with image loaded from the specified URL.

A file path is not a URL, and is often not even validly formed as a URL (it may have illegal characters, such as white space, for example).

So instead of passing the path, you should pass a URL that you get from the file:

ImageView imgView = new ImageView( strImageList[ count ].getURI().toString() );

As an aside, your DirectorChooser() (sic) method converts the chosen File to a String, which you then pass to your makeImageViewArr(...) method, where you immediately create a File out of it. This is bizarre (to say the least). Just change the method to accept a file, and pass the file directly:

private void DirectoryChooser(){
    DirectoryChooser chooser = new DirectoryChooser();
    chooser.setTitle("Open images folder");
    folder = chooser.showDialog(window);

    //Null directory check
    if(folder == null){
        System.out.println("Null directory");
    }

    //Else make the image array from that folder
    else{
            System.out.println(folder);
            makeImageViewArr(folder);
    }
}

and

private ArrayList<ImageView> makeImageViewArr(File imagesDir) { 

    File[] strImageList = imagesDir.listFiles();
    myMouseHandler mouseHandler = new myMouseHandler();

    //instantiate imageview arraylist
    arrImageList = new ArrayList<ImageView>();

    //get files from folder & start at 1 to ignore ds.Store
    for( int count = 1; count < strImageList.length; count++ ) {
        ImageView imgView = new ImageView( strImageList[ count ].toURI().toString() );
        imgView.setOnMouseClicked( mouseHandler );
        imgView.setFitHeight(500);
        imgView.setFitWidth(500);
        imgView.setPreserveRation(true);
        arrImageList.add( imgView );
    }
    return arrImageList;
}