Blurred custom tiles on Android Maps V2

时光怂恿深爱的人放手 提交于 2019-12-21 02:41:20

问题


I want to show a CustomOverlay on a Google Maps V2. The loading of the tiles works as expected, the only thing is, that the shown tiles are not appearing to be sharp at all, kind of blurry. Google did not get me to an usable answer.

I took the approach of adding classical 256px x 256px tiles for the TileProvider. I managed to get a tile source where the images were @2x (retina), which made the whole visual experience much sharper, but I would rather not use this source, as the data transfer rate is four times higher, hence not usable on mobile devices and slow internet speeds.

I included two different examples (screenshots) of the rendered map, both with the same configuration (OSM - 256x256 tiles) and with the provided TileProviderOsm. One is on a Galaxy Nexus and the other on a Nexus 5 phone. Both do not look like they were rendered correctly.

Any idea what I could do to prevent the blurriness or increase the sharpness?

My TileProvider looks like following:

 public class TileProviderOsm extends UrlTileProvider {

    private static final String MAP_URL = "http://tile.openstreetmap.org/%d/%d/%d.png";

    private static int TILE_WIDTH  = 256;
    private static int TILE_HEIGHT = 256;

    public static int MIN_ZOOM = 7;
    public static int MAX_ZOOM = 15;

    public TileProviderOsm() {
        super(TILE_WIDTH, TILE_HEIGHT);
    }

    @Override
    public synchronized URL getTileUrl(int x, int y, int zoom) {

        String s = String.format(Locale.US, MAP_URL, zoom, x, y);
        URL url = null;
        try {
             url = new URL(s);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return url;
    }
 }

Here's how I add the overlay to the map:

 map.addTileOverlay(new TileOverlayOptions().tileProvider(new TileProviderOsm()));

Here are some examples of the rendered Google Map:


回答1:


It's a problem with the zoom level and scaling of the map tiles. This seems to be a problem with the Maps API V2 for Android. The behavior is supposedly intended as stated here: gmaps-api-issues #4840

I solved it by requesting larger tiles from the WMS - just replace 256x256 with 512x512.




回答2:


I am solving this issue by drawing four tiles into one tile.

I wrote this TileProvider which is using another tile provider to create higher resolution tiles.

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

import com.google.android.gms.maps.model.Tile;
import com.google.android.gms.maps.model.TileProvider;

import java.io.ByteArrayOutputStream;

public class CanvasTileProvider implements TileProvider {

    static final int TILE_SIZE = 512;
    private TileProvider mTileProvider;

    public CanvasTileProvider(TileProvider tileProvider) {
        mTileProvider = tileProvider;
    }

    @Override
    public Tile getTile(int x, int y, int zoom) {
        byte[] data;
        Bitmap image = getNewBitmap();
        Canvas canvas = new Canvas(image);
        boolean isOk = onDraw(canvas, zoom, x, y);
        data = bitmapToByteArray(image);
        image.recycle();

        if (isOk) {
            Tile tile = new Tile(TILE_SIZE, TILE_SIZE, data);
            return tile;
        } else {
            return mTileProvider.getTile(x, y, zoom);
        }
    }

    Paint paint = new Paint();

    private boolean onDraw(Canvas canvas, int zoom, int x, int y) {
        x = x * 2;
        y = y * 2;
        Tile leftTop = mTileProvider.getTile(x, y, zoom + 1);
        Tile leftBottom = mTileProvider.getTile(x, y + 1, zoom + 1);
        Tile rightTop = mTileProvider.getTile(x + 1, y, zoom + 1);
        Tile rightBottom = mTileProvider.getTile(x + 1, y + 1, zoom + 1);

        if (leftTop == NO_TILE && leftBottom == NO_TILE && rightTop == NO_TILE && rightBottom == NO_TILE) {
            return false;
        }


        Bitmap bitmap;

        if (leftTop != NO_TILE) {
            bitmap = BitmapFactory.decodeByteArray(leftTop.data, 0, leftTop.data.length);
            canvas.drawBitmap(bitmap, 0, 0, paint);
            bitmap.recycle();
        }

        if (leftBottom != NO_TILE) {
            bitmap = BitmapFactory.decodeByteArray(leftBottom.data, 0, leftBottom.data.length);
            canvas.drawBitmap(bitmap, 0, 256, paint);
            bitmap.recycle();
        }
        if (rightTop != NO_TILE) {
            bitmap = BitmapFactory.decodeByteArray(rightTop.data, 0, rightTop.data.length);
            canvas.drawBitmap(bitmap, 256, 0, paint);
            bitmap.recycle();
        }
        if (rightBottom != NO_TILE) {
            bitmap = BitmapFactory.decodeByteArray(rightBottom.data, 0, rightBottom.data.length);
            canvas.drawBitmap(bitmap, 256, 256, paint);
            bitmap.recycle();
        }
        return true;
    }

    private Bitmap getNewBitmap() {
        Bitmap image = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE,
                Bitmap.Config.ARGB_8888);
        image.eraseColor(Color.TRANSPARENT);
        return image;
    }

    private static byte[] bitmapToByteArray(Bitmap bm) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, bos);

        byte[] data = bos.toByteArray();
        try {
            bos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return data;
    }
}


来源:https://stackoverflow.com/questions/23806348/blurred-custom-tiles-on-android-maps-v2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!