Como obter o Bitmap de um Uri?

209

Como obter um objeto Bitmap de um Uri (se eu conseguir armazená-lo /data/data/MYFOLDER/myimage.pngou file///data/data/MYFOLDER/myimage.png) para usá-lo no meu aplicativo?

Alguém tem uma idéia de como fazer isso?

ilredelweb
fonte
30
Você deve atualizar sua resposta aceita neste post, pois há respostas melhores que as minhas.
Vidar Vestnes
1
A segunda resposta é a correta, a terceira resposta é mais completa.
IgniteCoders
@VidarVestnes Por que você não o exclui?
Carlos López Marí

Respostas:

-35

. . IMPORTANTE: Consulte a resposta de @Mark Ingram abaixo e @pjv para obter uma solução melhor. . .

Você pode tentar o seguinte:

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;
}

Mas lembre-se, esse método só deve ser chamado de dentro de um thread (não da interface do usuário). Eu sou uma AsyncTask.

Vidar Vestnes
fonte
2
Que tal converter o URI em um URL, por exemplo, usando yourUri.toURL ()?
Vidar Vestnes
7
@VidarVestnes amigo, como o caminho do arquivo é convertido no URL?
Dharam
7
Eu não entendo como isso é a resposta selecionada
Nick Cardoso
11
Concordo que esta resposta não deve ser aceita como a melhor. Talvez tenha sido escolhido porque foi a primeira resposta. É um post antigo. Enfim, veja as respostas abaixo para obter melhores soluções.
Vidar Vestnes
8
@VidarVestnes acabou de excluir sua resposta
winklerrr 24/01
564

Aqui está a maneira correta de fazer isso:

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);
    }
}

Se você precisar carregar imagens muito grandes, o código a seguir será carregado em blocos (evitando grandes alocações de memória):

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

Veja a resposta aqui

Mark Ingram
fonte
3
Este código não lida com imagens maiores (basicamente qualquer tamanho de papel de parede). getBitmap () chama decodeStream () que falha com o erro OOM de stackoverflow.com/questions/2220949/handling-large-bitmaps . Algum outro conselho? MediaStore.Images.Thumbnails.getThumbnail () aparentemente não aceita um contentURI.
pjv
1
Veja a resposta aqui: stackoverflow.com/questions/4753013/…
Mark Ingram
@ MarkIngram Isso funciona com qualquer imagem local ou apenas com a imagem da câmera?
Narendra Singh
@ MarkIngram, e se não tivermos acesso a data.getData (), quero dizer, se eu simplesmente abrir alguma imagem da galeria e todos soubermos sobre o seu caminho, como posso obter uri e bitmap?
Umair
@Umair, você deve fazer uma nova pergunta em vez de perguntar nos comentários de uma resposta. A propósito: dê uma olhada aqui developer.android.com/reference/android/net/Uri.html
winklerrr
112

Aqui está a maneira correta de fazer isso, acompanhando também o uso da memória:

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;
}

A chamada getBitmap () da postagem de Mark Ingram também chama decodeStream (), para que você não perca nenhuma funcionalidade.

Referências:

pjv
fonte
1
Isso realmente me ajudou, embora eu acho que vale a pena mencionar que a palavra-chave this não pode ser usada dentro de um contexto estático. Eu passei para o método getThumbnail como argumento e funciona como um encanto.
MacKinley Smith 16/09
8
Qualquer um pode me dizer o valor que eu deveria dar a ThumbnailSize
Abid
2
Fechar e reabrir o InputStream é realmente necessário porque a primeira chamada BitmapFactory.decodeStream (...) define a posição de leitura do fluxo para o final, para que a segunda chamada do método não funcione mais sem reabrir o fluxo!
precisa saber é o seguinte
3
por favor, diga o valor de THUMBNAILSIZE
Mightian
3
Não é necessário calcular a proporção como uma potência de dois por conta própria, porque o próprio decodificador arredonda para o tamanho da amostra até a potência mais próxima de dois. Portanto, a chamada do método getPowerOfTwoForSampleRatio()pode ser ignorada. Veja: developer.android.com/reference/android/graphics/…
winklerrr 25/01
42
try
{
    Bitmap bitmap = MediaStore.Images.Media.getBitmap(c.getContentResolver() , Uri.parse(paths));
}
catch (Exception e) 
{
    //handle exception
}

