2013-03-27 8 views
14

Androidアプリに多少大きな画像を表示する必要があります。 今私はImageViewをソースBitmapで使用しています。 OpenGLには、画像サイズが処理するためにどれくらいの大きさがあるかについて、 について、デバイスに依存しない制限があることを理解しています。 Androidのテクスチャサイズの制限を処理する

は、これらの画像表示するANY方法複数ImageViewの要素に画像を分割するより 他のかかわらず、この制限の(固定された幅は、トリミングなし)がありますか?

ありがとうございます。

更新日01 4月2013 これまでのところ、すべての提案は画質を低下させることでした。 GPUを使用する代わりにCPUを使用してこの制限を回避することが可能であることを示唆しています(処理に時間がかかるかもしれませんが)。 イメージの品質を落とさずに、固定幅の長いイメージを表示する方法はありませんか?誰かが少なくとも私を正しい方向に向けるなら、私はそれが大好きだと思う。

ありがとうございました。

+1

私はこれについてはわかりませんが、代わりにWebViewを使ってみましたか? –

+1

本当に、私はリストビュー上にランダムに配置された非常に大きな画像の複数のインスタンスを持っています。私はパフォーマンスを考慮する必要があり、これはかなり悪い考えのように聞こえます。 – woot

+0

この素晴らしいプロジェクトを見てください:https://github.com/ened/Android-Tiling-ScrollView –

答えて

9

BitmapRegionDecoderを使用すると、より大きなビットマップを分割できます(APIレベル10が必要)。私はこのクラスを利用して内側に配置することができ、単一のDrawableを返します方法を書いてきましたImageView:メソッドは、描画可能リソースは両方でMAX_SIZE(1024)よりも小さいかどうかをチェックします

private static final int MAX_SIZE = 1024; 

private Drawable createLargeDrawable(int resId) throws IOException { 

    InputStream is = getResources().openRawResource(resId); 
    BitmapRegionDecoder brd = BitmapRegionDecoder.newInstance(is, true); 

    try { 
     if (brd.getWidth() <= MAX_SIZE && brd.getHeight() <= MAX_SIZE) { 
      return new BitmapDrawable(getResources(), is); 
     } 

     int rowCount = (int) Math.ceil((float) brd.getHeight()/(float) MAX_SIZE); 
     int colCount = (int) Math.ceil((float) brd.getWidth()/(float) MAX_SIZE); 

     BitmapDrawable[] drawables = new BitmapDrawable[rowCount * colCount]; 

     for (int i = 0; i < rowCount; i++) { 

      int top = MAX_SIZE * i; 
      int bottom = i == rowCount - 1 ? brd.getHeight() : top + MAX_SIZE; 

      for (int j = 0; j < colCount; j++) { 

       int left = MAX_SIZE * j; 
       int right = j == colCount - 1 ? brd.getWidth() : left + MAX_SIZE; 

       Bitmap b = brd.decodeRegion(new Rect(left, top, right, bottom), null); 
       BitmapDrawable bd = new BitmapDrawable(getResources(), b); 
       bd.setGravity(Gravity.TOP | Gravity.LEFT); 
       drawables[i * colCount + j] = bd; 
      } 
     } 

     LayerDrawable ld = new LayerDrawable(drawables); 
     for (int i = 0; i < rowCount; i++) { 
      for (int j = 0; j < colCount; j++) { 
       ld.setLayerInset(i * colCount + j, MAX_SIZE * j, MAX_SIZE * i, 0, 0); 
      } 
     } 

     return ld; 
    } 
    finally { 
     brd.recycle(); 
    } 
} 

軸。そうであれば、drawableを返します。そうでない場合は、イメージを分割してイメージのチャンクをデコードし、 LayerDrawableに配置します。

私は、ほとんどの利用可能な携帯電話が少なくともそれ以上の大きさの画像をサポートすると考えているため、1024を選択しました。電話機の実際のテクスチャサイズの制限を調べるには、OpenGLでファンキーなことをする必要があります。それは私が夢中にしたいことではありません。

画像にどのようにアクセスしていたのかわからなかったので、それらがあなたのドロウアブルフォルダにあると仮定しました。そうでない場合は、必要なパラメータを取り込むメソッドをリファクタリングするのはかなり簡単です。

+0

この実装は、グリッドではなく行に分割するだけであることに注意してください。幅が最大サイズより大きい場合はアルゴリズムを通過しますが、チャンクにはまだMAX_SIZEより大きな幅が含まれます。それをサポートするための簡単な修正ですが、私はLayerDrawableを使って描画可能なグリッドを表示することは考えていませんでした。素晴らしい答え。 –

+0

修正プログラムで編集して、単なる行ではなく正方形のチャンクに分割します。 –

+0

あなたの追加@DavidLiuをありがとう。私が世話した編集にはいくつかの誤りがありました。私の編集内容を見直して、私が編集の意図を破っていないことを確認してください。このメソッドは 'IOException'をスローします。これがcatchが必要ない理由です。 –

3

あなたはそのように気にいらを使用することができますpicture.Youのサイズを小さくするためにBitmapFactoryOptionsを使用することができます。

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inSampleSize = 3; //reduce size 3 times 
+0

ありがとうございます私は画質を落とさずに希望の結果を達成することができましたか? – woot

+0

私は画質を落とさずに解決策はないと思います。オーバーフローエラーが発生するためです。 – developerCoder

0

あなたは私達にあなたのビットマップの大きさを与えた場合、それが役立つだろう。

OpenGLは自然な数学的な制限に反することにご注意ください。

例えば、OpenGLのテクスチャがxの威力を2にしなければならない理由は非常にあります。これは、実際には、ダウンスケーリングの数学が余りなくてもきれいに行える唯一の方法です。

問題を起こしている最小のビットマップの正確な大きさを教えてください。私たちの中には、どのような実際の制限を実行しているのかが分かる場合があります。

+0

ビットマップのサイズは動的です。幅は480px、高さは1pxと10000pxの間で設定できます。表示されるべき所望の幅は、画面の幅からいくつかのマージンを差し引いた幅である。画像は、左上からアスペクト比クロッピングを維持しながら、希望の幅にスケーリングする必要があります。 – woot

+0

その後、OpenGLのテクスチャではありません。それをそのように扱わないでください。 OpenGLで背景画像を作成することはできますが、テクスチャとして扱わない限り、うまくいくでしょう。 –

+0

テクスチャとして扱わないということはどういう意味ですか?私はOpenGLを直接使用していません。私が行うのはImageViewのソースに設定されているため、デバイスのテクスチャサイズの制限のために画像が表示されません。たとえば、「ビットマップが大きすぎてNexus 10のテクスチャ(480x5400、最大= 4096x4096)にアップロードできない」 – woot

2

マップの仕組みを見てきましたか?私はマップのレンダラーを一度作っていました。同じトリックを使ってイメージを表示することができます。

画像を正方形のタイル(たとえば、128x128ピクセル)に分割します。タイルからのレンダリングをサポートするカスタムimageViewを作成します。あなたのimageViewは、現在表示されているビットマップの部分を知っていて、あなたのSDカードから読み込んだ必要なタイルだけを表示します。このようなタイルマップを使用すると、無限の画像を表示できます。

関連する問題