commit 72deef483a78424392f0521cbae2872aa9ab3419 from: leo date: Fri Jul 6 07:17:02 2007 UTC mepixel import commit - /dev/null commit + 72deef483a78424392f0521cbae2872aa9ab3419 blob - /dev/null blob + 088d129fec920b36fcfe192b372c6a9aec879478 (mode 644) --- /dev/null +++ MePixel.iml @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + blob - /dev/null blob + ba22d4400f61b1fa1eb1b649c1fe3df77ac5c42c (mode 644) --- /dev/null +++ MePixel.ipr @@ -0,0 +1,500 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + blob - /dev/null blob + 4b30399351aaa5c667a68823a55e6360f7809c8a (mode 644) --- /dev/null +++ MePixel.iws @@ -0,0 +1,798 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + blob - /dev/null blob + bdaae7291bd26d6fd81b9bdd3b5d348fe87eb256 (mode 644) --- /dev/null +++ build.properties @@ -0,0 +1,7 @@ +# +# Copyright (c) 2007, Matthias L. Jugel. All Rights Reserved. +# See http://thinkberg.com/ for details and instructions. +# + +qtjavamac.jar=/System/Library/Java/Extensions/QTJava.zip +qtjavawin.jar=c:\\Program Files\\QuickTime\\QTSystem\\QTJava.zip \ No newline at end of file blob - /dev/null blob + 1a18d4d30d54bfe969ad60842298c440bdc60fc7 (mode 644) --- /dev/null +++ build.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + blob - /dev/null blob + b4b7c8d80b56e5deca48ca244736b42368d77638 (mode 644) --- /dev/null +++ src/META-INF/mepixel.manifest @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Created-By: Matthias L. Jugel (http://thinkberg.com/) +Main-Class: com.thinkberg.mepixel.MePixelLauncher blob - /dev/null blob + 651b950075ea2cc925f77379afb9804c8cd3b75b (mode 644) --- /dev/null +++ src/com/thinkberg/launcher/Launcher.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2007, Matthias L. Jugel. All Rights Reserved. + * See http://thinkberg.com/ for details and instructions. + */ +package com.thinkberg.launcher; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.Policy; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; +import java.util.jar.Attributes; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; +import java.util.jar.JarEntry; + +/** + * Launcher for Java Applications. Creates the classpath and then starts the application. + * The launcher extracts all available jar files found in the Class-Path of the launcher jar + * file and adds them to the system class path before executing the real code. + * + * @author Matthias L. Jugel + */ +public class Launcher { + public final static String CLASSPATH = "launcher.classpath"; + + protected static boolean debug = false; + + private final static URL location = Launcher.class.getProtectionDomain().getCodeSource().getLocation(); + + /** + * Invokes the main() method of the class to be launched with the arguments provided. + * This is a wrapper to configure class path and other settings before launching the actual code. + * + * @param mainClassName the class to be launched + * @param args standard command line arguments + * @throws ClassNotFoundException + * @throws NoSuchMethodException + * @throws IllegalAccessException + * @throws InvocationTargetException + */ + public static void invokeMain(String mainClassName, final String args[]) + throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { + // get the parent class loader + ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader(); + if (null == parentClassLoader) { + parentClassLoader = Launcher.class.getClassLoader(); + } + if (null == parentClassLoader) { + parentClassLoader = ClassLoader.getSystemClassLoader(); + } + URLClassLoader classLoader = new URLClassLoader(initClassPath(System.getProperty(CLASSPATH)), + parentClassLoader); + Thread.currentThread().setContextClassLoader(classLoader); + + // for the sake of Java Web Start it is necessary to uninstall the security manager + if (System.getSecurityManager() != null) { + System.err.println("Launcher: uninstalling security manager ..."); + System.setSecurityManager(null); + } + + try { + Policy.getPolicy().refresh(); + } catch (Exception e) { + e.printStackTrace(); + } + + // load and start main class + Class mainClass = classLoader.loadClass(mainClassName); + final Method main = mainClass.getDeclaredMethod("main", new Class[]{String[].class}); + main.invoke(null, new Object[]{args}); + } + + /** + * Initialize the class path dynamically from information available in the manifest file. + * + * @param extraClassPath extra class path elements + * @return the URL array with the new class path + */ + protected static URL[] initClassPath(String extraClassPath) { + List urlArray = new ArrayList(); + InputStream manifestIn = null; + InputStream jarIn = null; + try { + manifestIn = location.openStream(); + JarInputStream launcherJarIs = new JarInputStream(manifestIn); + Manifest launcherManifest = launcherJarIs.getManifest(); + Attributes launcherAttribs = launcherManifest.getMainAttributes(); + String mainJarAttr = launcherAttribs.getValue("Launcher-Main-Jar"); + if (System.getProperty("launcher.main.jar") != null) { + mainJarAttr = System.getProperty("launcher.main.jar"); + } + URL mainJarUrl = getResourceUrl(mainJarAttr); + jarIn = mainJarUrl.openStream(); + Manifest mainManifest = new JarInputStream(jarIn).getManifest(); + Attributes mainAttributes = mainManifest.getMainAttributes(); + String manifestClassPath = mainAttributes.getValue("Class-Path"); + + urlArray.add(mainJarUrl); + // append extra class path to manifest class path (after replacing separatorchar) + if (extraClassPath != null && extraClassPath.length() > 0) { + manifestClassPath += " " + extraClassPath.replace(File.pathSeparatorChar, ' '); + } + + List extractedFiles = new ArrayList(); + StringBuffer classPath = new StringBuffer(location.getFile()); + if(manifestClassPath != null && manifestClassPath.length() != 0) { + StringTokenizer tokenizer = new StringTokenizer(manifestClassPath, " \t" + File.pathSeparatorChar, false); + while (tokenizer.hasMoreTokens()) { + String entry = tokenizer.nextToken(); + try { + URL classPathEntry = getResourceUrl(entry); + extractedFiles.add(entry); + urlArray.add(classPathEntry); + classPath.append(File.pathSeparatorChar); + classPath.append(classPathEntry.getFile()); + } catch (IOException e) { + System.err.println("Error: Missing resource ("+entry+") ignored, expect errors ..."); + } + } + } + + // ensure we extract all jar files from the launcher package and add them to the class path + // we do not rely on the Class-Path entry + List classpathList = new ArrayList(urlArray); + JarEntry jarEntry = null; + while(null != (jarEntry = launcherJarIs.getNextJarEntry())) { + if(!jarEntry.isDirectory() && + (jarEntry.getName().endsWith(".jar") || jarEntry.getName().endsWith(".zip")) && + !extractedFiles.contains(jarEntry.getName())) { + try { + URL classPathEntry = getResourceUrl(jarEntry.getName()); + if(!classpathList.contains(classPathEntry)) { + urlArray.add(classPathEntry); + classPath.append(File.pathSeparatorChar); + classPath.append(classPathEntry.getFile()); + } + } catch (IOException e) { + System.err.println("Error: Missing or corrupted resource ("+jarEntry.getName()+") ignored."); + } + } + } + + System.setProperty("java.class.path", classPath.toString()); + } catch (IOException e) { + System.err.println("Error: Set the system property launcher.main.jar to specify the jar file to start."); + e.printStackTrace(); + } finally { + try { manifestIn.close(); } catch (Throwable ignore) { }; + try { jarIn.close(); } catch (Throwable ignore) { }; + } + return (URL[]) urlArray.toArray(new URL[0]); + } + + /** + * Make a URL from a resource name. Necessary for creating a URL class loader. + * @param resource resource name/path + * @return the url pointing to the resource + * @throws IOException + */ + private static URL getResourceUrl(String resource) throws IOException { + File directoryBase = new File(location.getFile()).getParentFile(); + File file = new File(resource); + // see if this is an absolute URL + if (file.isAbsolute() && file.exists()) { + return file.toURL(); + } + // handle non-absolute URLs + file = new File(directoryBase, resource); + if (file.exists()) { + return file.toURL(); + } + + URL resourceURL = Launcher.class.getResource("/" + resource); + if (null != resourceURL) { + return extract(resourceURL); + } + + throw new MalformedURLException("missing resource: " + resource); + } + + /** + * Extract file from launcher jar to be able to access is via classpath. + * + * @param resource the jar resource to be extracted + * @return a url pointing to the new file + * @throws IOException if the extraction was not possible + */ + private static URL extract(URL resource) throws IOException { + if(debug) { + System.err.println("Launcher: extracting '" + resource.getFile() + "' ..."); + } + File f = File.createTempFile("launcher_", ".jar"); + f.deleteOnExit(); + if (f.getParentFile() != null) { + f.getParentFile().mkdirs(); + } + InputStream is = new BufferedInputStream(resource.openStream()); + FileOutputStream os = new FileOutputStream(f); + byte[] arr = new byte[8192]; + for (int i = 0; i >= 0; i = is.read(arr)) { + os.write(arr, 0, i); + } + is.close(); + os.close(); + return f.toURL(); + } +} \ No newline at end of file blob - /dev/null blob + 546687fccc91450227fb3c6005c5b6034488d129 (mode 644) --- /dev/null +++ src/com/thinkberg/mepixel/CameraGrabberThread.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2007, Matthias L. Jugel. All Rights Reserved. + * See http://thinkberg.com/ for details and instructions. + */ + +package com.thinkberg.mepixel; + +import quicktime.QTException; +import quicktime.QTRuntimeException; +import quicktime.QTRuntimeHandler; +import quicktime.QTSession; +import quicktime.io.QTFile; +import quicktime.io.OpenMovieFile; +import quicktime.qd.PixMap; +import quicktime.qd.QDGraphics; +import quicktime.qd.QDRect; +import quicktime.qd.QDConstants; +import quicktime.std.StdQTConstants; +import quicktime.std.movies.Movie; +import quicktime.std.sg.SGVideoChannel; +import quicktime.std.sg.SequenceGrabber; +import quicktime.util.RawEncodedImage; + +import java.awt.image.BufferedImage; +import java.awt.image.WritableRaster; +import java.io.File; + +/** + * @author Matthias L. Jugel + */ +public class CameraGrabberThread extends Thread { + private boolean running = false; + + private SequenceGrabber grabber; + private SGVideoChannel channel; + private RawEncodedImage rowEncodedImage; + private int[] pixelData; + private int width, height; + + public CameraGrabberThread() { + super(); + } + + public void init() throws QTException { + QTSession.open(); + + grabber = new SequenceGrabber(); + channel = new SGVideoChannel(grabber); + + width = channel.getSrcVideoBounds().getWidth(); + height = channel.getSrcVideoBounds().getHeight(); + QDRect bounds = new QDRect(width, height); + QDGraphics graphics; + if (quicktime.util.EndianOrder.isNativeLittleEndian()) { + graphics = new QDGraphics(QDConstants.k32BGRAPixelFormat, bounds); + } else { + graphics = new QDGraphics(QDGraphics.kDefaultPixelFormat, bounds); + } + grabber.setGWorld(graphics, null); + channel.setBounds(bounds); + channel.setUsage(StdQTConstants.seqGrabPreview); + grabber.prepare(true, false); + + grabber.setDataOutput( null, StdQTConstants.seqGrabDontMakeMovie); + grabber.prepare(true, true); + grabber.startRecord(); + + PixMap pixMap = graphics.getPixMap(); + rowEncodedImage = pixMap.getPixelData(); + pixelData = new int[width * height]; + + QTRuntimeException.registerHandler(new QTRuntimeHandler() { + public void exceptionOccurred( + QTRuntimeException e, Object eGenerator, + String methodNameIfKnown, boolean unrecoverableFlag) { + System.out.println("what should i do?"); + } + }); + } + + public int getCameraWidth() { + return width; + } + + public int getCameraHeight() { + return height; + } + + public void enable() { + running = true; + start(); + } + + public void disable() { + running = true; + } + + public void run() { + try { + while (running) { + grabber.idle(); + rowEncodedImage.copyToArray(0, pixelData, 0, pixelData.length); + } + } catch (QTException e) { + e.printStackTrace(); + } + QTSession.close(); + } + + public int[] getPixelData() { + return pixelData; + } + + public void dispose() { + try { + grabber.stop(); + grabber.release(); + grabber.disposeChannel(channel); + } catch (Exception e) { + e.printStackTrace(); + } finally { + QTSession.close(); + } + } +} blob - /dev/null blob + 159f9e4a0d0c7bfd4a3fc5fc65a7d12af7ca9d7e (mode 644) --- /dev/null +++ src/com/thinkberg/mepixel/CharDisplay.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2007, Matthias L. Jugel. All Rights Reserved. + * See http://thinkberg.com/ for details and instructions. + */ + +package com.thinkberg.mepixel; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyListener; +import java.awt.event.KeyEvent; + +/** + * @author Matthias L. Jugel + */ +public class CharDisplay extends JFrame { + private Image backingStore; + private int xOffset; + private int yOffset; + + public CharDisplay() { + super(); + + setUndecorated(true); + setExtendedState(Frame.MAXIMIZED_BOTH); + setVisible(true); + setBackground(Color.BLACK); + + getGraphicsConfiguration().getDevice().setFullScreenWindow(this); + + } + + public void setBackingStore(Image image) { + backingStore = image; + xOffset = (getWidth() - backingStore.getWidth(this)) / 2; + yOffset = (getHeight() - backingStore.getHeight(this)) / 2; + } + + /** + * Paint the current screen using the backing store image. + */ + public void paint(Graphics g) { + if (backingStore != null) { + g.drawImage(backingStore, xOffset, yOffset, this); + } + } +} blob - /dev/null blob + c0000c00c997ac78b8fe7d5b1d9ac2c793c9641e (mode 644) --- /dev/null +++ src/com/thinkberg/mepixel/MePixel.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2007, Matthias L. Jugel. All Rights Reserved. + * See http://thinkberg.com/ for details and instructions. + */ + +package com.thinkberg.mepixel; + +import quicktime.QTException; + +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; +import java.awt.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.Policy; +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; + + +public class MePixel { + private static int delay = 20; + private static boolean fillSwap = true; + private static boolean charSwap = false; + private static double brightnessThreshold = 0.50; + + + private static void showUsage() { + System.out.println("MePixel (c) 2007 Matthias L. Jugel. All Rights Reserved."); + System.out.println(); + System.out.println("** Use cursor 'UP' and 'DOWN' to increase/decrease speed"); + System.out.println("** Use cursor 'LEFT' and 'RIGHT' to change the brightness threshold"); + System.out.println("** Press 'C' to change between number and rectangle fill mode"); + System.out.println("** Press 'F' to toggle fill modes (toggle 1 and 0)"); + System.out.println("** To quit, press 'Cmd-Q' or 'Alt-F4'"); + System.out.println(); + System.out.println("Press return to continue ..."); + try { + new BufferedReader(new InputStreamReader(System.in)).readLine(); + } catch (IOException e) { + // ignore + } + } + + public MePixel(String[] args) { + showUsage(); + + int fontSize = 8; + try { + if (args.length > 0) { + fontSize = Integer.parseInt(args[0]); + } + } catch (NumberFormatException e) { + // ignore if the value is not an integer + } + + CameraGrabberThread cameraGrabber = new CameraGrabberThread(); + try { + cameraGrabber.init(); + } catch (QTException e) { + System.err.println("Camera grabber failed: "+e.getMessage()+" (no camera found?)"); + System.err.println("Exiting ..."); + System.exit(-1); + } + cameraGrabber.enable(); + + int cameraWidth = cameraGrabber.getCameraWidth(); + int cameraHeight = cameraGrabber.getCameraHeight(); + + int[] pixelData = cameraGrabber.getPixelData(); + + CharDisplay charDisplay = new CharDisplay(); + charDisplay.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent keyEvent) { + switch (keyEvent.getKeyCode()) { + case KeyEvent.VK_UP: + delay += 20; + break; + case KeyEvent.VK_DOWN: + if (delay >= 20) delay -= 20; + break; + case KeyEvent.VK_LEFT: + if (brightnessThreshold > 0) brightnessThreshold -= 0.05; + break; + case KeyEvent.VK_RIGHT: + if (brightnessThreshold < 1) brightnessThreshold += 0.05; + break; + case KeyEvent.VK_F: + fillSwap = !fillSwap; + break; + case KeyEvent.VK_C: + charSwap = !charSwap; + } + } + }); + + Font font = new Font("Bitstream Vera Sans Mono", Font.PLAIN, fontSize); + charDisplay.setFont(font); + int charWidth = charDisplay.getFontMetrics(font).charWidth('@'); + int charHeight = charDisplay.getFontMetrics(font).getHeight(); + int adaptedScreenHeight = charDisplay.getHeight() / charHeight; + int adaptedScreenWidth = charDisplay.getWidth() / charWidth; + System.out.println("Using a character size of [" + charWidth + "x" + charHeight + "] pixels"); + System.out.println("The screen is divided into [" + adaptedScreenWidth + "x" + adaptedScreenHeight + "] squares"); + + + BufferedImage cachedImage = new BufferedImage(adaptedScreenWidth * charWidth, + adaptedScreenHeight * charHeight, + BufferedImage.TYPE_INT_RGB); + Graphics2D cachedImageG2D = cachedImage.createGraphics(); + cachedImageG2D.setFont(font); + charDisplay.setBackingStore(cachedImage); + float[] hsvValues = new float[3]; + + int rectWidth = cameraWidth / adaptedScreenWidth; + int rectHeight = cameraHeight / adaptedScreenHeight; + + while (true) { + for (int row = 0; row < cameraHeight; row += rectHeight) { + int y = (row / rectHeight) * charHeight; + + cachedImageG2D.setColor(charDisplay.getBackground()); + cachedImageG2D.fillRect(0, y, cameraWidth * charWidth, charHeight); + + for (int column = 0; column < cameraWidth; column += rectWidth) { + int offset = (row * cameraWidth) + column; + int avgColor = getAveragedRectPixelColor(pixelData, offset, cameraWidth, rectWidth, rectHeight); + + int x = ((cameraWidth - column) / rectWidth) * charWidth; + + + Color fg = new Color(avgColor); + Color.RGBtoHSB(fg.getRed(), fg.getGreen(), fg.getBlue(), hsvValues); + cachedImageG2D.setColor(fg); + if ((fillSwap && (hsvValues[2] > brightnessThreshold)) || + (!fillSwap && hsvValues[2] < brightnessThreshold)) { + if (charSwap) { + cachedImageG2D.drawRect(x, y, charWidth, charHeight); + } else { + cachedImageG2D.drawString("1", x, y - charHeight); + } + } else { + if (charSwap) { + cachedImageG2D.fillRect(x, y, charWidth, charHeight); + } else { + cachedImageG2D.drawString("0", x, y - charHeight); + } + } + } + charDisplay.repaint(); + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + // ignore thread errors + } + } + } + } + + /** + * Calculate the average color for a certain pixel rectangle + * + * @param image the image to get the data from + * @param offset current offset (left, top) in the data array + * @param rowSize the current row length in bytes + * @param width the width of the rectangle in pixels + * @param height the height of the rectange in pixels + * @return a 24 bit color int + */ + private int getAveragedRectPixelColor(int[] image, int offset, int rowSize, int width, int height) { + int avgColor = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int pixColor; + try { + pixColor = image[offset + (y * rowSize) + x]; + } catch (Exception e) { + return avgColor; + } + // color averaging + avgColor = (((avgColor ^ pixColor) & 0xfffefefe) >> 1) + (avgColor & pixColor); + } + } + return avgColor; + } +} blob - /dev/null blob + a8824b9f57659c7d3bc986b296c7ecd8d019b96f (mode 644) --- /dev/null +++ src/com/thinkberg/mepixel/MePixelLauncher.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2007, Matthias L. Jugel. All Rights Reserved. + * See http://thinkberg.com/ for details and instructions. + */ + +package com.thinkberg.mepixel; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.Policy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author Matthias L. Jugel + */ +public class MePixelLauncher { + private static List qtClassPath = Arrays.asList( + "/System/Library/Java/Extensions/QTJava.zip", + "C:\\Program Files\\Quicktime\\QTSystem\\QTJava.zip", + "C:\\Programme\\Quicktime\\QTSystem\\QTJava.zip" + ); + + public static void main(String args[]) { + + System.err.println("MePixelLauncher (c) 2007 Matthias L. Jugel. All Rights Reserved."); + System.err.println("++ Checking Quicktime installation ..."); + ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader(); + if (null == parentClassLoader) { + parentClassLoader = MePixel.class.getClassLoader(); + } + if (null == parentClassLoader) { + parentClassLoader = ClassLoader.getSystemClassLoader(); + } + + List classPath = new ArrayList(); + classPath.add(MePixel.class.getProtectionDomain().getCodeSource().getLocation()); + for (String fileName : qtClassPath) { + File file = new File(fileName); + if (file.exists()) { + try { + classPath.add(file.toURL()); + System.err.println("++ Added " + file + " to class path."); + } catch (MalformedURLException e) { + // ignore + } + } + } + URLClassLoader classLoader = new URLClassLoader(classPath.toArray(new URL[0]), + null); + Thread.currentThread().setContextClassLoader(classLoader); + + // for the sake of Java Web Start it is necessary to uninstall the security manager + if (System.getSecurityManager() != null) { + System.err.println("Launcher: uninstalling security manager ..."); + System.setSecurityManager(null); + } + + try { + Policy.getPolicy().refresh(); + } catch (Exception e) { + e.printStackTrace(); + } + + System.err.println(); + // load and start main class + try { + Class mainClass = classLoader.loadClass("com.thinkberg.mepixel.MePixel"); + final Constructor mainContructor = mainClass.getConstructor(String[].class); + mainContructor.newInstance(new Object[]{args}); + } catch (Exception e) { + e.printStackTrace(); + } + } + +}