e sim o caminho deve estar em um formato como este

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

DjP
fonte
1
graças Itay, isso é simples, se u tem o caminho u apenas tem que passar esse caminho e obter o Bitmap .. ele está trabalhando para mim, a esperança de u também tentar isso ..
DJP
2
@Dhananjay Obrigado, sua dica salva o meu dia e funciona para carregar o bitmap em miniatura do Provedor de Conteúdo.
Nezneika 29/10
2
Além disso, o Uri.parse () deve conter o formato URI, assim como: Uri.parse ("file: ///mnt/sdcard/filename.jpg") ; caso contrário, obteremos java.io.FileNotFoundException: No content fornecedor .
Nezneika 29/10
Alguma editorial seria legal, mas essa é uma boa resposta concisa à pergunta dos OPs que funciona na maioria dos casos. Essa é uma boa resposta para ter na página, com o objetivo de destilar o restante dessas outras respostas que respondem diretamente às perguntas dos OPs.
Umassthrower
1
@AndroidNewBee c é um objeto de Contexto.
DjP 27/09/16
17

Esta é a solução mais fácil:

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
Hasib Akter
fonte
16
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();
    }
}
DeltaCap019
fonte
3
funciona em todos os SDK .. Obrigado. é forma alternativa deBitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Jigar Patel
a resposta mais genuína todos SDK satisfeito
Noaman Akram
13

Parece que MediaStore.Images.Media.getBitmapfoi preterido em API 29. A maneira recomendada é usar o ImageDecoder.createSourceque foi adicionado API 28.

Aqui está como obter o bitmap:

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)
}
Ika
fonte
11

Você pode recuperar o bitmap da uri assim

Bitmap bitmap = null;
try {
    bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
} catch (IOException e) {
    e.printStackTrace();
}
Emre AYDIN
fonte
10
Uri imgUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imgUri);
Ahmed Sayed
fonte
2
Você poderia explicar como esse código funciona e como ele responde à pergunta?
Michael Dodd
2

Use o método startActivityForResult como abaixo

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

E você pode obter resultados como este:

@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;
    }
}
Faxriddin Abdullayev
fonte
2

Eu tentei de várias maneiras. este trabalho para mim perfeitamente.

Se você escolher pictrue na Galeria. Você precisa ser ware de obter Uria partir de intent.clipdataou intent.data, porque um deles pode ser nulo na versão diferente.

  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 )
}
Cyrus
fonte
1

você pode fazer esta estrutura:

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;
   }

com isso, você pode facilmente converter um uri em bitmap. espero ajudar você.

Sayed Mohammad Amin Emrani
fonte
1
Isso não está funcionando na versão do Android Nougat 7.1.1. Este extras.getParcelable ("data"); está retornando null
Developer_vaibhav
1

Inserção da getBitmapqual é privada agora eu uso a seguinte abordagem no Kotlin

PICK_IMAGE_REQUEST ->
    data?.data?.let {
        val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(it))
        imageView.setImageBitmap(bitmap)
    }
yaugenka
fonte
1
  InputStream imageStream = null;
    try {
        imageStream = getContext().getContentResolver().openInputStream(uri);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
Fawzi Nofal
fonte
1

(KOTLIN) Então, em 7 de abril de 2020, nenhuma das opções mencionadas acima funcionou, mas eis o que funcionou para mim:

  1. Se você deseja armazenar o bitmap em um val e definir um imageView com ele, use o seguinte:

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

  2. Se você deseja apenas definir o bitmap como e imageView, use o seguinte:

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

Advait Bansode
fonte
0

Método completo para obter uri de imagem da galeria para celular.

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();
      }


   }
}
Zzmilanzz Zzmadubashazz
fonte