Uriからビットマップを取得する方法?


209

アプリケーションで使用するためにUriからBitmapオブジェクトを取得する方法(/data/data/MYFOLDER/myimage.pngまたはに保存した 場合file///data/data/MYFOLDER/myimage.png

誰かがこれを達成する方法についてのアイデアを持っていますか?


30
私の回答よりも良い回答があるため、この投稿で承認済みの回答を更新する必要があります。
Vidar Vestnes、2014

1
二答えが正しいものである、第三の答えは、より完全です。
IgniteCoders 2018年

@VidarVestnesどうしてそれを削除しないのですか?
CarlosLópezMarí19年

回答:


-35

。。 重要:より良い解決策については、下記の@Mark Ingramと@pjvからの回答を参照してください。 。。

あなたはこれを試すことができます:

public Bitmap loadBitmap(String url)
{
    Bitmap bm = null;
    InputStream is = null;
    BufferedInputStream bis = null;
    try 
    {
        URLConnection conn = new URL(url).openConnection();
        conn.connect();
        is = conn.getInputStream();
        bis = new BufferedInputStream(is, 8192);
        bm = BitmapFactory.decodeStream(bis);
    }
    catch (Exception e) 
    {
        e.printStackTrace();
    }
    finally {
        if (bis != null) 
        {
            try 
            {
                bis.close();
            }
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        }
        if (is != null) 
        {
            try 
            {
                is.close();
            }
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        }
    }
    return bm;
}

ただし、このメソッドはスレッド内からのみ呼び出す必要があります(GUIスレッドではありません)。私はAsyncTaskです。


2
たとえば、yourUri.toURL()を使用して、URIをURLに変換するのはどうですか?
Vidar Vestnes

7
@VidarVestnesバディ、URLでファイルパスを変換するにはどうすればよいですか?
dharam 2013年

7
これが選択された答えであるか分かりません
Nick Cardoso 14

11
私は同意します、この答えは最高のものとして受け入れられるべきではありません。多分それが最初の答えだったので選ばれました。その古い記事。とにかく、seはより良い解決策について以下に答えます。
Vidar Vestnes 2014

8
@VidarVestnesは回答を削除します
winklerrr 2017年

564

これを行う正しい方法は次のとおりです。

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK)
    {
        Uri imageUri = data.getData();
        Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
    }
}

非常に大きな画像を読み込む必要がある場合は、次のコードで画像をタイルに読み込みます(大量のメモリ割り当てを避けます)。

BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(myStream, false);  
Bitmap region = decoder.decodeRegion(new Rect(10, 10, 50, 50), null);

ここで答えを見てください


3
ただし、このコードは大きな画像(基本的には壁紙のサイズは何でも)を扱いません。getBitmap()がdecodeStream()を呼び出します。これは、stackoverflow.com /questions/2220949/handling-large-bitmapsからのOOMエラーで失敗します。他に何かアドバイスはありますか?MediaStore.Images.Thumbnails.getThumbnail()は明らかにcontentURIを取りません。
pjv

1
ここで答えを参照してください。stackoverflow.com/questions/4753013/...
マーク・イングラム

@MarkIngramこれはローカル画像でもカメラ画像でも機能しますか?
Narendra Singh

@MarkIngram data.getData()にアクセスできない場合、つまり、ギャラリーから画像を単に開いて、そのパスについてすべて知っている場合、URIとビットマップを取得するにはどうすればよいですか?
Umair 2016年

@Umairは、回答のコメントを求める代わりに、新しい質問をする必要があります。ちなみに、こちらをご覧くださいdeveloper.android.com/reference/android/net/Uri.html
winklerrr

111

これが正しい方法であり、メモリ使用量も監視します。

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
  super.onActivityResult(requestCode, resultCode, data);
  if (resultCode == RESULT_OK)
  {
    Uri imageUri = data.getData();
    Bitmap bitmap = getThumbnail(imageUri);
  }
}

public static Bitmap getThumbnail(Uri uri) throws FileNotFoundException, IOException{
  InputStream input = this.getContentResolver().openInputStream(uri);

  BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
  onlyBoundsOptions.inJustDecodeBounds = true;
  onlyBoundsOptions.inDither=true;//optional
  onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
  BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
  input.close();

  if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) {
    return null;
  }

  int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;

  double ratio = (originalSize > THUMBNAIL_SIZE) ? (originalSize / THUMBNAIL_SIZE) : 1.0;

  BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
  bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
  bitmapOptions.inDither = true; //optional
  bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//
  input = this.getContentResolver().openInputStream(uri);
  Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
  input.close();
  return bitmap;
}

private static int getPowerOfTwoForSampleRatio(double ratio){
  int k = Integer.highestOneBit((int)Math.floor(ratio));
  if(k==0) return 1;
  else return k;
}

Mark Ingramの投稿からgetBitmap()を呼び出すと、decodeStream()も呼び出されるため、機能が失われることはありません。

参照:


1
これは本当に役に立ちましたが、thisキーワードは静的コンテキスト内からは使用できないことを言及する価値があると思います。引数としてgetThumbnailメソッドに渡しましたが、これは魅力のように機能します。
MacKinley Smith 2013

8
いずれかは、私がTHUMBNAILSIZEに与えるべき値を教えてもらえます
ABID

2
最初のBitmapFactory.decodeStream(...)呼び出しがストリームの読み取り位置を最後に設定するため、InputStreamを閉じて再度開くことが実際に必要です。そのため、メソッドの2番目の呼び出しは、ストリームを再度開くまで機能しません。
DominicM 2015年

3
THUMBNAILSIZEの値を教えてください
Mightian

