How to decrease the quality of an image in android?

2

I have a list of objects that have an array of images that are somewhat "heavy", at the beginning of the application I have a custom listView that presents an image (icone) of each object, I would like to decrease the quality of these images because when I will slip on the list it is possible to notice slowness, I would need to make a copy of an image of each object to decrease the quality and show in the listview.

How can I do this in java code?

    
asked by anonymous 06.01.2015 / 00:23

3 answers

7

This is very common. And, in addition to slowness, you can catch the famous exception OutOffMemory .

To avoid this, you can solve in two (simple) steps inside your adapter:

1) - Place all image uploads within a AsyncTask . This causes you to pull out of your main thread the job of loading heavy images and blocking the user experience. And, in addition, you can cancel the execution of this AsyncTask , for example, the user of a very fast scroll:

Add a AsyncTask within your ViewHolder:

...

private class ViewHolder{
    public ImageView image;
    public AsyncTask<Void, Void, Bitmap> asyncTask;
    ...
}

Within the getView() method of your adapter:

...

//Previnindo o recycle de view
if (holder.asyncTask != null) {
    holder.asyncTask.cancel(true);
    holder.asyncTask = null;
}

//Previnido que a imagem "pisque" caso de um scroll muito rápido;
holder.image.setImageResource(R.drawable.someDrawable);

final ImageView image = holder.image;

holder.asyncTask = new AsyncTask<Void, Void, Bitmap>() {
    @Override
    protected Bitmap doInBackground(Void... params) {
        //Aqui você faz as implementações a seguir
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        image.setImageBitmap(bitmap);       
    }
};
holder.asyncTask.execute();

2) Within your AsyncTask, you can use a property called inSampleSize , which does what decodes your image into a smaller resolution, as if it were a "sample" of your image. For example, an image of 2048x1536 using inSampleSize as 4 produces an image with approximately 512x384. This loaded image uses only 0.75MB of memory instead of 12MB of the original image size. You can use this property within BitmapFactory.Options :

//Dentro de sua AsyncTask criada
@Override
protected Bitmap doInBackground(Void... params) {
    try {
        BitmapFactory.Options options = new BitmapFactory.Options();
        /*Reduzindo a qualidade da imagem para preservar memoria. 
        * Aqui você pode testar a redução que melhor atende sua necessidade
        */
        options.inSampleSize = 2;

        return BitmapFactory.decodeStream(new FileInputStream(imagePath), null, options);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    return null;
}

Sources:

Loading Large Bitmaps Efficiently

Processing Bitmaps Off the UI Thread

    
06.01.2015 / 13:13
2

According to Google, it is advisable to perform the image processing, so that its application does not exceed the memory.

            // Obter as dimensões do componente na tela
            File file = new File(Caminho da sua imagem)
             int targetW = imageview.getWidth();
             int targetH = imageview.getHeight();


            // Obter as dimensões do bitmap
            BitmapFactory.Options bmOptions = new BitmapFactory.Options();

            bmOptions.inJustDecodeBounds = true;

            BitmapFactory.decodeFile(file.getAbsolutePath(), bmOptions);

            int photoW = bmOptions.outWidth;
            int photoH = bmOptions.outHeight;

            // Determinar o quanto é necessario diminuir a imagem
            int scaleFactor = 1;
            if ((targetW > 0) || (targetH > 0)) {
                scaleFactor = Math.min(photoW/targetW, photoH/targetH); 
            }

            // Decodifica o arquivo de imagem em um Bitmap dimensionando para preencher o
            // ImagemView
            bmOptions.inJustDecodeBounds = false;
            bmOptions.inSampleSize = scaleFactor;
            bmOptions.inPurgeable = true;

            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), bmOptions);



            imageview.setImageBitmap(bitmap);

In this way you create a bitmap of the exact size of the screen component. Source: link

    
06.01.2015 / 16:20
1

You can resize the Bitmap:

Bitmap yourBitmap;
Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);
// ou:
resized = Bitmap.createScaledBitmap(yourBitmap,(int)(yourBitmap.getWidth()*0.3), (int)(yourBitmap.getHeight()*0.3), true);

Source: link

    
06.01.2015 / 04:29