public void decode(TmxMap map) {
        HashMap<TmxTileInstance, TmxTileInstance> tileInstancePool = new HashMap<TmxTileInstance, TmxTileInstance>();
        for (TmxLayer layer : map.getLayers()) {
            int[][] data = new int[layer.getWidth()][layer.getHeight()];
            layer.getData().decodeTo(layer.getWidth(), layer.getHeight(), data);
            for (int x = 0; x < layer.getWidth(); ++x) {
                for (int y = 0; y < layer.getHeight(); ++y) {
                    int gid = data[x][y];
                    if (0 != gid) {
                        EnumSet<TmxTileInstanceEffect> effects = EnumSet.noneOf(TmxTileInstanceEffect.class);
                        for (TmxTileInstanceEffect effect : TmxTileInstanceEffect.values()) {
                            if ((gid & effect.gidFlag) != 0) {
                                effects.add(effect);
                            }
                            gid &= ~effect.gidFlag;
                        }
                        ListIterator<TmxTileset> it = map.getTilesets().listIterator(map.getTilesets().size());
                        while (it.hasPrevious()) {
                            TmxTileset tileset = it.previous();
                            if (tileset.getFirstgid() <= gid) {
                                TmxTileInstance instance = new TmxTileInstance(tileset.getTileById(gid - tileset.getFirstgid()), effects);
                                TmxTileInstance pooledInstance = tileInstancePool.get(instance);
                                if (null != pooledInstance) {
                                    instance = pooledInstance;
                                } else {
                                    tileInstancePool.put(instance, instance);
                                }
                                layer.setTileAt(x, y, instance);
                                break;
                            }
                        }
                    }
                }
            }
        }
        map.setReady(true);
    }