Image Compression using Bitmap in Android Studio

In this article you can learn how to compress a image and you can set up your compressed image quality.this article we are using Bitmap Image Compression method.Now we are going to learn Image Compress using Bitmap.

Image Compression using Bitmap in Android Studio

1. Example App

Here is the demo app we are going to implement in this article.

Image Compression using Bitmap in Android Studio Image Compression using Bitmap in Android Studio

 

2. Creating New Project

1. Create a new project in Android Studio from File ⇒ New Project and select Basic Activity from templates.

2. Add STORAGE permission to your AndroidManifest.xml.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Your AndroidManifest.xml file look like this.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="andrious.com.imagecompressor">
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

3. Open the layout file of main activity activity_main.xml and add the below code.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp"
        android:layout_alignParentTop="true" >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="280dp"
            android:orientation="horizontal">
            <LinearLayout
                android:id="@+id/actual_layout"
                android:visibility="gone"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="vertical">
                <ImageView
                    android:id="@+id/actual_image"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:maxHeight="240dp"
                    android:adjustViewBounds="true"/>
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:text="Actual Image"/>
                <TextView
                    android:id="@+id/actual_size"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:text="Size : -"
                    android:textSize="12sp"/>
            </LinearLayout>
            <View
                android:id="@+id/view1"
                android:visibility="gone"
                android:layout_width="5dp"
                android:layout_height="60dp"/>
            <LinearLayout
                android:id="@+id/compresse_layout"
                android:visibility="gone"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="vertical">
                <ImageView
                    android:id="@+id/compressed_image"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:maxHeight="240dp"
                    android:layout_marginLeft="4dp"
                    android:layout_marginStart="4dp"
                    android:layout_weight="1"
                    android:adjustViewBounds="true"/>
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:text="Compressed Image"/>
                <TextView
                    android:id="@+id/compressed_size"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:text="Size : -"
                    android:textSize="12sp"/>
            </LinearLayout>
        </LinearLayout>
        <LinearLayout
            android:id="@+id/abc"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:orientation="horizontal">
            <Button
                android:id="@+id/choose_button"
                android:layout_width="0dp"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@drawable/border"
                android:text="Choose image"/>
            <View
                android:id="@+id/view2"
                android:visibility="gone"
                android:layout_width="5dp"
                android:layout_height="60dp"/>
            <Button
                android:id="@+id/compress_button"
                android:visibility="gone"
                android:layout_width="0dp"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@drawable/border"
                android:text="Compress image"/>
        </LinearLayout>
        <LinearLayout
            android:id="@+id/quality_layout"
            android:visibility="gone"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginTop="20dp"
            android:gravity="center"
            android:orientation="horizontal">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:text="Enter Quality : "
                android:gravity="center"/>
            <EditText
                android:id="@+id/quality_field"
                android:layout_width="70dp"
                android:layout_height="match_parent"
                android:inputType="number"
                android:maxLength="3"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:text="%"
                android:gravity="center"/>
            <ImageButton
                android:id="@+id/check"
                android:layout_width="60dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="30dp"
                android:src="@drawable/check"
                android:background="@android:color/holo_blue_dark"/>
        </LinearLayout>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="90dp"
        android:layout_alignParentBottom="true">
        <Button
            android:id="@+id/save_button"
            android:visibility="gone"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorPrimary"
            android:text="save"
            android:textColor="@android:color/background_light"
            android:textSize="30dp"/>
    </LinearLayout>
</RelativeLayout>

3. Create new Drawable Resource file  named border.xml and paste this code given bellow.

[ Right click on drawable => new =>Drawable resource file and then write file name as border ]

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners
        android:radius="1dp"/>
    <stroke
        android:width="1dp"
        android:color="#66000000" />
</shape>

4. Add image icon name check.

[ Right click on drawable => new  => Image Asset  =>  set icon type Action Bar and Tab Icon => set name check => click on Clip Art   => then write search box  check  press enter, you can find check icon then select and press ok ]

 

5. Open MainActivity.java and add the below code.

package andrious.com.imagecompressor;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.util.Log;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;

