バックグラウンド
多くの高品質の画像を含むアプリを作成するため、画像を必要なサイズに縮小することにしました (つまり、画像が画面よりも大きい場合は縮小します)。
問題
一部のデバイスでは、画像が縮小されている場合、画像がぼやけたりピクセル化されたりしますが、同じデバイスで、同じターゲット imageView サイズに対して、画像が縮小されていない場合は問題なく表示されることに気付きました。
私が試したこと
この問題をさらに確認することにし、問題を示す小さな POC アプリを作成しました。
コードをお見せする前に、私が話していることのデモを次に示します。
違いがわかりにくいですが、2番目は少しピクセル化されていることがわかります。これはどの画像にも表示できます。
public class MainActivity extends Activity
{
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView originalImageView=(ImageView)findViewById(R.id.originalImageView);
final ImageView halvedImageView=(ImageView)findViewById(R.id.halvedImageView);
final ImageView halvedBitmapImageView=(ImageView)findViewById(R.id.halvedBitmapImageView);
//
final Bitmap originalBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.test);
originalImageView.setImageBitmap(originalBitmap);
halvedImageView.setImageBitmap(originalBitmap);
//
final LayoutParams layoutParams=halvedImageView.getLayoutParams();
layoutParams.width=originalBitmap.getWidth()/2;
layoutParams.height=originalBitmap.getHeight()/2;
halvedImageView.setLayoutParams(layoutParams);
//
final Options options=new Options();
options.inSampleSize=2;
// options.inDither=true; //didn't help
// options.inPreferQualityOverSpeed=true; //didn't help
final Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.test,options);
halvedBitmapImageView.setImageBitmap(bitmap);
}
}
xml:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".MainActivity"
android:fillViewport="true">
<HorizontalScrollView android:layout_width="match_parent"
android:fillViewport="true" android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent" android:orientation="vertical">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="original" />
<ImageView android:layout_width="wrap_content"
android:id="@+id/originalImageView" android:layout_height="wrap_content" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="original , imageView size is halved" />
<ImageView android:layout_width="wrap_content"
android:id="@+id/halvedImageView" android:layout_height="wrap_content" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="bitmap size is halved" />
<ImageView android:layout_width="wrap_content"
android:id="@+id/halvedBitmapImageView" android:layout_height="wrap_content" />
</LinearLayout>
</HorizontalScrollView>
</ScrollView>
質問
なぜ発生するのですか?
どちらの方法も、同じソースから同じ因子を使用してサンプリングするため、同じ結果になるはずです。
ダウンサンプリング法を試してみましたが、何も役に立ちませんでした。
(inSampleSizeの代わりに)inDensityを使用すると修正されるようですが、何を設定すればよいかわかりません。外部の画像(インターネットなど)の場合、使用したいサンプルサイズを掛けた画面密度に設定できると思います。
しかし、それは良い解決策ですか?画像がリソースフォルダー内にある場合はどうすればよいですか(ビットマップが配置されている密度フォルダーを取得する機能はないと思います)?推奨される方法(ここで説明)を使用してもうまくいかないのに、なぜうまくいくのですか?
編集:リソースから取得したドローアブルに使用される密度を取得するためのトリックを見つけました(リンクはこちら)。ただし、検出する密度に固有である必要があるため、将来の証明ではありません。