3
デコーダ自体がサンプルサイズを最も近い2の累乗に切り捨てるため、比率を2の累乗として自分で計算する必要はありません。したがって、メソッド呼び出しgetPowerOfTwoForSampleRatio()はスキップできます。参照:developer.android.com/reference/android/graphics/...
winklerrr

42
try
{
    Bitmap bitmap = MediaStore.Images.Media.getBitmap(c.getContentResolver() , Uri.parse(paths));
}
catch (Exception e) 
{
    //handle exception
}

はい、パスはこのような形式でなければなりません

file:///mnt/sdcard/filename.jpg


1
uはuはちょうどそのパスを渡すと、ビットマップを取得する必要がありますパスを持っている場合...それは私のために働いているおかげでイタイ、これはシンプルで、Uへの希望もこの..試す
DJP

2
@Dhananjayありがとう、あなたのヒントは私の一日を救い、コンテンツプロバイダーからサムネイルビットマップをロードする働きをします。
Nezneika 2013年

2
さらに、Uri.parse()には、次のようにURI形式を含める必要があります。Uri.parse( "file:///mnt/sdcard/filename.jpg")、そうでない場合、java.io.FileNotFoundException:コンテンツなしプロバイダー
Nezneika 2013年

いくつかの編集は良いですが、これはほとんどの場合に機能するOPの質問に対する良い簡潔な回答です。これは、OPの質問に直接回答するこれらの他の回答の一部を抽出するために、ページに表示するのに適した回答です。
umassthrower、2014

1
@AndroidNewBee cはContextオブジェクトです。
DjP 2016


15
private void uriToBitmap(Uri selectedFileUri) {
    try {
        ParcelFileDescriptor parcelFileDescriptor =
                getContentResolver().openFileDescriptor(selectedFileUri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);

        parcelFileDescriptor.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3
すべてのSDKで動作します。ありがとうございます。それは別の方法ですBitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Jigar Patel 2017

すべてのSDKが満足する最も純粋な答え
Noaman Akram

13

MediaStore.Images.Media.getBitmap廃止されたようAPI 29です。推奨される方法は、ImageDecoder.createSourceで追加されたを使用することAPI 28です。

ビットマップを取得する方法は次のとおりです。

val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    ImageDecoder.decodeBitmap(ImageDecoder.createSource(requireContext().contentResolver, imageUri))
} else {
    MediaStore.Images.Media.getBitmap(requireContext().contentResolver, imageUri)
}

11

このようにしてuriからビットマップを取得できます

Bitmap bitmap = null;
try {
    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
} catch (IOException e) {
    e.printStackTrace();
}

10
Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);

2
このコードがどのように機能し、どのように質問に答えるかについて詳しく説明していただけませんか?
マイケルドッド

2

以下のようにstartActivityForResultメソッドを使用します

        startActivityForResult(new Intent(Intent.ACTION_PICK).setType("image/*"), PICK_IMAGE);

そして、あなたはこのような結果を得ることができます:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode != RESULT_OK) {
        return;
    }
    switch (requestCode) {
        case PICK_IMAGE:
            Uri imageUri = data.getData();
            try {
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
            } catch (IOException e) {
                e.printStackTrace();
            }
         break;
    }
}

2

私は多くの方法を試してみました。この作品は私にとって完璧です。

ギャラリーからpictrueを選択した場合。またはUriからの取得に注意する必要があります。バージョンによってはnullになる可能性があるためです。intent.clipdataintent.data

  private fun onChoosePicture(data: Intent?):Bitmap {
        data?.let {
            var fileUri:Uri? = null

              data.clipData?.let {clip->
                  if(clip.itemCount>0){
                      fileUri = clip.getItemAt(0).uri
                  }
              }
            it.data?.let {uri->
                fileUri = uri
            }


               return MediaStore.Images.Media.getBitmap(this.contentResolver, fileUri )
}

1

あなたはこの構造を行うことができます:

protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
    switch(requestCode) {
        case 0:
            if(resultCode == RESULT_OK){
                    Uri selectedImage = imageReturnedIntent.getData();
                    Bundle extras = imageReturnedIntent.getExtras();
                    bitmap = extras.getParcelable("data");
            }
            break;
   }

これにより、URIをビットマップに簡単に変換できます。助けてほしい


1
これは、android nougat 7.1.1バージョンでは機能しません。このextras.getParcelable( "data"); がnullを返す
Developer_vaibhav

1

インセットはgetBitmap現在低価格ですが、Kotlinで次のアプローチを使用しています

PICK_IMAGE_REQUEST ->
    data?.data?.let {
        val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(it))
        imageView.setImageBitmap(bitmap)
    }

1
  InputStream imageStream = null;
    try {
        imageStream = getContext().getContentResolver().openInputStream(uri);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);

0

モバイルギャラリーから画像URIを取得するための完全なメソッド。

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

  if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
                Uri filePath = data.getData();

     try { //Getting the Bitmap from Gallery
           Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
           rbitmap = getResizedBitmap(bitmap, 250);//Setting the Bitmap to ImageView
           serImage = getStringImage(rbitmap);
           imageViewUserImage.setImageBitmap(rbitmap);
      } catch (IOException e) {
           e.printStackTrace();
      }


   }
}

0

(KOTLIN)したがって、2020年4月7日の時点では、上記のオプションはどれも機能していませんでしたが、次のように機能しました。

  1. ビットマップをvalに保存し、それにimageViewを設定する場合は、次のようにします。

    val bitmap = BitmapFactory.decodeFile(currentPhotoPath).also { bitmap -> imageView.setImageBitmap(bitmap) }

  2. ビットマップをimageViewに設定するだけの場合は、これを使用します。

    BitmapFactory.decodeFile(currentPhotoPath).also { bitmap -> imageView.setImageBitmap(bitmap) }

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.