public class MainActivity extends AppCompatActivity{
    private static final int PICK_IMAGE_REQUEST = 1;
    private static final int REQUEST_WRITE_STORAGE = 112;
    public static final String MyPREFERENCES = "MyPrefs" ;
    public static final String IMG_SERIAL = "serial";
    SharedPreferences sharedpreferences;
    static ImageView actualImageView, compressedImageView;
    static TextView actualSizeTextView, compressedSizeTextView;
    static LinearLayout actual_layout,compresse_layout,quality_layout;
    static Button choose_button,compress_button,save_button;
    static ImageButton check;
    static EditText quality_field;
    static View view1,view2;
    static File actualImage;
    static Bitmap compressedImage;
    byte[] imageInByte;
    static int quality;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        actualImageView = findViewById(R.id.actual_image);
        compressedImageView = findViewById(R.id.compressed_image);
        actualSizeTextView = findViewById(R.id.actual_size);
        compressedSizeTextView = findViewById(R.id.compressed_size);
        actual_layout = findViewById(R.id.actual_layout);
        compresse_layout = findViewById(R.id.compresse_layout);
        quality_layout = findViewById(R.id.quality_layout);
        quality_field = findViewById(R.id.quality_field);
        check = findViewById(R.id.check);
        view1 = findViewById(R.id.view1);
        view2 = findViewById(R.id.view2);
        sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);

        choose_button = (Button) findViewById(R.id.choose_button);
        compress_button = findViewById(R.id.compress_button);
        save_button = findViewById(R.id.save_button);

        Boolean hasPermission = (ContextCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
        if (!hasPermission) {
            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    REQUEST_WRITE_STORAGE);
        }else {

            File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "Image Compressor");

            if (!mediaStorageDir.exists()) {
                if (!mediaStorageDir.mkdirs()) {
                    Log.d("=====", "failed to create directory");
                }
            }

        }

        choose_button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.setType("image/*");
                startActivityForResult(intent, PICK_IMAGE_REQUEST);
            }
        });

        compress_button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                quality_layout.setVisibility(View.VISIBLE);

            }
        });

        check.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String quality_data=quality_field.getText().toString();

                if(quality_data == null || quality_data.trim().equals("null") || quality_data.trim()
                        .length() <= 0){
                    Toast.makeText(getApplicationContext(), "Please insert quality", Toast.LENGTH_SHORT).show();
                }else{
                    quality = Integer.parseInt(quality_data);
                    if(quality> 0 && quality <=100 ){
                        compressImage();
                    }else{
                        Toast.makeText(getApplicationContext(), "Wrong input.try again !", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });

        save_button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                SaveFile(compressedImage);
                Log.d("======","image saved");
            }
        });

        clearImage();
    }


    public void compressImage() {
        if (actualImage == null) {
            showError("Please choose an image!");
        } else {

            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            compressedImage = BitmapFactory.decodeFile(actualImage.getAbsolutePath());
            compressedImage.compress(Bitmap.CompressFormat.JPEG, quality, stream);
            imageInByte = stream.toByteArray();

            setCompressedImage();

        }
    }

    private void setCompressedImage() {
        view1.setVisibility(View.VISIBLE);
        compresse_layout.setVisibility(View.VISIBLE);
        compressedImageView.setImageBitmap(compressedImage);
        compressedSizeTextView.setText(String.format("Size : %s",getReadableFileSize(imageInByte.length)));
        save_button.setVisibility(View.VISIBLE);

    }



    public String getReadableFileSize(long size) {
        if (size <= 0) {
            return "0";
        }
        final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }



    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK) {
            if (data == null) {
                showError("Failed to open picture!");
                return;
            }
            try {
                view1.setVisibility(View.GONE);
                compresse_layout.setVisibility(View.GONE);
                save_button.setVisibility(View.GONE);
                quality_layout.setVisibility(View.GONE);
                actual_layout.setVisibility(View.VISIBLE);
                view2.setVisibility(View.VISIBLE);
                compress_button.setVisibility(View.VISIBLE);
                actualImage = FileUtil.from(this, data.getData());
                actualImageView.setImageBitmap(BitmapFactory.decodeFile(actualImage.getAbsolutePath()));
                actualSizeTextView.setText(String.format("Size : %s", getReadableFileSize(actualImage.length())));
                clearImage();
            } catch (IOException e) {
                showError("Failed to read picture data!");
                e.printStackTrace();
            }
        }
    }


    private void SaveFile(Bitmap imageToSave) {

        File file = new File(new File("/sdcard/Image Compressor/"),"Comp_img_"+ sharedpreferences.getString(IMG_SERIAL,"1")+".jpg");

        try {
            FileOutputStream out = new FileOutputStream(file);
            imageToSave.compress(Bitmap.CompressFormat.JPEG, quality, out);
            out.flush();
            out.close();
            Toast.makeText(getApplicationContext(),"Saved",Toast.LENGTH_SHORT).show();
            SharedPreferences.Editor editor = sharedpreferences.edit();
            int abc = Integer.parseInt(sharedpreferences.getString(IMG_SERIAL,"1"));
            abc++;
            editor.putString(IMG_SERIAL,String.valueOf(abc));
            editor.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }





    private void clearImage() {
        compressedImageView.setImageDrawable(null);
        compressedSizeTextView.setText("Size : -");
    }



    public void showError(String errorMessage) {
        Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT).show();
    }







}

