Browse code

Added support for base64 uncompressed, gzip and zlib. Added tests.

Casper Faergemand authored on 12/10/2014 12:54:50
Showing 3 changed files
... ...
@@ -23,13 +23,21 @@
23 23
  */
24 24
 package im.bci.tmxloader;
25 25
 
26
+import java.io.*;
27
+import java.nio.*;
28
+import java.util.zip.*;
29
+
30
+import javax.xml.bind.DatatypeConverter;
31
+
26 32
 /**
27 33
  *
28 34
  * @author devnewton
35
+ * @author Casper Faergemand (shorttail at gmail dot com)
29 36
  */
30 37
 public class TmxData {
31 38
 
32 39
     private String encoding;
40
+    private String compression;
33 41
     private String data;
34 42
 
35 43
     public String getEncoding() {
... ...
@@ -40,6 +48,14 @@ public class TmxData {
40 48
         this.encoding = encoding;
41 49
     }
42 50
 
51
+    public String getCompression() {
52
+        return compression;
53
+    }
54
+
55
+    public void setCompression(String compression) {
56
+        this.compression = compression;
57
+    }
58
+
43 59
     public String getData() {
44 60
         return data;
45 61
     }
... ...
@@ -51,9 +67,49 @@ public class TmxData {
51 67
     public void decodeTo(int width, int height, int[][] data) {
52 68
         if ("csv".equals(encoding)) {
53 69
             decodeCsvTo(width, height, data);
70
+        } else if ("base64".equals(encoding)) {
71
+            decodeBase64To(width, height, data);
72
+        } else {
73
+            throw new RuntimeException("Unsupported tiled layer data encoding: " + encoding);
74
+        }
75
+    }
76
+
77
+    private void decodeBase64To(int width, int height, int[][] gidArray) {
78
+        byte[] decodedRaw = DatatypeConverter.parseBase64Binary(getData());
79
+        if (compression == null) {
80
+            // Do nothing.
81
+        } else if ("gzip".equals(compression)) {
82
+            try {
83
+                ByteArrayInputStream bais = new ByteArrayInputStream(decodedRaw);
84
+                GZIPInputStream gis = new GZIPInputStream(bais);
85
+                DataInputStream dis = new DataInputStream(gis);
86
+                byte[] uncompressedRaw = new byte[height * width * 4];
87
+                dis.readFully(uncompressedRaw);
88
+                decodedRaw = uncompressedRaw;
89
+            } catch (IOException e) {
90
+                throw new RuntimeException("Gzip decompression failed.", e);
91
+            }
92
+        } else if ("zlib".equals(compression)) {
93
+            try {
94
+                Inflater inflater = new Inflater();
95
+                inflater.setInput(decodedRaw);
96
+                byte[] uncompressedRaw = new byte[height * width * 4];
97
+                inflater.inflate(uncompressedRaw);
98
+                decodedRaw = uncompressedRaw;
99
+            } catch (DataFormatException e) {
100
+                throw new RuntimeException("Zlib decompression failed.", e);
101
+            }
54 102
         } else {
55
-            throw new RuntimeException(
56
-                    "Unsupported tiled layer data encoding: " + encoding);
103
+            throw new RuntimeException("Unsupported compression: " + getCompression());
104
+        }
105
+        IntBuffer buffer = ByteBuffer.wrap(decodedRaw).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
106
+        int[] decodedInts = new int[buffer.remaining()];
107
+        buffer.get(decodedInts);
108
+        int i = 0;
109
+        for (int y = 0; y < height; y++) {
110
+            for (int x = 0; x < width; x++) {
111
+                gidArray[x][y] = decodedInts[i++];
112
+            }
57 113
         }
58 114
     }
59 115
 
... ...
@@ -218,6 +218,8 @@ public class TmxLoader {
218 218
     private TmxData parseData(XmlTag xmlData) {
219 219
         TmxData data = new TmxData();
220 220
         data.setEncoding(xmlData.attributes.get("encoding"));
221
+        data.setCompression(xmlData.attributes.get("compression"));
222
+        System.out.println(xmlData.attributes);
221 223
         data.setData(xmlData.content);
222 224
         return data;
223 225
     }
... ...
@@ -38,12 +38,23 @@ import org.junit.Assert;
38 38
 /**
39 39
  *
40 40
  * @author devnewton
41
+ * @author Casper Faergemand (shorttail at gmail dot com)
41 42
  */
42 43
 public class TestTmxLoader {
43 44
 
44 45
     @Test
45 46
     public void simpleTmx() throws IOException {
46
-        final File mapFile = new File("test-data/desert.tmx");
47
+        File mapFileCSV = new File("test-data/desert.tmx");
48
+        testFile(mapFileCSV);
49
+        File mapFileBase64 = new File("test-data/desert_base64_uncompressed.tmx");
50
+        testFile(mapFileBase64);
51
+        File mapFileBase64Gzip = new File("test-data/desert_base64_gzip.tmx");
52
+        testFile(mapFileBase64Gzip);
53
+        File mapFileBase64Zlib = new File("test-data/desert_base64_zlib.tmx");
54
+        testFile(mapFileBase64Zlib);
55
+    }
56
+
57
+    private void testFile(File mapFile) throws IOException {
47 58
         final File mapParentDir = mapFile.getParentFile().getCanonicalFile();
48 59
         TmxLoader loader = new TmxLoader();
49 60
         TmxMap map = new TmxMap();
... ...
@@ -58,10 +69,14 @@ public class TestTmxLoader {
58 69
                 tilesetParentDir = mapParentDir;
59 70
             }
60 71
             if (null != tileset.getImage()) {
61
-                tileset.getImage().setSource(convertRelativeToAbsolutePath(tilesetParentDir, tileset.getImage().getSource()));
72
+                tileset.getImage().setSource(
73
+                        convertRelativeToAbsolutePath(tilesetParentDir, tileset.getImage().getSource()));
62 74
             }
63 75
             for (TmxTile tile : tileset.getTiles()) {
64
-                tile.getFrame().getImage().setSource(convertRelativeToAbsolutePath(tilesetParentDir, tile.getFrame().getImage().getSource()));
76
+                tile.getFrame()
77
+                        .getImage()
78
+                        .setSource(
79
+                                convertRelativeToAbsolutePath(tilesetParentDir, tile.getFrame().getImage().getSource()));
65 80
             }
66 81
         }
67 82
         loader.decode(map);
... ...
@@ -71,13 +86,16 @@ public class TestTmxLoader {
71 86
         Assert.assertEquals(32, map.getTilewidth());
72 87
         Assert.assertEquals(32, map.getTileheight());
73 88
         Assert.assertEquals(1, map.getLayers().size());
89
+        // Test that the map was actually decoded. Tile at 0,0 has id 29.
90
+        Assert.assertEquals(29, map.getLayers().get(0).getTileAt(0, 0).getTile().getId());
91
+
74 92
     }
75
-    
93
+
76 94
     private String convertRelativeToAbsolutePath(File parentDir, String relativePath) throws IOException {
77
-        if(new File(relativePath).isAbsolute()) {
95
+        if (new File(relativePath).isAbsolute()) {
78 96
             return relativePath;
79 97
         }
80
-        return new File(parentDir, relativePath).getCanonicalPath();        
98
+        return new File(parentDir, relativePath).getCanonicalPath();
81 99
     }
82 100
 
83 101
     private String loadText(File f) throws IOException {