ユーザーが写真を撮ることができるアプリケーションを入手しました。写真が撮られた後、ユーザーはそれを私のウェブサーバーに送信できます。ただし、これを行う前に、ビットマップのサイズを変更する必要があります。一貫したサイズを Web サーバーに送信したいからです。
とにかく、ビットマップをメモリにロードして操作するために使用するコードは、多くのメモリを占有しているようです。このコードは現在使用されています:
/*
* This method is used to calculate image size.
* And also resize/scale image down to 1600 x 1200
*/
private void ResizeBitmapAndSendToWebServer(string album_id) {
Bitmap bm = null;
// This line is taking up to much memory each time..
Bitmap bitmap = MediaStore.Images.Media.GetBitmap(Android.App.Application.Context.ApplicationContext.ContentResolver,fileUri);
/*
* My question is : Could i do the next image manipulation
* before i even load the bitmap into memory?
*/
int width = bitmap.Width;
int height = bitmap.Height;
if (width >= height) { // <-- Landscape picture
float scaledWidth = (float)height / width;
if (width > 1600) {
bm = Bitmap.CreateScaledBitmap (bitmap, 1600, (int)(1600 * scaledWidth), true);
} else {
bm = bitmap;
}
} else {
float scaledHeight = (float)width / height;
if (height > 1600) {
bm = Bitmap.CreateScaledBitmap (bitmap, (int)(1600 * scaledHeight), 1600 , true);
} else {
bm = bitmap;
}
}
// End of question code block.
MemoryStream stream = new MemoryStream ();
bitmap.Compress (Bitmap.CompressFormat.Jpeg, 80, stream);
byte[] bitmapData = stream.ToArray ();
bitmap.Dispose ();
app.api.SendPhoto (Base64.EncodeToString (bitmapData, Base64Flags.Default), album_id);
}
このようなメモリの問題を解決するための適切でクリーンな方法は何でしょうか?
編集1:
他の投稿を読んだ後、自分のコードで非効率的なことをしていることが明らかになりました。これは、段階的に、私が行ってきたことです:
- 完全なビットマップをメモリにロードします。
- 風景であるかどうかを決定します。
- 次に、正しい寸法で新しいビットマップを作成します。
- 次に、このビットマップをバイト配列に変換します
- 初期ビットマップの破棄。(ただし、スケーリングされたビットマップをメモリから削除しないでください)。
私が本当にすべきこと:
次のコマンドを使用して、メモリにロードせずに実際のビットマップの寸法を決定します。
private void FancyMethodForDeterminingImageDimensions() { BitmapFactory.Options options = new BitmapFactory.Options(); options.InJustDecodeBounds = true; BitmapFactory.DecodeFile(fileUri.Path, options); // Now the dimensions of the bitmap are known without loading // the bitmap into memory. // I am not further going to explain this, i think the purpose is // explaining enough. int outWidth = options.OutWidth; int outHeight = options.OutHeight; }
true に設定すると、デコーダーは null (ビットマップなし) を返しますが、out... フィールドは引き続き設定されるため、呼び出し元はピクセルにメモリを割り当てることなくビットマップをクエリできます。
- 今、私は本当の次元を知っています。そのため、メモリにロードする前にダウンサンプリングできます。
- (私の場合)ビットマップをbase64文字列に変換して送信します。
- メモリがクリアされるようにすべてを破棄します。
開発マシンにいないため、現在これをテストできません。これが正しい方法である場合、誰かが私にフィードバックを与えることができますか? それは高く評価されます。