All Downloads are FREE. Search and download functionalities are using the official Maven repository.

boofcv.io.UtilIO Maven / Gradle / Ivy

Go to download

BoofCV is an open source Java library for real-time computer vision and robotics applications.

There is a newer version: 1.1.7
Show newest version
/*
 * Copyright (c) 2011-2020, Peter Abeles. All Rights Reserved.
 *
 * This file is part of BoofCV (http://boofcv.org).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package boofcv.io;

import boofcv.BoofVersion;
import boofcv.io.calibration.CalibrationIO;
import boofcv.struct.calib.CameraPinholeBrown;
import org.apache.commons.io.FilenameUtils;

import javax.swing.*;
import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;

/**
 * @author Peter Abeles
 */
public class UtilIO {
	public static final String UTF8 = "UTF-8";

	/**
	 * Returns an absolute path to the file that is relative to the example directory
	 * @param path File path relative to root directory
	 * @return Absolute path to file
	 */
	public static URL pathExampleURL( String path ) {
		try {
			File fpath = new File(path);
			if (fpath.isAbsolute())
				return fpath.toURI().toURL();
			// Assume we are running inside of the project come
			String pathToBase = getPathToBase();
			if( pathToBase != null ) {
				File pathExample = new File(pathToBase, "data/example/");
				if (pathExample.exists()) {
					return new File(pathExample.getPath(), path).getAbsoluteFile().toURL();
				}
			}

//			System.out.println("-----------------------");
			// maybe we are running inside an app and all data is stored inside as a resource
//			System.out.println("Attempting to load resource "+path);
			URL url = UtilIO.class.getClassLoader().getResource(path);

			if (url == null) {
				System.err.println(path);
				System.err.println();
				System.err.println("Can't find data/example directory!  There are three likely causes for this problem.");
				System.err.println();
				System.err.println("1) You checked out the source code from git and did not pull the data submodule too.");
				System.err.println("2) You are trying to run an example from outside the BoofCV directory tree.");
				System.err.println("3) You are trying to pass in your own image.");
				System.err.println();
				System.err.println("Solutions:");
				System.err.println("1) Follow instructions in the boofcv/readme.md file to grab the data directory.");
				System.err.println("2) Launch the example from inside BoofCV's directory tree!");
				System.err.println("3) Don't use this function and just pass in the path directly");
				System.exit(1);
			}
			return url;
		} catch (MalformedURLException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Loads camera model for an example input file. First checks to see if there's calibration specific to that file
	 * if not it looks to see if there is a directory wide one. If all fails it returns null.
	 */
	public static CameraPinholeBrown loadExampleIntrinsic( MediaManager media, File exampleFile ) {
		CameraPinholeBrown intrinsic = null;
		String specialName = FilenameUtils.getBaseName(exampleFile.getName())+"_intrinsic.yaml";
		File specialIntrinsic = new File(exampleFile.getParent(),specialName);
		Reader reader = media.openFile(specialIntrinsic.getPath());
		if( reader != null ) {
			intrinsic = CalibrationIO.load(reader);
		} else {
			reader = media.openFile(new File(exampleFile.getParent(), "intrinsic.yaml").getPath());
			if ( reader != null ) {
				intrinsic = CalibrationIO.load(reader);
			}
		}
		return intrinsic;
	}

	public static BufferedReader openBufferedReader(String fileName) throws FileNotFoundException {
		InputStream stream = UtilIO.openStream(fileName);
		if( stream == null )
			throw new FileNotFoundException("Can't open "+fileName);
		return new BufferedReader(new InputStreamReader(stream, Charset.forName(UTF8)));
	}

	/**
	 * Given a path which may or may not be a URL return a URL
	 */
	public static URL ensureURL(String path ) {
		path = systemToUnix(path);
		URL url;
		try {
			url = new URL(path);
			if( url.getProtocol().equals("jar")) {
				return simplifyJarPath(url);
			}
		} catch (MalformedURLException e) {
			// might just be a file reference.
			try {
				url = new File(path).toURI().toURL(); // simplify the path. "1/2/../3" = "1/3"
			} catch (MalformedURLException e2) {
				return null;
			}
		}
		return url;
	}

	public static String ensureFilePath(String path ) {
		URL url = ensureURL(path);
		if( url == null )
			return null;
		try {
			return URLDecoder.decode(url.getPath(), UTF8);
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}

	/**
	 * Jar paths don't work if they include up directory. this wills trip those out.
	 */
	public static URL simplifyJarPath( URL url ) {
		try {
			String segments[] = url.toString().split(".jar!/");
			String path = simplifyJarPath(segments[1]);
			return new URL(segments[0]+".jar!/"+path);
		} catch (IOException e) {
			return url;
		}
	}

	public static String systemToUnix(String path) {
		if (path==null) return null;
		if (File.separatorChar=='\\') {
			return path.replace('\\', '/');
		} else {
			return path;
		}
	}

	public static String simplifyJarPath( String path ) {
		List elements = new ArrayList<>();
		File f = new File(path);

		boolean skip = false;
		do {
			if( !skip ) {
				if( f.getName().equals("..")) {
					skip = true;
				} else {
					elements.add(f.getName());
				}
 			} else {
				skip = false;
			}
			f = f.getParentFile();
		}while( f != null );

		path = "";
		for (int i = elements.size()-1; i >=0; i--) {
			path += elements.get(i);
			if( i > 0 )
				path+='/';
		}
		return path;
	}

	public static InputStream openStream( String path ) {
		try {
			URL url = ensureURL(path);
			if( url == null ) {
				System.err.println("Unable to open "+path);
			} else {
				return url.openStream();
			}
		} catch (IOException ignore) {}
		return null;
	}

	/**
	 * Reads a line from an input stream.
	 */
	public static String readLine( InputStream input, StringBuffer buffer ) throws IOException {
		buffer.setLength(0);
		while( true ) {
			int v = input.read();
			if( v == -1 || v == '\n' )
				return buffer.toString();
			buffer.append((char)v);
		}
	}

	public static String pathExample( String path ) {
		File fpath = new File(path);
		if (fpath.isAbsolute())
			return path;
		// Assume we are running inside of the project come
		String pathToBase = getPathToBase();
		if( pathToBase != null ) {
			File pathExample = new File(pathToBase, "data/example/");
			if (pathExample.exists()) {
				return new File(pathExample.getPath(), path).getAbsolutePath();
			}
		}

		return pathExampleURL(path).toString();
	}

	public static File fileExample( String path ) {
		return new File(pathExample(path));
	}

	/**
	 * Searches for the root BoofCV directory and returns an absolute path from it.
	 * @param path File path relative to root directory
	 * @return Absolute path to file
	 */
	public static String path( String path ) {
		String pathToBase = getPathToBase();
		if( pathToBase == null )
			return path;
		return new File(pathToBase,path).getAbsolutePath();
	}

	public static File getFileToBase() {
		return new File(getPathToBase());
	}

	/**
	 * Steps back until it finds the base BoofCV directory.
	 *
	 * @return Path to the base directory.
	 */
	public static String getPathToBase() {
		String path = new File(".").getAbsoluteFile().getParent();

		while( path != null )  {
			File f = new File(path);
			if( !f.exists() )
				break;

			String[] files = f.list();
			if( files == null )
				break;

			boolean foundReadme = false;
			boolean foundMain = false;
			boolean foundExamples = false;
			boolean foundIntegration = false;

			for( String s : files ) {
				if( s.compareToIgnoreCase("README.md") == 0 )
					foundReadme = true;
				else if( s.compareToIgnoreCase("main") == 0 )
					foundMain = true;
				else if( s.compareToIgnoreCase("examples") == 0 )
					foundExamples = true;
				else if( s.compareToIgnoreCase("integration") == 0 )
					foundIntegration = true;
			}

			if( foundMain && foundExamples && foundIntegration && foundReadme)
				return path;

			path = f.getParent();
		}
		return null;
	}

	/**
	 * Opens up a dialog box asking the user to select a file.  If the user cancels
	 * it either returns null or quits the program.
	 *
	 * @param exitOnCancel If it should quit on cancel or not.
	 * @return Name of the selected file or null if nothing was selected.
	 */
	public static String selectFile(boolean exitOnCancel) {
		String fileName = null;
		JFileChooser fc = new JFileChooser();

		int returnVal = fc.showOpenDialog(null);

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			fileName = fc.getSelectedFile().getAbsolutePath();
		} else if (exitOnCancel) {
			System.exit(0);
		}

		return fileName;
	}

	public static void loadLibrarySmart(String libraryName) {

		// see if it works the first try
		if (loadLibrary(libraryName))
			return;

		// otherwise search through the classpath for the library
		String classPath = System.getProperty("java.class.path");

		String stuff[] = classPath.split(":");

		for (String s : stuff) {
			File f = new File(s);
			if (!f.isDirectory())
				continue;
			f = new File(s + "/" + libraryName);
			if (f.exists()) {
				String libraryPath = System.getProperty("java.library.path");
				libraryPath += ":" + s;
				System.setProperty("java.library.path", libraryPath);
				if (!loadLibrary(libraryName))
					throw new RuntimeException("Shouldn't have failed to load this time");
				return;
			}

		}

		System.out.println("classPath");
	}

	public static boolean loadLibrary(String libraryName) {
		try {
			System.out.println("tring to load: " + libraryName);
			System.loadLibrary(libraryName);
			return true;
		} catch (UnsatisfiedLinkError e) {
			return false;
		}
	}

	public static void save( Object o , String fileName ) {
		try {
			FileOutputStream fileOut = new FileOutputStream(fileName);
			ObjectOutputStream out = new ObjectOutputStream(fileOut);
			out.writeObject(o);
			out.close();
			fileOut.close();
		} catch(IOException e) {
			throw new RuntimeException(e);
		}
	}

	public static  T load( String fileName ) {
		try {
			FileInputStream fileIn = new FileInputStream(fileName);
			ObjectInputStream in = new ObjectInputStream(fileIn);
			T obj = (T)in.readObject();
			in.close();
			fileIn.close();
			return obj;
		} catch(IOException | ClassNotFoundException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Deletes all the file/directory and all of its children
	 */
	public static void deleteRecursive( File f ) {
		if (f.isDirectory()) {
			for (File c : f.listFiles())
				deleteRecursive(c);
		}
		if (!f.delete())
			throw new RuntimeException("Failed to delete file: " + f);
	}

	/**
	 * Reads an entire file and converts it into a text string
	 */
	public static String readAsString( String path ) {
		InputStream stream = openStream(path);
		if( stream == null ) {
			System.err.println("Failed to open "+path);
			return null;
		}
		return readAsString(stream);
	}

	/**
	 * Reads an entire file and converts it into a text string
	 */
	public static String readAsString( InputStream stream ) {
		StringBuilder code = new StringBuilder();
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
			String line;
			while ((line = reader.readLine()) != null)
				code.append(line).append(System.lineSeparator());
			reader.close();
		} catch (IOException e) {
			return null;
//			throw new RuntimeException(e);
		}
		String output = code.toString();

		// make windows strings appear the same as linux strings
		String nl = System.getProperty("line.separator");
		if( nl.compareTo("\n") != 0 ) {
			output = output.replaceAll(nl,"\n");
		}

		return output;
	}

	/**
	 * Constructs the path for a source code file residing in the examples or demonstrations directory
	 * In the case of the file not being in either directory, an empty string is returned
	 * The expected parameters are class.getPackage().getName(), class.getSimpleName()
	 * @param pkg package containing the class
	 * @param app simple class name
	 * @return
	 */
	public static String getSourcePath(String pkg, String app) {
		String path = "";
		if(pkg == null || app == null)
			return path;


		String pathToBase = getPathToBase();
		if( pathToBase != null ) {
			if(pkg.contains("examples"))
				path =  new File(pathToBase,"examples/src/main/java/").getAbsolutePath();
			else if(pkg.contains("demonstrations"))
				path =  new File(pathToBase,"demonstrations/src/main/java/").getAbsolutePath();
			else {
				System.err.println("pkg must be to examples or demonstrations. " + pkg);
				return path;
			}
			String pathToCode = pkg.replace('.','/') + "/" + app + ".java";
			return new File(path,pathToCode).getPath();
		} else {
			// probably running inside a jar
			String pathToCode = pkg.replace('.','/') + "/" + app + ".java";
			URL url = UtilIO.class.getClassLoader().getResource(pathToCode);
			if( url != null )
				return url.toString();
			else
				return pathToCode;
		}
	}

	public static String getGithubURL(String pkg, String app) {
		if(pkg == null || app == null)
			return "";

		String base;
		if( BoofVersion.VERSION.contains("SNAPSHOT")) {
			base = "https://github.com/lessthanoptimal/BoofCV/blob/" + BoofVersion.GIT_SHA + "/";
		} else {
			base = "https://github.com/lessthanoptimal/BoofCV/blob/v" + BoofVersion.VERSION + "/";
		}
		pkg = pkg.replace('.','/') + "/";

		String dir;
		if(pkg.contains("demonstrations"))
			dir = "demonstrations/";
		else if(pkg.contains("examples"))
			dir = "examples/";
		else
			return "";

		return base + dir + "src/main/java/" + pkg + app + ".java";
	}

	/**
	 * Finds the first javadoc OR the start of the class, which ever comes first.
	 * This does require some thought.  The word class can easily be inside a comment.
	 * Comments may or may not be there.  Always the potential for stray //
	 */
	public static int indexOfSourceStart( String code ) {
		int state = 0;

		int indexLineStart = 0;
		char previous = 0;
		boolean justEntered = false;

		StringBuilder buffer = new StringBuilder(1024);

		for (int i = 0; i < code.length(); i++) {
			char c = code.charAt(i);

			if( state == 1 ) {
				if( justEntered ) {
					justEntered = false;
					if( c == '*' ) {
						return indexLineStart;
					}
				}
				if( previous == '*' && c == '/') {
					state = 0;
				}
			} else if( state == 0 ){
				if( previous == '/' && c == '/' ) {
					state = 2;
				} else if( previous == '/' && c == '*') {
					state = 1;
					justEntered = true;
				} else {
					buffer.append(c);
				}
			}

			if( c == '\n' ) {
				if( buffer.toString().contains("class")) {
					return indexLineStart;
				}
				buffer.delete(0,buffer.length());
				indexLineStart = i+1;
				if( state == 2 ) {
					state = 0;
				}
			}

			previous = c;
		}
		if( buffer.toString().contains("class")) {
			return indexLineStart;
		} else{
			return 0;
		}
	}

	/**
	 * Loads a list of files with the specified prefix.
	 *
	 * @param directory Directory it looks inside of
	 * @param prefix Prefix that the file must have
	 * @param suffix
	 * @return List of files that are in the directory and match the prefix.
	 */
	public static List listByPrefix(String directory, String prefix, String suffix) {
		List ret = new ArrayList<>();

		File d = new File(directory);

		if( !d.isDirectory() ) {
			try {
				URL url = new URL(directory);
				if( url.getProtocol().equals("file")) {
					d = new File(url.getFile());
				} else if( url.getProtocol().equals("jar")){
					return listJarPrefix(url,prefix,suffix);
				}
			} catch( MalformedURLException ignore){}
		}
		if( !d.isDirectory() )
			throw new IllegalArgumentException("Must specify an directory. "+directory);

		File files[] = d.listFiles();

		for( File f : files ) {
			if( f.isDirectory() || f.isHidden() )
				continue;

			if( prefix == null || f.getName().startsWith(prefix )) {
				if( suffix ==null || f.getName().endsWith(suffix)) {
					ret.add(f.getAbsolutePath());
				}
			}
		}

		return ret;
	}

	public static List listByRegex(String directory, String regex ) {
		List ret = new ArrayList<>();

		File d = new File(directory);

		if( !d.isDirectory() ) {
			try {
				URL url = new URL(directory);
				if( url.getProtocol().equals("file")) {
					d = new File(url.getFile());
				} else if( url.getProtocol().equals("jar")){
					return listJarRegex(url,regex);
				}
			} catch( MalformedURLException ignore){}
		}
		if( !d.isDirectory() )
			throw new IllegalArgumentException("Must specify an directory. "+directory);

		File files[] = d.listFiles();

		for( File f : files ) {
			if( f.isDirectory() || f.isHidden() )
				continue;

			if( f.getName().matches(regex) ) {
				ret.add(f.getAbsolutePath());
			}
		}

		return ret;
	}

	public static List listAll(String directory ) {
		List ret = new ArrayList<>();

		try {
			// see if it's a URL or not
			URL url = new URL(directory);
			if( url.getProtocol().equals("file") ) {
				directory = url.getFile();
			} else if( url.getProtocol().equals("jar") ) {
				return listJarPrefix(url,null,null);
			} else {
				throw new RuntimeException("Not sure what to do with this url. "+url.toString());
			}
		} catch (MalformedURLException ignore) {
		}

		File d = new File(directory);

		if( !d.isDirectory() )
			throw new IllegalArgumentException("Must specify an directory");

		File files[] = d.listFiles();

		for( File f : files ) {
			if( f.isDirectory() || f.isHidden() )
				continue;

			ret.add(f.getAbsolutePath());
		}

		return ret;
	}

	/**
	 * Lists all files in the directory with an MIME type that contains the string "type"
	 */
	public static List listAllMime( String directory , String type ) {
		List ret = new ArrayList<>();

		try {
			// see if it's a URL or not
			URL url = new URL(directory);
			if( url.getProtocol().equals("file") ) {
				directory = url.getFile();
			} else if( url.getProtocol().equals("jar") ) {
				return listJarMime(url,null,null);
			} else {
				throw new RuntimeException("Not sure what to do with this url. "+url.toString());
			}
		} catch (MalformedURLException ignore) {
		}

		File d = new File(directory);

		if( !d.isDirectory() )
			throw new IllegalArgumentException("Must specify an directory");

		File []files = d.listFiles();
		if( files == null )
			return ret;

		for( File f : files ) {
			if( f.isDirectory() )
				continue;
			try {
				String mimeType = Files.probeContentType(f.toPath());

				if( mimeType.contains(type))
					ret.add(f.getAbsolutePath());
			} catch (IOException ignore) {}
		}

		Collections.sort(ret);
		return ret;
	}

	private static List listJarPrefix(URL url , String prefix , String suffix ) {
		List output = new ArrayList<>();

		JarFile jarfile;
		try {
			JarURLConnection connection = (JarURLConnection)url.openConnection();
			jarfile = connection.getJarFile();

			String targetPath = connection.getEntryName()+"/";
			if( prefix != null ) {
				targetPath += prefix;
			}

			final Enumeration e = jarfile.entries();
			while( e.hasMoreElements() ) {
				final ZipEntry ze = (ZipEntry) e.nextElement();
//				System.out.println("  ze.anme="+ze.getName());
				if( ze.getName().startsWith(targetPath) &&
						ze.getName().length() != targetPath.length()) {
					if( suffix == null || ze.getName().endsWith(suffix))  {
						output.add("jar:file:"+jarfile.getName()+"!/"+ze.getName());
					}
				}
			}

			jarfile.close();
			return output;
		} catch (IOException e) {
			return new ArrayList<>();
		}
	}

	private static List listJarMime(URL url , String prefix , String type ) {
		List output = new ArrayList<>();

		FileNameMap fileNameMap = URLConnection.getFileNameMap();

		JarFile jarfile;
		try {
			JarURLConnection connection = (JarURLConnection)url.openConnection();
			jarfile = connection.getJarFile();

			String targetPath = connection.getEntryName()+"/";
			if( prefix != null ) {
				targetPath += prefix;
			}

			final Enumeration e = jarfile.entries();
			while( e.hasMoreElements() ) {
				final ZipEntry ze = (ZipEntry) e.nextElement();
//				System.out.println("  ze.anme="+ze.getName());

				if( ze.getName().startsWith(targetPath) &&
						ze.getName().length() != targetPath.length()) {
					// TODO no idea if this will work and is fast
					String path = "jar:file:"+jarfile.getName()+"!/"+ze.getName();
					String mimeType = fileNameMap.getContentTypeFor(path);
					if( mimeType.contains(type))  {
						output.add(path);
					}
				}
			}

			jarfile.close();
			return output;
		} catch (IOException e) {
			return new ArrayList<>();
		}
	}

	private static List listJarRegex(URL url , String regex ) {
		List output = new ArrayList<>();

		JarFile jarfile;
		try {
			JarURLConnection connection = (JarURLConnection)url.openConnection();
			jarfile = connection.getJarFile();

			String targetPath = connection.getEntryName()+"/";

			final Enumeration e = jarfile.entries();
			while( e.hasMoreElements() ) {
				final ZipEntry ze = (ZipEntry) e.nextElement();
//				System.out.println("  ze.anme="+ze.getName());
				if( ze.getName().startsWith(targetPath) &&
						ze.getName().length() != targetPath.length()) {
					String shortName = ze.getName().substring(targetPath.length());
					if( shortName.matches(regex)) {
						output.add("jar:file:"+jarfile.getName()+"!/"+ze.getName());
					}
				}
			}

			jarfile.close();
			return output;
		} catch (IOException e) {
			return new ArrayList<>();
		}
	}

	/**
	 * 

* Looks for file names which match the regex in the directory. *

*

* Example:
* BoofMiscOps.findMatches(new File("/path/to/directory"), ".+jpg"); *

* * @param directory directory * @param regex file name regex * @return array of matching files */ public static File[] findMatches( File directory , String regex ) { final Pattern p = Pattern.compile(regex); // careful: could also throw an exception! return directory.listFiles(file -> p.matcher(file.getName()).matches()); } public static boolean validURL( URL url ) { try { URLConnection c = url.openConnection(); return true; } catch( IOException e ) { return false; } } public static void copyToFile( InputStream in , File file ) { try { if( in == null ) throw new RuntimeException("Input is null"); FileOutputStream out = new FileOutputStream(file); byte buffer[] = new byte[1024*1024]; while( in.available() > 0 ) { int amount = in.read(buffer,0,buffer.length); out.write(buffer,0,amount); } out.close(); in.close(); } catch( IOException e ) { e.printStackTrace(); throw new RuntimeException(e); } } /** * Recursively deletes all files in path which pass the test. * @param f base directory or file * @param test The test * @throws IOException Exception if fails to delete a file */ public static void delete( File f , FileTest test ) throws IOException { if ( f.isDirectory() ) { File[] files = f.listFiles(); if( files != null ) { for (File c : files) { delete(c,test); } } } if ( test.isTarget(f) && !f.delete()) throw new IOException("Failed to delete file: " + f); } public static String checkIfJarAndCopyToTemp(String filename ) { // InputStream can't be seeked. This is a problem. Hack around it is to write the file // to a temporary file or see if it's a file pass that in URL url = ensureURL(filename); if( url == null ) throw new RuntimeException("Invalid: "+filename); switch( url.getProtocol() ) { case "file": filename = url.getPath(); // the filename will include an extra / in windows, this is fine // in Java but FFMPEG can't handle it. So this will strip off the // extra character and be cross platform filename = new File(filename).getAbsolutePath(); break; case "jar": System.out.println("Copying the file from the jar as a work around"); String suffix = FilenameUtils.getExtension(filename); // copy the resource into a temporary file try { InputStream in = openStream(filename); if( in == null ) throw new RuntimeException("Failed to open "+filename); final File tempFile = File.createTempFile("boofcv_jar_hack_", suffix); tempFile.deleteOnExit(); copyToFile(in,tempFile); filename = tempFile.getAbsolutePath(); } catch( IOException e ) { e.printStackTrace(); throw new RuntimeException(e); } break; } return filename; } public interface FileTest { boolean isTarget( File f ); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy