ファイルに大きなビットマップ(3888x2592など)があります。次に、そのビットマップのサイズを800x533に変更し、別のファイルに保存します。通常、Bitmap.createBitmap
メソッドを呼び出してビットマップをスケーリングしますが、最初の引数としてソースビットマップが必要です。元の画像をBitmapオブジェクトに読み込むと、もちろんメモリを超えるため、提供できません(- ここ 、たとえば)。
また、正確な幅と高さにサイズを変更するため、BitmapFactory.Options.inSampleSize
を提供するBitmapFactory.decodeFile(file, options)
などでビットマップを読み取ることもできません。 inSampleSize
を使用すると、ビットマップのサイズが972x648(inSampleSize=4
を使用する場合)または778x518(inSampleSize=5
を使用する場合、2の累乗ではない)にサイズ変更されます。
また、たとえば、最初のステップで972x648を使用してinSampleSizeを使用してイメージを読み取ってから、2番目のステップで正確に800x533にサイズ変更することは避けたいと思います。
私の質問をまとめると、10MP以上の大きな画像ファイルを読み取り、特定の新しい幅と高さにサイズ変更した新しい画像ファイルに保存する方法はありますか?
BitmapFactory.decodeFile(file, options)
も試して、Options.outHeightとOptions.outWidthの値を手動で800と533に設定しましたが、それはうまくいきません。
番号。誰かが私を直すことを望みますが、妥協点として試みたロード/サイズ変更アプローチを受け入れました。
閲覧している人のための手順は次のとおりです。
inSampleSize
を計算します。BitmapFactory.decodeFile(file, options)
を使用して画像をロードします。Bitmap.createScaledBitmap()
を使用して目的のサイズにサイズ変更します。Justin answerがコードに翻訳されました(私にとっては完璧です)。
private Bitmap getBitmap(String path) {
Uri uri = getImageUri(path);
InputStream in = null;
try {
final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
in = mContentResolver.openInputStream(uri);
// Decode image size
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
in.close();
int scale = 1;
while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) >
IMAGE_MAX_SIZE) {
scale++;
}
Log.d(TAG, "scale = " + scale + ", orig-width: " + options.outWidth + ",
orig-height: " + options.outHeight);
Bitmap resultBitmap = null;
in = mContentResolver.openInputStream(uri);
if (scale > 1) {
scale--;
// scale to max possible inSampleSize that still yields an image
// larger than target
options = new BitmapFactory.Options();
options.inSampleSize = scale;
resultBitmap = BitmapFactory.decodeStream(in, null, options);
// resize to desired dimensions
int height = resultBitmap.getHeight();
int width = resultBitmap.getWidth();
Log.d(TAG, "1th scale operation dimenions - width: " + width + ",
height: " + height);
double y = Math.sqrt(IMAGE_MAX_SIZE
/ (((double) width) / height));
double x = (y / height) * width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(resultBitmap, (int) x,
(int) y, true);
resultBitmap.recycle();
resultBitmap = scaledBitmap;
System.gc();
} else {
resultBitmap = BitmapFactory.decodeStream(in);
}
in.close();
Log.d(TAG, "bitmap size - width: " +resultBitmap.getWidth() + ", height: " +
resultBitmap.getHeight());
return resultBitmap;
} catch (IOException e) {
Log.e(TAG, e.getMessage(),e);
return null;
}
これは「Mojo Risin」と「Ofir」のソリューションを「組み合わせた」ものです。これにより、最大幅と最大高さの境界を持つ比例サイズ変更された画像が得られます。
私にとっては、5メガピクセル以下の画像で問題なく動作しています。
try
{
int inWidth = 0;
int inHeight = 0;
InputStream in = new FileInputStream(pathOfInputImage);
// decode image size (decode metadata only, not the whole image)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
in.close();
in = null;
// save width and height
inWidth = options.outWidth;
inHeight = options.outHeight;
// decode full image pre-resized
in = new FileInputStream(pathOfInputImage);
options = new BitmapFactory.Options();
// calc rought re-size (this is no exact resize)
options.inSampleSize = Math.max(inWidth/dstWidth, inHeight/dstHeight);
// decode full image
Bitmap roughBitmap = BitmapFactory.decodeStream(in, null, options);
// calc exact destination size
Matrix m = new Matrix();
RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
RectF outRect = new RectF(0, 0, dstWidth, dstHeight);
m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
float[] values = new float[9];
m.getValues(values);
// resize bitmap
Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);
// save image
try
{
FileOutputStream out = new FileOutputStream(pathOfOutputImage);
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
}
catch (Exception e)
{
Log.e("Image", e.getMessage(), e);
}
}
catch (IOException e)
{
Log.e("Image", e.getMessage(), e);
}
なぜAPIを使わないのですか?
int h = 48; // height in pixels
int w = 48; // width in pixels
Bitmap scaled = Bitmap.createScaledBitmap(largeBitmap, w, h, true);
これまでのところ他の優れた答えを認めて、私がこれのために今までに見た最もよいコードは写真撮影ツールのためのドキュメンテーションにあります。
「拡大縮小画像のデコード」というタイトルのセクションを参照してください。
http://developer.Android.com/training/camera/photobasics.html
それが提案する解決策は、ここで他の人たちのようにサイズを変更して拡大縮小する解決策です、しかし、それはかなりきれいです。
便宜上、すぐに使える機能として以下のコードをコピーしました。
private void setPic(String imagePath, ImageView destination) {
int targetW = destination.getWidth();
int targetH = destination.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions);
destination.setImageBitmap(bitmap);
}
これらの答えを読んだ後、 Androidのドキュメント これは、メモリに読み込まずにビットマップのサイズを変更するためのコードです。
public Bitmap getResizedBitmap(int targetW, int targetH, String imagePath) {
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
//inJustDecodeBounds = true <-- will not load the bitmap into memory
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions);
return(bitmap);
}
大きなビットマップを持っていてサイズを変えてデコードしたいときは、次のようにします。
BitmapFactory.Options options = new BitmapFactory.Options();
InputStream is = null;
is = new FileInputStream(path_to_file);
BitmapFactory.decodeStream(is,null,options);
is.close();
is = new FileInputStream(path_to_file);
// here w and h are the desired width and height
options.inSampleSize = Math.max(options.outWidth/w, options.outHeight/h);
// bitmap is the resized bitmap
Bitmap bitmap = BitmapFactory.decodeStream(is,null,options);
これは他の誰かがこの質問を見るのに役立つかもしれません。私はJustinのコードを書き換えて、メソッドが必要なターゲットサイズオブジェクトを受け取ることができるようにしました。 Canvasを使用している場合、これはとてもうまくいきます。すべての功績は彼のすばらしい初期コードのためにJUSTINに行くべきです。
private Bitmap getBitmap(int path, Canvas canvas) {
Resources resource = null;
try {
final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
resource = getResources();
// Decode image size
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(resource, path, options);
int scale = 1;
while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) >
IMAGE_MAX_SIZE) {
scale++;
}
Log.d("TAG", "scale = " + scale + ", orig-width: " + options.outWidth + ", orig-height: " + options.outHeight);
Bitmap pic = null;
if (scale > 1) {
scale--;
// scale to max possible inSampleSize that still yields an image
// larger than target
options = new BitmapFactory.Options();
options.inSampleSize = scale;
pic = BitmapFactory.decodeResource(resource, path, options);
// resize to desired dimensions
int height = canvas.getHeight();
int width = canvas.getWidth();
Log.d("TAG", "1th scale operation dimenions - width: " + width + ", height: " + height);
double y = Math.sqrt(IMAGE_MAX_SIZE
/ (((double) width) / height));
double x = (y / height) * width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(pic, (int) x, (int) y, true);
pic.recycle();
pic = scaledBitmap;
System.gc();
} else {
pic = BitmapFactory.decodeResource(resource, path);
}
Log.d("TAG", "bitmap size - width: " +pic.getWidth() + ", height: " + pic.getHeight());
return pic;
} catch (Exception e) {
Log.e("TAG", e.getMessage(),e);
return null;
}
}
ジャスティンのコードは、大きなビットマップを扱うオーバーヘッドを減らすのに非常に効果的です。
私の解決策がベストプラクティスであるかどうかはわかりませんが、inDensity
およびinTargetDensity
オプションを使用して、希望のスケーリングでビットマップをロードすることができました。描画可能リソースをロードしていない場合、inDensity
は最初は0
なので、このアプローチは非リソースイメージをロードするためのものです。
変数imageUri
、maxImageSideLength
、およびcontext
は、私のメソッドのパラメータです。わかりやすくするために、AsyncTaskをラップせずにメソッド実装のみを掲載しました。
ContentResolver resolver = context.getContentResolver();
InputStream is;
try {
is = resolver.openInputStream(imageUri);
} catch (FileNotFoundException e) {
Log.e(TAG, "Image not found.", e);
return null;
}
Options opts = new Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, opts);
// scale the image
float maxSideLength = maxImageSideLength;
float scaleFactor = Math.min(maxSideLength / opts.outWidth, maxSideLength / opts.outHeight);
// do not upscale!
if (scaleFactor < 1) {
opts.inDensity = 10000;
opts.inTargetDensity = (int) ((float) opts.inDensity * scaleFactor);
}
opts.inJustDecodeBounds = false;
try {
is.close();
} catch (IOException e) {
// ignore
}
try {
is = resolver.openInputStream(imageUri);
} catch (FileNotFoundException e) {
Log.e(TAG, "Image not found.", e);
return null;
}
Bitmap bitmap = BitmapFactory.decodeStream(is, null, opts);
try {
is.close();
} catch (IOException e) {
// ignore
}
return bitmap;
あなたが正確なサイズにリサイズしたいと思い、必要とされるだけ多くの品質を保ちたいということを考慮して、私はあなたがこれを試みるべきであると思います。
動機づけ:マルチステップスケーリングはあなたに高品質の写真を与えるかもしれません、しかし、それが高いinSampleSizeを使うことよりよく働くという保証はありません。実際には、inSampleSizeを5のように(2のべき乗ではなく)使用して、1回の操作で直接スケーリングすることもできます。または4を使用するだけで、その画像をUIで使用できます。あなたがそれをサーバーに送るなら - あなたはあなたが高度なスケーリング技術を使うことを可能にするサーバー側で正確なサイズにスケーリングすることができるよりも。
注:step-3で読み込まれたビットマップが少なくとも4倍大きい場合(つまり4 * targetWidth <width)、品質を向上させるためにいくつかのサイズ変更を使用することができます。少なくともそれは一般的なJavaで動作します、Androidではスケーリングに使用される補間を指定するオプションはありません http://today.Java.net/pub/a/today/2007/04/03/ perils-of-image-getscaledinstance.html
上記のコードは少しきれいになりました。 InputStreamは、同様に閉じられるように、最後に閉じています。
*注意
入力:InputStreamは、int w、int hです。
出力:ビットマップ
try
{
final int inWidth;
final int inHeight;
final File tempFile = new File(temp, System.currentTimeMillis() + is.toString() + ".temp");
{
final FileOutputStream tempOut = new FileOutputStream(tempFile);
StreamUtil.copyTo(is, tempOut);
tempOut.close();
}
{
final InputStream in = new FileInputStream(tempFile);
final BitmapFactory.Options options = new BitmapFactory.Options();
try {
// decode image size (decode metadata only, not the whole image)
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
}
finally {
in.close();
}
// save width and height
inWidth = options.outWidth;
inHeight = options.outHeight;
}
final Bitmap roughBitmap;
{
// decode full image pre-resized
final InputStream in = new FileInputStream(tempFile);
try {
final BitmapFactory.Options options = new BitmapFactory.Options();
// calc rought re-size (this is no exact resize)
options.inSampleSize = Math.max(inWidth/w, inHeight/h);
// decode full image
roughBitmap = BitmapFactory.decodeStream(in, null, options);
}
finally {
in.close();
}
tempFile.delete();
}
float[] values = new float[9];
{
// calc exact destination size
Matrix m = new Matrix();
RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
RectF outRect = new RectF(0, 0, w, h);
m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
m.getValues(values);
}
// resize bitmap
final Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);
return resizedBitmap;
}
catch (IOException e) {
logger.error("Error:" , e);
throw new ResourceException("could not create bitmap");
}
私はこのようなコードを使用しました:
String filePath=Environment.getExternalStorageDirectory()+"/test_image.jpg";
BitmapFactory.Options options=new BitmapFactory.Options();
InputStream is=new FileInputStream(filePath);
BitmapFactory.decodeStream(is, null, options);
is.close();
is=new FileInputStream(filePath);
// here w and h are the desired width and height
options.inSampleSize=Math.max(options.outWidth/460, options.outHeight/288); //Max 460 x 288 is my desired...
// bmp is the resized bitmap
Bitmap bmp=BitmapFactory.decodeStream(is, null, options);
is.close();
Log.d(Constants.TAG, "Scaled bitmap bytes, "+bmp.getRowBytes()+", width:"+bmp.getWidth()+", height:"+bmp.getHeight());
私はオリジナルの画像が1230 x 1230であることを試してみました、そして得られたビットマップは330 x 330であると言いました。
そして2590 x 3849を試してみると、OutOfMemoryErrorが出ます。
私はそれをトレースしました、それでもまだ元のビットマップが大きすぎるならば、それはライン "BitmapFactory.decodeStream(is、null、options);"にOutOfMemoryErrorを投げます...
これはサイズ変更に別のアプローチをとる記事です。プロセスで使用可能なメモリに基づいて、可能な限り大きいビットマップをメモリにロードしてから、変換を実行します。
http://bricolsoftconsulting.com/2012/12/07/handling-large-images-on-Android/
ピクセルをスキップせずに画像を「正しい」方法で拡大縮小するには、画像デコーダにフックして、行ごとにダウンサンプリングを実行する必要があります。 Android(およびその基盤となるSkiaライブラリ)はそのようなフックを提供していないため、自分でロールバックする必要があります。あなたがJPEG画像を話していると仮定すると、あなたの最善の策はC言語でlibjpegを直接使うことでしょう。
複雑な複雑さを考えると、2段階のサブサンプル - その後 - スケール変更を使用することは、おそらくイメージプレビュータイプのアプリケーションに最適です。
もしあなたがどうしても一段階のサイズ変更をしたいのなら、おそらくAndroid:largeHeap = trueならビットマップ全体をロードすることができますが、ご覧のとおりこれはお勧めできません。
ドキュメントから:Android:largeHeapアプリケーションのプロセスを大きなDalvikヒープで作成するかどうか。これは、アプリケーション用に作成されたすべてのプロセスに適用されます。プロセスにロードされた最初のアプリケーションにのみ適用されます。複数のアプリケーションがプロセスを使用できるようにするために共有ユーザーIDを使用している場合は、それらすべてがこのオプションを一貫して使用する必要があります。そうしないと、予期しない結果が生じます。ほとんどのアプリはこれを必要とせず、代わりにパフォーマンスを向上させるために全体的なメモリ使用量を減らすことに集中するべきです。これを有効にしても、利用可能なメモリの一定の増加を保証するわけではありません。デバイスによっては、利用可能なメモリの総容量によって制約を受けるためです。
これは私のために働きました。この関数は、SDカード上のファイルへのパスを取得し、表示可能な最大サイズでビットマップを返します。このコードはOfirのもので、sd上の画像ファイルのような変更がいくつかあります。代わりにRessourceを使用し、幅と高さはDisplay Objectから取得します。
private Bitmap makeBitmap(String path) {
try {
final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
//resource = getResources();
// Decode image size
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
int scale = 1;
while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) >
IMAGE_MAX_SIZE) {
scale++;
}
Log.d("TAG", "scale = " + scale + ", orig-width: " + options.outWidth + ", orig-height: " + options.outHeight);
Bitmap pic = null;
if (scale > 1) {
scale--;
// scale to max possible inSampleSize that still yields an image
// larger than target
options = new BitmapFactory.Options();
options.inSampleSize = scale;
pic = BitmapFactory.decodeFile(path, options);
// resize to desired dimensions
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.y;
int height = size.x;
//int height = imageView.getHeight();
//int width = imageView.getWidth();
Log.d("TAG", "1th scale operation dimenions - width: " + width + ", height: " + height);
double y = Math.sqrt(IMAGE_MAX_SIZE
/ (((double) width) / height));
double x = (y / height) * width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(pic, (int) x, (int) y, true);
pic.recycle();
pic = scaledBitmap;
System.gc();
} else {
pic = BitmapFactory.decodeFile(path);
}
Log.d("TAG", "bitmap size - width: " +pic.getWidth() + ", height: " + pic.getHeight());
return pic;
} catch (Exception e) {
Log.e("TAG", e.getMessage(),e);
return null;
}
}
私はInteger.numberOfLeadingZeros
を使って最良のサンプルサイズ、より良いパフォーマンスを計算します。
Kotlinのフルコード:
@Throws(IOException::class)
fun File.decodeBitmap(options: BitmapFactory.Options): Bitmap? {
return inputStream().use {
BitmapFactory.decodeStream(it, null, options)
}
}
@Throws(IOException::class)
fun File.decodeBitmapAtLeast(
@androidx.annotation.IntRange(from = 1) width: Int,
@androidx.annotation.IntRange(from = 1) height: Int
): Bitmap? {
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
decodeBitmap(options)
val ow = options.outWidth
val oh = options.outHeight
if (ow == -1 || oh == -1) return null
val w = ow / width
val h = oh / height
if (w > 1 && h > 1) {
val p = 31 - maxOf(Integer.numberOfLeadingZeros(w), Integer.numberOfLeadingZeros(h))
options.inSampleSize = 1 shl maxOf(0, p)
}
options.inJustDecodeBounds = false
return decodeBitmap(options)
}
これは私が使っているコードで、Android上でメモリ内の大きな画像をデコードするのに問題はありません。私の入力パラメータがおよそ1024x1024である限り、私は20MBより大きい画像をデコードすることができました。返されたビットマップを別のファイルに保存することができます。この方法の下に、画像を新しいビットマップに拡大縮小するためにも使用する別の方法があります。このコードを自由に使用してください。
/*****************************************************************************
* public decode - decode the image into a Bitmap
*
* @param xyDimension
* - The max XY Dimension before the image is scaled down - XY =
* 1080x1080 and Image = 2000x2000 image will be scaled down to a
* value equal or less then set value.
* @param bitmapConfig
* - Bitmap.Config Valid values = ( Bitmap.Config.ARGB_4444,
* Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888 )
*
* @return Bitmap - Image - a value of "null" if there is an issue decoding
* image dimension
*
* @throws FileNotFoundException
* - If the image has been removed while this operation is
* taking place
*/
public Bitmap decode( int xyDimension, Bitmap.Config bitmapConfig ) throws FileNotFoundException
{
// The Bitmap to return given a Uri to a file
Bitmap bitmap = null;
File file = null;
FileInputStream fis = null;
InputStream in = null;
// Try to decode the Uri
try
{
// Initialize scale to no real scaling factor
double scale = 1;
// Get FileInputStream to get a FileDescriptor
file = new File( this.imageUri.getPath() );
fis = new FileInputStream( file );
FileDescriptor fd = fis.getFD();
// Get a BitmapFactory Options object
BitmapFactory.Options o = new BitmapFactory.Options();
// Decode only the image size
o.inJustDecodeBounds = true;
o.inPreferredConfig = bitmapConfig;
// Decode to get Width & Height of image only
BitmapFactory.decodeFileDescriptor( fd, null, o );
BitmapFactory.decodeStream( null );
if( o.outHeight > xyDimension || o.outWidth > xyDimension )
{
// Change the scale if the image is larger then desired image
// max size
scale = Math.pow( 2, (int) Math.round( Math.log( xyDimension / (double) Math.max( o.outHeight, o.outWidth ) ) / Math.log( 0.5 ) ) );
}
// Decode with inSampleSize scale will either be 1 or calculated value
o.inJustDecodeBounds = false;
o.inSampleSize = (int) scale;
// Decode the Uri for real with the inSampleSize
in = new BufferedInputStream( fis );
bitmap = BitmapFactory.decodeStream( in, null, o );
}
catch( OutOfMemoryError e )
{
Log.e( DEBUG_TAG, "decode : OutOfMemoryError" );
e.printStackTrace();
}
catch( NullPointerException e )
{
Log.e( DEBUG_TAG, "decode : NullPointerException" );
e.printStackTrace();
}
catch( RuntimeException e )
{
Log.e( DEBUG_TAG, "decode : RuntimeException" );
e.printStackTrace();
}
catch( FileNotFoundException e )
{
Log.e( DEBUG_TAG, "decode : FileNotFoundException" );
e.printStackTrace();
}
catch( IOException e )
{
Log.e( DEBUG_TAG, "decode : IOException" );
e.printStackTrace();
}
// Save memory
file = null;
fis = null;
in = null;
return bitmap;
} // decode
注:createScaledBitmapが上記のdecodeメソッドを呼び出す以外は、メソッドは互いに関係ありません。メモの幅と高さは元の画像とは異なる場合があります。
/*****************************************************************************
* public createScaledBitmap - Creates a new bitmap, scaled from an existing
* bitmap.
*
* @param dstWidth
* - Scale the width to this dimension
* @param dstHeight
* - Scale the height to this dimension
* @param xyDimension
* - The max XY Dimension before the original image is scaled
* down - XY = 1080x1080 and Image = 2000x2000 image will be
* scaled down to a value equal or less then set value.
* @param bitmapConfig
* - Bitmap.Config Valid values = ( Bitmap.Config.ARGB_4444,
* Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888 )
*
* @return Bitmap - Image scaled - a value of "null" if there is an issue
*
*/
public Bitmap createScaledBitmap( int dstWidth, int dstHeight, int xyDimension, Bitmap.Config bitmapConfig )
{
Bitmap scaledBitmap = null;
try
{
Bitmap bitmap = this.decode( xyDimension, bitmapConfig );
// Create an empty Bitmap which will contain the new scaled bitmap
// This scaled bitmap should be the size we want to scale the
// original bitmap too
scaledBitmap = Bitmap.createBitmap( dstWidth, dstHeight, bitmapConfig );
float ratioX = dstWidth / (float) bitmap.getWidth();
float ratioY = dstHeight / (float) bitmap.getHeight();
float middleX = dstWidth / 2.0f;
float middleY = dstHeight / 2.0f;
// Used to for scaling the image
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale( ratioX, ratioY, middleX, middleY );
// Used to do the work of scaling
Canvas canvas = new Canvas( scaledBitmap );
canvas.setMatrix( scaleMatrix );
canvas.drawBitmap( bitmap, middleX - bitmap.getWidth() / 2, middleY - bitmap.getHeight() / 2, new Paint( Paint.FILTER_BITMAP_FLAG ) );
}
catch( IllegalArgumentException e )
{
Log.e( DEBUG_TAG, "createScaledBitmap : IllegalArgumentException" );
e.printStackTrace();
}
catch( NullPointerException e )
{
Log.e( DEBUG_TAG, "createScaledBitmap : NullPointerException" );
e.printStackTrace();
}
catch( FileNotFoundException e )
{
Log.e( DEBUG_TAG, "createScaledBitmap : FileNotFoundException" );
e.printStackTrace();
}
return scaledBitmap;
} // End createScaledBitmap
Bitmap yourBitmap;
Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);
または
resized = Bitmap.createScaledBitmap(yourBitmap,(int)(yourBitmap.getWidth()*0.8), (int)(yourBitmap.getHeight()*0.8), true);
この正確な問題に関する素晴らしい記事がAndroid開発者Webサイトにあります。 大きなビットマップを効率的にロードする