合并图像并将其转换为字节数组的最快方法

时间:2014-08-27 18:33:18

标签: android image google-maps bytearray tile

我正在为Google Maps API创建一个自定义UrlTileProvider来处理设备的分辨率:

  • 如果给定的图块是512x512px,则只返回图块
  • 如果给定的图块是256x256px,则在下一个缩放级别合并对应于所请求图块的四个图块以返回512x512px图块

由于GoogleMaps的TileProvider必须使用byte [],我需要能够:

  • 下载图像并将其转换为字节[] - 确定
  • 下载四张图片,将它们合并为一张,并将其转换为字节[] - KO

我有一个使用Android Bitmaps的工作解决方案,但合并+转换非常慢(大约1.5秒)。这是代码:

public class CustomUrlTileProvider implements TileProvider {

    // ---------------------------------------------------------------------------------------
    // Private attributes :

    private OnlineMapSource _source;
    // ---------------------------------------------------------------------------------------



    // ---------------------------------------------------------------------------------------
    // Constructor :

    public CustomUrlTileProvider(OnlineMapSource source) {

        this._source = source;
    }

    @Override
    public Tile getTile(int x, int y, int zoom) {

        if(_source.getTileSize().getWidth() == 256 && _source.getTileSize().getHeight() == 256) { return getTileFromNextZoomLevel(x, y, zoom); }
        else if(_source.getTileSize().getWidth() == 512 && _source.getTileSize().getHeight() == 512) { return getTileFromCurrentZoomLevel(x, y, zoom); }
        else return TileProvider.NO_TILE;
    }
    // ---------------------------------------------------------------------------------------



    // ---------------------------------------------------------------------------------------
    // Tile creation :

    public Tile getTileFromNextZoomLevel(int x, int y, int zoom) {

        String topLeftTileUrl = _source.getUrlSchema().replace("{z}", "" + (zoom + 1)).replace("{x}", "" + (x * 2)).replace("{y}", "" + (y * 2));
        String topRightTileUrl = _source.getUrlSchema().replace("{z}", "" + (zoom + 1)).replace("{x}", "" + (x * 2 + 1)).replace("{y}", "" + (y * 2));
        String bottomLeftTileUrl = _source.getUrlSchema().replace("{z}", "" + (zoom + 1)).replace("{x}", "" + (x * 2)).replace("{y}", "" + (y * 2 + 1));
        String bottomRightTileUrl = _source.getUrlSchema().replace("{z}", "" + (zoom + 1)).replace("{x}", "" + (x * 2 + 1)).replace("{y}", "" + (y * 2 + 1));

        Bitmap topLeftTile = Utils.getBitmapFromURL(topLeftTileUrl);
        Bitmap topRightTile = Utils.getBitmapFromURL(topRightTileUrl);
        Bitmap bottomLeftTile = Utils.getBitmapFromURL(bottomLeftTileUrl);
        Bitmap bottomRightTile = Utils.getBitmapFromURL(bottomRightTileUrl);

        Bitmap[] parts = {
            topLeftTile,
            topRightTile,
            bottomLeftTile,
            bottomRightTile
        };

        Bitmap tileBitmap = Bitmap.createBitmap(parts[0].getWidth() * 2, parts[0].getHeight() * 2, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(tileBitmap);
        Paint paint = new Paint();
        for (int i = 0; i < parts.length; i++) {
            canvas.drawBitmap(parts[i], parts[i].getWidth() * (i % 2), parts[i].getHeight() * (i / 2), paint);
        }

        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        tileBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);

        byte[] tile = stream.toByteArray();

        return tile == null ? TileProvider.NO_TILE : new Tile(_source.getTileSize().getWidth(), _source.getTileSize().getHeight(), tile);
    }

    public Tile getTileFromCurrentZoomLevel(int x, int y, int zoom) {

        String tileUrl = _source.getUrlSchema().replace("{z}", "" + zoom).replace("{x}", "" + x).replace("{y}", "" + y);

        byte[] tile = Utils.getByteArrayFromURL(tileUrl);

        return tile == null ? TileProvider.NO_TILE : new Tile(_source.getTileSize().getWidth(), _source.getTileSize().getHeight(), tile);
    }
    // ---------------------------------------------------------------------------------------
}

Utils.getBitmapFromURL和Utils.getByteArrayFromURL方法:

public static Bitmap getBitmapFromURL(String src) {

    try {
        URL url = new URL(src);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);

        return myBitmap;
    }
    catch (IOException e) { return null; }
}

public static byte[] getByteArrayFromURL(String src) {

    ByteArrayOutputStream bais = new ByteArrayOutputStream();
    InputStream is = null;
    try {

        is = new URL(src).openStream();
        byte[] byteChunk = new byte[4096];
        int n;

        while ((n = is.read(byteChunk)) > 0) {
            bais.write(byteChunk, 0, n);
        }
    }
    catch (IOException e) { e.printStackTrace(); }
    finally {
        if (is != null) {
            try { is.close(); }
            catch (IOException e) { e.printStackTrace(); }
        }
    }

    return bais.toByteArray();
}

所以问题是:是否有更快的方法来实现第二个操作(下载4个图像 - &gt;合并它们 - &gt;将结果转换为byte [])?为了简化,有没有办法将四个bye [](代表图像)合并为一个?

编辑:我发现花时间不是合并,而是转换Bitmap - &gt;字节[]。所以我知道尝试使用Bitmap.copyPixelsToBuffer而不是Bitmap.compress,没有成功(没有例外,但没有显示图像)。有什么想法吗?

由于

1 个答案:

答案 0 :(得分:0)

通过网络检索磁贴可能花费了大部分时间。如果是这样的话,那么通过更有效的代码可以实现的效率提升将会产生相应的小影响。您无法通过代码加速网络。

相关问题