Bitmapをアスペクト比を保ったままリサイズする


クラスの内容はvolleyでImageRequestをした後に行われるリサイズ処理を抜き出して軽く機能を削ったものです。
これ単体でも何かと便利なので抜き出してBitmapのリサイズに使わせてもらっています。

## URIを受け取って指定したmaxSizeに合わせてリサイズしたBitmapを返すクラスです。

```java:BitmapResizer.java
public class BitmapResizer {
    private Context context;

    public BitmapResizer(Context context) {
        this.context = context;
    }

    public Bitmap resize(Uri uri,int mMaxWidth,int mMaxHeight) throws IOException {

        Bitmap bitmap = null;
        BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
        decodeOptions.inJustDecodeBounds = true;
        InputStream inputStream = context.getContentResolver().openInputStream(uri);
        BitmapFactory.decodeStream(inputStream,null,decodeOptions);
        inputStream.close();
        int actualWidth = decodeOptions.outWidth;
        int actualHeight = decodeOptions.outHeight;

        int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight,
                actualWidth, actualHeight);
        int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth,
                actualHeight, actualWidth);

        decodeOptions.inJustDecodeBounds = false;
        decodeOptions.inSampleSize =
                findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight);

        inputStream = context.getContentResolver().openInputStream(uri);
        Bitmap tempBitmap = BitmapFactory.decodeStream(inputStream,null,decodeOptions);
        inputStream.close();

        if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth ||
                tempBitmap.getHeight() > desiredHeight)) {
            bitmap = Bitmap.createScaledBitmap(tempBitmap,
                    desiredWidth, desiredHeight, true);
            tempBitmap.recycle();
        } else {
            bitmap = tempBitmap;
        }
        return bitmap;
    }

    private int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary,
                                           int actualSecondary) {
        if ((maxPrimary == 0) && (maxSecondary == 0)) {
            return actualPrimary;
        }

        if (maxPrimary == 0) {
            double ratio = (double) maxSecondary / (double) actualSecondary;
            return (int) (actualPrimary * ratio);
        }

        if (maxSecondary == 0) {
            return maxPrimary;
        }

        double ratio = (double) actualSecondary / (double) actualPrimary;
        int resized = maxPrimary;

        if ((resized * ratio) < maxSecondary) {
            resized = (int) (maxSecondary / ratio);
        }
        return resized;
    }

    static int findBestSampleSize(
            int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) {
        double wr = (double) actualWidth / desiredWidth;
        double hr = (double) actualHeight / desiredHeight;
        double ratio = Math.min(wr, hr);
        float n = 1.0f;
        while ((n * 2) <= ratio) {
            n *= 2;
        }
        return (int) n;
    }
}
```

## 使用例

Intentでギャラリーなどから画像のURIを取得して
その画像をリサイズします

```java:MainActivity.java
public class MainActivity extends ActionBarActivity {
    private int REQUEST_GALLERY = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(intent, REQUEST_GALLERY);
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_GALLERY && resultCode == Activity.RESULT_OK) {
            BitmapResizer bitmapResizer = new BitmapResizer(this);
            try {
                Bitmap bitmap = bitmapResizer.resize(data.getData(),500,500);//アスペクト比を保ったままいい感じにリサイズされたBitmapが返ってくる
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
```

このサンプルではURIからbitmapを取得してリサイズしていますが
リソースからでもbyte[]からでもBitmapFactoryでBitmapを取得する処理の所を変えれば大丈夫です。

もともとのvolleyのソースはこちらです。
https://github.com/mcxiaoke/android-volley/blob/master/src/main/java/com/android/volley/toolbox/ImageRequest.java