diff --git a/.gitignore b/.gitignore
index 9f25cc2301ab500393825b61c652ac5751c5dc3b..7cbe242d3e57f29e4c908eaef1e72c996c53f81a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,8 @@ src/main/resources/mapping/liblouis
 
 # Exported SVG files
 *.svg
+
+# Native libraries
+*.so
+*.dylib
+*.dll
diff --git a/.gitmodules b/.gitmodules
index c5dd365bd9aec06336502855f51c391593fd54cd..6279666aaacb70d51061cd2eaf45864903353052 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
 [submodule "third_party/liblouis"]
 	path = third_party/liblouis
 	url = https://github.com/liblouis/liblouis
+[submodule "third_party/liblouis_bin"]
+	path = third_party/liblouis_bin
+	url = ../../brailleplot/liblouis_bin.git
diff --git a/build.gradle b/build.gradle
index 59cf0b22950c45a026679cd9f96d0232bc297d16..d56141ec73bfe993b742785d3cf4376a3c4085f3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -68,6 +68,23 @@ clean {
     delete "$rootDir/src/main/resources/mapping/liblouis"
 }
 
+// Copy native liblouis libraries for major platforms to the resource folder
+task copyLibLouisBinary(type: Copy) {
+    from "$projectDir/third_party/liblouis_bin/bin/"
+    into "$rootDir/src/main/resources/native/liblouis"
+}
+processResources.dependsOn copyLibLouisBinary
+// Abort if files are missing
+gradle.taskGraph.afterTask { copyLibLouisBinary ->
+    if(copyLibLouisBinary.state.noSource){
+        throw new GradleException("Could not find liblouis native libraries in \"$projectDir/third_party/liblouis_bin/bin/\". Please make sure you updated all git submodules using \"git submodule update --init --recursive\" ")
+    }
+}
+// Delete libraries on "clean" task
+clean {
+    delete "$rootDir/src/main/resources/native/liblouis"
+}
+
 // Define the main class for the application
 mainClassName = 'de.tudresden.inf.mci.brailleplot.App'
 
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/App.java b/src/main/java/de/tudresden/inf/mci/brailleplot/App.java
index cd0a7d8249f6d3d77d07e25e91fdcb248c3a3c78..a302869bea0c1dca31239b721c30e1ba7ab8a066 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/App.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/App.java
@@ -153,8 +153,6 @@ public final class App {
         try {
             // Logging example
             mLogger.info("Application started");
-            // Needed for Windows machines
-            System.setProperty("jna.library.path", System.getProperty("user.dir") + "/third_party");
             // Parse command line parameters
             CommandLineParser cliParser = new CommandLineParser();
             SettingsWriter settings = cliParser.parse(args);
@@ -198,6 +196,7 @@ public final class App {
             barChart.setYAxisName("Länge in m");
 
             // Render diagram
+            LiblouisBrailleTextRasterizer.initModule();
             MasterRenderer renderer = new MasterRenderer(indexV4Printer, representationParameters, a4Format);
             RasterCanvas canvas = renderer.rasterize(barChart);
             // SVG exporting
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java
index 1bcbed6087ee1b293194715a4959a25c1d9855c5..e214755c5ff66fbe0a4b534b26d63eb1aa081b3b 100644
--- a/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/rendering/LiblouisBrailleTextRasterizer.java
@@ -8,8 +8,11 @@ import de.tudresden.inf.mci.brailleplot.layout.InsufficientRenderingAreaExceptio
 import de.tudresden.inf.mci.brailleplot.layout.RasterCanvas;
 import de.tudresden.inf.mci.brailleplot.layout.Rectangle;
 import de.tudresden.inf.mci.brailleplot.printerbackend.NotSupportedFileExtensionException;
+import de.tudresden.inf.mci.brailleplot.util.NativeLibraryHelper;
+import de.tudresden.inf.mci.brailleplot.util.NoSuchNativeLibraryException;
 import org.liblouis.DisplayException;
 import org.liblouis.DisplayTable;
+import org.liblouis.Louis;
 import org.liblouis.TranslationException;
 import org.liblouis.TranslationResult;
 import org.liblouis.Translator;
@@ -27,6 +30,8 @@ import static java.lang.Math.ceil;
 
 public class LiblouisBrailleTextRasterizer implements Rasterizer<BrailleText> {
 
+    private static boolean mNativeLibInitialized = false;
+
     private AbstractBrailleTableParser mParser;
     // Parameters for rasterizing
     private int x;
@@ -241,4 +246,33 @@ public class LiblouisBrailleTextRasterizer implements Rasterizer<BrailleText> {
         mTranslator = temp;
         return length;
     }
+
+    /**
+     * Initializes the Module.
+     * @throws LibLouisLibraryMissingException If liblouis could not be loaded from neither the jar or the default JNI include path.
+     */
+    public static void initModule() throws LibLouisLibraryMissingException {
+        if (!mNativeLibInitialized) {
+            try {
+                NativeLibraryHelper.loadNativeLibrary("liblouis");
+            } catch (NoSuchNativeLibraryException e) {
+                // Even if the library is not distributed within the jar file, it might be installed on the system.
+            }
+            try {
+                Louis.getVersion();
+            } catch (java.lang.UnsatisfiedLinkError e) {
+                throw new LibLouisLibraryMissingException(e);
+            }
+            mNativeLibInitialized = true;
+        }
+    }
+
+    /**
+     * Indicates, the native liblouis library was not found.
+     */
+    public static class LibLouisLibraryMissingException extends NoSuchNativeLibraryException {
+        LibLouisLibraryMissingException(final Throwable cause) {
+            super(cause);
+        }
+    }
 }
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/util/NativeLibraryHelper.java b/src/main/java/de/tudresden/inf/mci/brailleplot/util/NativeLibraryHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb12d84492efcbfc339696d9e772692ae93417a6
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/util/NativeLibraryHelper.java
@@ -0,0 +1,118 @@
+package de.tudresden.inf.mci.brailleplot.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+
+/**
+ * This class offers static methods for native library loading purposes.
+ * @author Georg Graßnick
+ * @version 2019.09.26
+ */
+public final class NativeLibraryHelper {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NativeLibraryHelper.class);
+    private static final String LIB_PATH = calculateLibPath();
+
+    private NativeLibraryHelper() { }
+
+    /**
+     * Loads a library from the resources according to the current system architecture and operating system.
+     * @param libName The name of the library. Library prefixes ({@literal "}lib{@literal "}) are not treated separately.
+     *                The system specific file ending is added automatically and must not be included in the parameter.
+     * @return A File object representing the file of the library. The JNI is automatically set up to take of the library,
+     * so there is most likely no need for this return value.
+     * @throws NoSuchNativeLibraryException If the requested library could not be found or read.
+     */
+    public static synchronized File loadNativeLibrary(final String libName) throws NoSuchNativeLibraryException {
+        File libFile;
+        try {
+            String libPath = "native/" + libName + "/" + LIB_PATH + "/" + libName + dynamicLibFileEnding();
+            libFile = GeneralResource.getOrExportResourceFile(libPath).getAbsoluteFile();
+            registerNewSystemLibPath(libFile.getParent());
+        } catch (Exception e) {
+            throw new NoSuchNativeLibraryException("Could not provide native library from java resources", e);
+        }
+        LOG.debug("Found and exported native library \"" + libFile + "\" for requested library \"" + libName + "\"");
+        return libFile;
+    }
+
+    /**
+     * Adds a path in the file system to the search path of the JNI.
+     * @param path The path to add.
+     */
+    private static synchronized void registerNewSystemLibPath(final String path) {
+        String currentLibPath = System.getProperty("jna.library.path");
+        String newLibPath = null;
+        boolean pathExists = false;
+
+        if (currentLibPath == null) {
+            newLibPath = path;
+        } else {
+            // Do not insert path if it already is included
+            String[] existingPaths = currentLibPath.split(File.pathSeparator);
+            for (String s : existingPaths) {
+                if (s.equals(path)) {
+                    pathExists = true;
+                    break;
+                }
+            }
+            newLibPath = currentLibPath + File.pathSeparator + path;
+        }
+
+        if (!pathExists) {
+            LOG.debug("Setting JNI library path property to \"" + newLibPath + "\"");
+            System.setProperty("jna.library.path", newLibPath);
+        }
+    }
+
+    private static String calculateLibPath() {
+        return getArch() + "/" + getOs();
+    }
+
+    private static String getArch() {
+        String arch = System.getProperty("os.arch");
+        // reference: https://stackoverflow.com/a/36926327
+        switch (arch) {
+            case "x86":
+            case "i386":
+            case "i486":
+            case "i586":
+            case "i686":
+                return "x86_32";
+            case "x86_64":
+            case "amd64":
+                return "x86_64";
+            default:
+                throw new RuntimeException("Operating System architecture \"" + arch + "\" is currently not supported");
+        }
+    }
+
+    private static String getOs() {
+        String name = System.getProperty("os.name");
+        String nameLow = name.toLowerCase();
+        if (nameLow.contains("linux")) {
+            return "linux";
+        } else if (nameLow.contains("mac")) {
+            return "osx";
+        } else if (nameLow.contains("win")) {
+            return "win32";
+        } else {
+            throw new RuntimeException("Operating System \"" + name + "\" is currently not supported");
+        }
+    }
+
+    private static String dynamicLibFileEnding() {
+        switch (getOs()) {
+            case "win32":
+                return ".dll";
+            case "linux":
+                return ".so";
+            case "osx":
+                return ".dylib";
+            default:
+                throw new IllegalStateException("If this exception was thrown, something is wrong with your code");
+        }
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/mci/brailleplot/util/NoSuchNativeLibraryException.java b/src/main/java/de/tudresden/inf/mci/brailleplot/util/NoSuchNativeLibraryException.java
new file mode 100644
index 0000000000000000000000000000000000000000..2f7331e5f542838d14a77027252710f5dd426b50
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/mci/brailleplot/util/NoSuchNativeLibraryException.java
@@ -0,0 +1,23 @@
+package de.tudresden.inf.mci.brailleplot.util;
+
+/**
+ * Indicates, some error has occurred while trying to load a native library from the java resources.
+ * @author Georg Graßnick
+ * @version 2019.09.26
+ */
+public class NoSuchNativeLibraryException extends RuntimeException {
+
+        public NoSuchNativeLibraryException() { }
+
+        public NoSuchNativeLibraryException(final String message) {
+            super(message);
+        }
+
+        public NoSuchNativeLibraryException(final Throwable cause) {
+            super(cause);
+        }
+
+        public NoSuchNativeLibraryException(final String message, final Throwable cause) {
+            super(message, cause);
+        }
+}
diff --git a/third_party/liblouis_bin b/third_party/liblouis_bin
new file mode 160000
index 0000000000000000000000000000000000000000..24b6908d0b167ce785c0f9ce8295d9845b69a303
--- /dev/null
+++ b/third_party/liblouis_bin
@@ -0,0 +1 @@
+Subproject commit 24b6908d0b167ce785c0f9ce8295d9845b69a303