6. create FileUtil.java and add the below code.

package andrious.com.imagecompressor;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


class FileUtil {
    private static final int EOF = -1;
    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

    private FileUtil() {

    }

    public static File from(Context context, Uri uri) throws IOException {
        InputStream inputStream = context.getContentResolver().openInputStream(uri);
        String fileName = getFileName(context, uri);
        String[] splitName = splitFileName(fileName);
        File tempFile = File.createTempFile(splitName[0], splitName[1]);
        tempFile = rename(tempFile, fileName);
        tempFile.deleteOnExit();
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(tempFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (inputStream != null) {
            copy(inputStream, out);
            inputStream.close();
        }

        if (out != null) {
            out.close();
        }
        return tempFile;
    }

    private static String[] splitFileName(String fileName) {
        String name = fileName;
        String extension = "";
        int i = fileName.lastIndexOf(".");
        if (i != -1) {
            name = fileName.substring(0, i);
            extension = fileName.substring(i);
        }

        return new String[]{name, extension};
    }

    private static String getFileName(Context context, Uri uri) {
        String result = null;
        if (uri.getScheme().equals("content")) {
            Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
            try {
                if (cursor != null && cursor.moveToFirst()) {
                    result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
        if (result == null) {
            result = uri.getPath();
            int cut = result.lastIndexOf(File.separator);
            if (cut != -1) {
                result = result.substring(cut + 1);
            }
        }
        return result;
    }

    private static File rename(File file, String newName) {
        File newFile = new File(file.getParent(), newName);
        if (!newFile.equals(file)) {
            if (newFile.exists() && newFile.delete()) {
                Log.d("FileUtil", "Delete old " + newName + " file");
            }
            if (file.renameTo(newFile)) {
                Log.d("FileUtil", "Rename file to " + newName);
            }
        }
        return newFile;
    }

    private static long copy(InputStream input, OutputStream output) throws IOException {
        long count = 0;
        int n;
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        while (EOF != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
            count += n;
        }
        return count;
    }
}

run and enjoy this programme….

 

 

N.B.

1.Bitmap Compression method is like this.

ByteArrayOutputStream stream = new ByteArrayOutputStream();
compressedImage = BitmapFactory.decodeFile(actualImage.getAbsolutePath());
compressedImage.compress(Bitmap.CompressFormat.JPEG, 100, stream);

 

here you can use CompressFormat  like PNG , JPEG , WEBP   and set quality as you like.

 

2. I am also using a method to save the compressed image in storage.if you can save any thing in storage you need  storage  parmission  to the user .Add this code in onCreate() method  bellow the MainActivity.java class.

Boolean hasPermission = (ContextCompat.checkSelfPermission(MainActivity.this,
        Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermission) {
    ActivityCompat.requestPermissions(MainActivity.this,
            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
            REQUEST_WRITE_STORAGE);
}else {

    File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "Image Compressor");

    if (!mediaStorageDir.exists()) {
        if (!mediaStorageDir.mkdirs()) {
            Log.d("=====", "failed to create directory");
        }
    }
}

This code show a storage parmission dialog  when user first open this application.when user click the ok button then create a folder name Image Compressor. I am using this code in else condition.You can  use anywhere where you need.

private void SaveFile(Bitmap imageToSave) {

    File file = new File(new File("/sdcard/Image Compressor/"),"Image Name"+".jpg");

    try {
        FileOutputStream out = new FileOutputStream(file);
        imageToSave.compress(Bitmap.CompressFormat.JPEG, quality, out);
        out.flush();
        out.close();
        Toast.makeText(getApplicationContext(),"Saved",Toast.LENGTH_SHORT).show();
        
    } catch (Exception e) {
        e.printStackTrace();
    }
}

This method is used for save the compressed image in the created folder,

 

Leave a Reply