2016-07-28 3 views
2

この質問が回答しているかどうかわかりません。少なくとも私は答えを見つけられませんでした。Androidで大きなビットマップを描く

ここには何かがあります:私はアンドロイドで空間テーマの2Dゲームを作っており、画面サイズ= 2560x1600のエミュレータでテストしています。このゲームでは、宇宙船が飛んでいるフィールドがあります。そして、もちろん(フィールド)は、高解像度で美しい背景を持っている必要があります。私の背景イメージの解像度は4500x4500です。私はカメラの動きに相対して画像を反対方向に動かしたいので、小さな静止画像を使うことができないのです。当時この画像の一部のみが表示されます:

Example 1

私はFPS = 1-2(もちろん、それが原因で、画像サイズの低い)を得、それを描画しようとしたとき

canvas.drawBitmap(getBigImage(), -x, -y, null); 
/* getBigImage() method does nothing but returning 
a Bitmap object (no calculation or decoding is performing in there) */ 

私は大きなものから必要な画像を切り出すことを試みたが、FPSはまだ低かった:

Bitmap b = Bitmap.createBitmap(getBigImage(), x, y, sw, sh); 
canvas.drawBitmap(b, 0, 0, null); 

どのように私は高いFPSで、この大きなビットマップを描くことができますか?

答えて

1

私はたくさんのことを考えていました。入力ビットマップを小さなチャンクに分割し、それらをアレイに保存するアイデアが出てきました。だから私はビットマップを描画するためには、目に見えるチャンクを描画するだけです。

画像:

enter image description here

大きな黒い長方形は入力ビットマップを意味し、緑色の長方形がビューポートを意味し、赤い四角形は

を描かれている目に見える塊を意味し、私はそのすべて(ないオブジェクトを書いてきました私はまだバグを確認していませんでした:/)。私はそれをテストし、〜45 fpsで3000x3000ビットマップを描画します。私はこの方法を非常に効果的だと考えています。オブジェクト自体はさらに開発する必要があるかもしれませんが、私はこの機能が私のニーズに十分だと思います。誰かを助けることを願って:)

P.S. https://stackoverflow.com/a/25953122/6121671 - インスピレーションのためにこれを使用しました:)

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

public final class DividedBitmap { 
    private final Bitmap[][] mArray; // array where chunks is stored 

    private final int mWidth;   // original (full) width of source image 
    private final int mHeight;   // original (full) height of source image 
    private final int mChunkWidth;  // default width of a chunk 
    private final int mChunkHeight;  // default height of a chunk 

    /* Init */ 

    public DividedBitmap(Bitmap src) { 
     this(new Options(src, 100, 100)); 
    } 

    public DividedBitmap(Options options) { 
     mArray = divideBitmap(options); 

     mWidth = options.source.getWidth(); 
     mHeight = options.source.getHeight(); 
     mChunkWidth = options.chunkWidth; 
     mChunkHeight = options.chunkHeight; 
    } 

    /* Getters */ 

    public int getWidth() { 
     return mWidth; 
    } 

    public int getHeight() { 
     return mHeight; 
    } 

    public Bitmap getChunk(int x, int y) { 
     if (mArray.length < x && x > 0 && mArray[x].length < y && y > 0) { 
      return mArray[x][y]; 
     } 

     return null; 
    } 

    /* Methods */ 

    /** 
    * x, y are viewport coords on the image itself; 
    * w, h are viewport's width and height. 
    */ 
    public void draw(Canvas canvas, int x, int y, int w, int h, Paint paint) { 
     if (x >= getWidth() || y >= getHeight() || x + w <= 0 || y + h <= 0) 
      return; 

     int i1 = x/mChunkWidth;   // i1 and j1 are indices of visible chunk that is 
     int j1 = y/mChunkHeight;   // on the top-left corner of the screen 
     int i2 = (x + w)/mChunkWidth;  // i2 and j2 are indices of visible chunk that is 
     int j2 = (y + h)/mChunkHeight; // on the right-bottom corner of the screen 

     i2 = i2 >= mArray.length ? mArray.length - 1 : i2; 
     j2 = j2 >= mArray[i2].length ? mArray[i2].length - 1 : j2; 

     int offsetX = x - i1 * mChunkWidth; 
     int offsetY = y - j1 * mChunkHeight; 

     for (int i = i1; i <= i2; i++) { 
      for (int j = j1; j <= j2; j++) { 
       canvas.drawBitmap(
         mArray[i][j], 
         (i - i1) * mChunkWidth - offsetX, 
         (j - j1) * mChunkHeight - offsetY, 
         paint 
       ); 
      } 
     } 
    } 

    /* Static */ 

    public static Bitmap[][] divideBitmap(Bitmap bitmap) { 
     return divideBitmap(new Options(bitmap, 100, 100)); 
    } 

    public static Bitmap[][] divideBitmap(Options options) { 
     Bitmap[][] arr = new Bitmap[options.xCount][options.yCount]; 

     for (int x = 0; x < options.xCount; ++x) { 
      for (int y = 0; y < options.yCount; ++y) { 
       int w = Math.min(options.chunkWidth, options.source.getWidth() - (x * options.chunkWidth)); 
       int h = Math.min(options.chunkHeight, options.source.getHeight() - (y * options.chunkHeight)); 
       arr[x][y] = Bitmap.createBitmap(options.source, x * options.chunkWidth, y * options.chunkHeight, w, h); 
      } 
     } 

     return arr; 
    } 

    public static final class Options { 
     final int chunkWidth; 
     final int chunkHeight; 
     final int xCount; 
     final int yCount; 
     final Bitmap source; 

     public Options(Bitmap src, int chunkW, int chunkH) { 
      chunkWidth = chunkW; 
      chunkHeight = chunkH; 

      xCount = ((src.getWidth() - 1)/chunkW) + 1; 
      yCount = ((src.getHeight() - 1)/chunkH) + 1; 

      source = src; 
     } 

     public Options(int xc, int yc, Bitmap src) { 
      xCount = xc; 
      yCount = yc; 

      chunkWidth = src.getWidth()/xCount; 
      chunkHeight = src.getHeight()/yCount; 

      source = src; 
     } 
    } 
} 
3

キャンバス上の矩形に表示するソース画像からピクセルの矩形をとる

drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) 

を試してみてください。私はスクロールゲームをしたとき、これがより速く戻ることがわかった。

+0

実際に入力画像からsrc矩形を切り取るか、サイズを変更するだけですか?そして、src.x + src.width> bitmap.width?その場合、例外はスローされません。 –

+0

単純にソース矩形内のイメージをキャンバスの矩形に描画します。ソースビットマップのピクセルは削除されません。ソースの四角形がソースのビットマップより大きい場合、私は例外があると確信しています。それがあなたのFPSをまったく改善できるかどうかをすぐに試してみてください。 –

+0

私はこれを次のようにテストしました: 'Rect rect = new Rect(0、0、sw、sh); ビットマップb = Data.Images.getImage(R.drawable.neb_1); canvas.drawBitmap(b、rect、rect、null); ' Fpsはまだ低かった(1-2)。 非常に大きな画像を描画するためのトリックや何かがあるかもしれません。 –

関連する問題