How to compress an image file in Android

Our first blog post on How to create an Android app for image compression, resizing, and filtering from scratch focuses on the scope and content of the Android project.

In this tutorial, we will learn how to compress an image in Android without losing quality. 

If you need to compress an image file in Android, this tutorial is for you.

There are different compression options available with image compression in Android.

 Using BitmapFactory.Options

BitmapFactory.Options is a class that provides several options for manipulating images. One of these options is the “inSampleSize” property, which can reduce the image’s resolution and its size. You can use this property to compress the image while decoding it. 

Below is a simple code example in Android.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2; // Set the inSampleSize value as per your requirement
Bitmap compressedBitmap = BitmapFactory.decodeFile(filePath, options);

Bitmap.compress Method

The Bitmap class in Android provides a `compress()` method which can be used to compress an image. This method allows you to specify the image format (e.g., JPEG, PNG), the quality, and an output stream to write the compressed image to.

Below is a simple code example in Android.

Bitmap bitmap = BitmapFactory.decodeFile(filePath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
byte[] imageData = baos.toByteArray();

Using third-party libraries

There are several third-party libraries available that offer more advanced image compression techniques. These libraries often provide options to control the compression level, image dimensions, and quality. Some popular libraries include Glide, Picasso, and Compressor. You can use these libraries in your project using Gradle and follow their documentation to compress images.

  • implementation ‘com.github.bumptech.glide:glide:4.11.0’
  • implementation ‘com.squareup.picasso:picasso:2.5.2’
  • implementation ‘id.zelory:compressor:3.0.0’

The method you choose depends on your specific requirements and preferences.

Since we are working on different image manipulation options in Android, we will use the compressor third-party library. There is no need to reinvent the wheel. 

Image Compression UI

Below is the user interface for image compression in Andriod. 

  1. Select the Compress item on the list 
  2. Click the image picker button to select an image.
  3. Choose an image compression option and click the save button. 

Create Android Project

I will not cover how to create a new Android Project in Android Studio. There are lots of tutorials out there that have already covered it.

This is a Java Android project. You can convert it to Kotlin if you prefer Kotlin over Java.

I will use the details below in this project. Feel free to choose a name of your choice.

App Name: Image Compress & Resize

Package Name: com.istoby

Language: Java

Now that we have created a new Android Project, let’s see what we will develop. I have added some screenshots below.

Android Image Tool List Page

First, we will create a list of image tools in this project using a Recyclerview.

  1. Create a new Activity Page and use any name of your choice.
  2. Add a Recycleview in the layout file of the Activity page.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/bg_color"
    android:layout_margin="8dp"
    tools:context=".home.ui.tools.PhotoToolFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/image_tool_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:scrollbars="none"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Open the Activity page and add the below code.

public class PhotoToolFragment extends Fragment {

    private static final String TAG = PhotoToolFragment.class.getSimpleName();

    private FragmentPhotoToolBinding binding;

    private RecyclerView imageToolList;

    private SmartRecyclerAdapter smartRecyclerAdapter;

    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        binding = FragmentPhotoToolBinding.inflate(inflater, container, false);
        View root = binding.getRoot();

        imageToolList = binding.imageToolList;

        List<ImageToolModel> data = DataUtils.fetchImageToolOptions();
        setUpImageTools(data);

        return root;
    }

    private void setUpImageTools(List<ImageToolModel> data){
        smartRecyclerAdapter = SmartRecyclerAdapter
                .items(data)
                .map(ImageToolModel.class, ImageToolViewHolder.class)
                .setLayoutManager(new GridLayoutManager(requireActivity(), 2))
                .addViewEventListener((OnImageToolItemClickListener) (view, actionId, position) -> {

                    ImageToolModel model = (ImageToolModel) data.get(position);
                    Type type = new TypeToken<ImageToolModel>(){}.getType();
                    String param = new Gson().toJson(model, type);
                    String optionName = model.getToolName();

                    viewImageOption(optionName);

                })
                .into(imageToolList);
    }

    private void viewImageOption(String param){
        Intent imageToolIntent = null;

        if(param.equals("Resize")){
            imageToolIntent = new Intent(requireActivity(), ResizeImageActivity.class);
        }
        if (param.equals("Compress")) {
            imageToolIntent = new Intent(requireActivity(), CompressImageActivity.class);
        }
        if (param.equals("Crop")) {
            imageToolIntent = new Intent(requireActivity(), CropImageActivity.class);
        }
        if (param.equals("Convert")) {
            imageToolIntent = new Intent(requireActivity(), ConvertImageActivity.class);
        }
        if (param.equals("Filter")) {
            imageToolIntent = new Intent(requireActivity(), FilterImageActivity.class);
        }
        if (param.equals("Base64 Encode")) {
            imageToolIntent = new Intent(requireActivity(), CipherImageActivity.class);
        }
        if (param.equals("Draw")) {
            imageToolIntent = new Intent(requireActivity(), DrawImageActivity.class);
        }
        if (param.equals("Image Background")) {
            imageToolIntent = new Intent(requireActivity(), BackgroundImageActivity.class);
        }
        if (param.equals("Compare Images")) {
            imageToolIntent = new Intent(requireActivity(), CompareImageActivity.class);
        }
        if (param.equals("Pixelate")) {
            imageToolIntent = new Intent(requireActivity(), PixelateImageActivity.class);
        }
        if (param.equals("Sketch")) {
            imageToolIntent = new Intent(requireActivity(), SketchImageActivity.class);
        }
        if (param.equals("Image To Ascii")) {
            imageToolIntent = new Intent(requireActivity(), AsciiImageActivity.class);
        }
        if (param.equals("Combine Images")) {
            imageToolIntent = new Intent(requireActivity(), CombineImagesActivity.class);
        }
        if (param.equals("Load Image Online")) {
            imageToolIntent = new Intent(requireActivity(), LoadImageOnlineActivity.class);
        }
        if (param.equals("Zoom")) {
            imageToolIntent = new Intent(requireActivity(), ZoomImageActivity.class);
        }
        if (param.equals("Grid Image")) {
            imageToolIntent = new Intent(requireActivity(), GridImageActivity.class);
        }
        if (param.equals("Erase Background")) {
            imageToolIntent = new Intent(requireActivity(), EraseBackgroundActivity.class);
        }
        if (param.equals("Image Watermark")) {
            imageToolIntent = new Intent(requireActivity(), WatermarkImageActivity.class);
        }
        if (param.equals("Image To Text")) {
            imageToolIntent = new Intent(requireActivity(), ImageToTextActivity.class);
        }
        if (param.equals("Image To PDF")) {
            imageToolIntent = new Intent(requireActivity(), ImageToPDFActivity.class);
        }

        if(imageToolIntent != null){
            imageToolIntent.putExtra(ConstantUtils.IMAGE_TOOL_ITEM, param);
            startActivity(imageToolIntent);
            Bungee.slideLeft(requireActivity());
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}

From the code below, we obtained an instant of the Recyclerview.

Add the SmartRecyclerAdapter library in your project build.gradle page.

The SmartRecyclerAdapter library connects the Recycleview with the data source.

Create a Model class and a ViewHolder class, then add this code to them.

ImageToolModel Class

public class ImageToolModel {

    private static final String TAG = ImageToolModel.class.getSimpleName();

    private int toolIcon;

    private String toolName;

    public ImageToolModel(int toolIcon, String toolName) {
        this.toolIcon = toolIcon;
        this.toolName = toolName;
    }

    public int getToolIcon() {
        return toolIcon;
    }

    public void setToolIcon(int toolIcon) {
        this.toolIcon = toolIcon;
    }

    public String getToolName() {
        return toolName;
    }

    public void setToolName(String toolName) {
        this.toolName = toolName;
    }
}

ImageToolViewHolder Class

public class ImageToolViewHolder extends SmartViewHolder<ImageToolModel> {

    private static final String TAG = ImageToolViewHolder.class.getSimpleName();

    private AppCompatImageView toolIcon;

    private AppCompatTextView toolName;

    public ImageToolViewHolder(ViewGroup parentView) {
        super(LayoutInflater.from(parentView.getContext()).inflate(R.layout.image_tool_item_layout, parentView, false));

        toolIcon = (AppCompatImageView) itemView.findViewById(R.id.image_tool_icon);
        toolName = (AppCompatTextView) itemView.findViewById(R.id.image_tool_name);
    }

    @Override
    public void bind(ImageToolModel item) {
        toolIcon.setImageResource(item.getToolIcon());
        toolName.setText(item.getToolName());
    }

}

Compile and install the code to your device. If there is no error, you will see a screenshot like below.

List Item Click Listener Event

Create an Interface class and use a name of your choice. 

Add the code below to this page.

public interface OnImageToolItemClickListener extends OnItemClickListener {

    @NonNull
    @Override
    default Class<? extends SmartViewHolder> getViewHolderType() {
        return ImageToolViewHolder.class;
    }
}

Go to the SmartRecyclerviewAdapter and add it as a click listener callback.

Add an Intent that navigates to the ImageCompressActivity page.

Image Compression Activity XML Layout File

Open this layout file, copy and paste the code to the file.

This layout file does not need any explanation apart from the toggle button. Add this line to build.gradle to make it work.

implementation 'nl.bryanderidder:themed-toggle-button-group:1.4.1'

Layout Code

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/lighter"
    tools:context=".home.ui.tools.featuresUI.CompressImageActivity">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/adview_wrapper"
        android:scrollbars="none">

        <androidx.appcompat.widget.LinearLayoutCompat
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <androidx.cardview.widget.CardView
                android:id="@+id/image_card"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:cardElevation="4dp"
                app:cardUseCompatPadding="true"
                app:cardCornerRadius="16dp">

                <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="220dp"
                    android:orientation="vertical">

                    <androidx.appcompat.widget.AppCompatImageView
                        android:id="@+id/selected_image"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:scaleType="centerCrop"/>

                    <androidx.appcompat.widget.AppCompatTextView
                        android:id="@+id/click_to_upload_image"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="CLICK TO UPLOAD IMAGE"
                        android:textStyle="bold"
                        android:textSize="16sp"
                        android:padding="16dp"/>

                </FrameLayout>

            </androidx.cardview.widget.CardView>

            <androidx.appcompat.widget.LinearLayoutCompat
                android:id="@+id/feature_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <androidx.cardview.widget.CardView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:cardUseCompatPadding="true"
                    app:cardCornerRadius="8dp"
                    android:layout_marginEnd="4dp"
                    android:layout_marginStart="4dp"
                    android:elevation="2dp"
                    android:layout_marginTop="8dp">

                    <androidx.appcompat.widget.LinearLayoutCompat
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:padding="12dp"
                        android:orientation="vertical">

                        <androidx.appcompat.widget.LinearLayoutCompat
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:orientation="horizontal">

                            <androidx.appcompat.widget.AppCompatTextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="Filename: "
                                android:textStyle="bold"
                                android:layout_marginEnd="12dp"
                                android:textColor="@color/black"
                                android:textSize="15sp"/>

                            <androidx.appcompat.widget.AppCompatTextView
                                android:id="@+id/selected_image_name"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="A"
                                android:textSize="15sp"
                                android:layout_marginBottom="12dp"
                                android:textColor="@color/black"/>

                        </androidx.appcompat.widget.LinearLayoutCompat>

                        <androidx.appcompat.widget.LinearLayoutCompat
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:orientation="horizontal">

                            <androidx.appcompat.widget.AppCompatTextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="File Size: "
                                android:textStyle="bold"
                                android:layout_marginEnd="12dp"
                                android:textColor="@color/black"
                                android:textSize="15sp"/>

                            <androidx.appcompat.widget.AppCompatTextView
                                android:id="@+id/selected_image_size"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text=""
                                android:textSize="15sp"
                                android:textColor="@color/black"/>

                        </androidx.appcompat.widget.LinearLayoutCompat>


                    </androidx.appcompat.widget.LinearLayoutCompat>

                </androidx.cardview.widget.CardView>

                <androidx.cardview.widget.CardView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:cardUseCompatPadding="true"
                    app:cardCornerRadius="8dp"
                    android:layout_marginEnd="4dp"
                    android:layout_marginStart="4dp"
                    android:elevation="2dp"
                    android:layout_marginTop="8dp">

                    <androidx.appcompat.widget.LinearLayoutCompat
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:padding="12dp"
                        android:orientation="vertical">

                        <androidx.appcompat.widget.AppCompatTextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="Image Format"
                            android:textStyle="bold"
                            android:textSize="15sp"
                            android:layout_marginBottom="18dp"
                            android:textColor="@color/black"/>

                        <nl.bryanderidder.themedtogglebuttongroup.ThemedToggleButtonGroup
                            android:id="@+id/file_format_options"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            app:justifyContent="center">

                            <nl.bryanderidder.themedtogglebuttongroup.ThemedButton
                                android:id="@+id/image_png"
                                android:layout_width="wrap_content"
                                android:layout_height="38dp"
                                app:toggle_selectedBackgroundColor="@color/my_accent"
                                app:toggle_selectedTextColor="@android:color/black"
                                app:toggle_text="PNG" />

                            <nl.bryanderidder.themedtogglebuttongroup.ThemedButton
                                android:id="@+id/image_jpg"
                                android:layout_width="wrap_content"
                                android:layout_height="38dp"
                                app:toggle_selectedBackgroundColor="@color/my_accent"
                                app:toggle_selectedTextColor="@android:color/black"
                                app:toggle_text="JPG" />

                            <nl.bryanderidder.themedtogglebuttongroup.ThemedButton
                                android:id="@+id/image_webp"
                                android:layout_width="wrap_content"
                                android:layout_height="38dp"
                                app:toggle_selectedBackgroundColor="@color/my_accent"
                                app:toggle_selectedTextColor="@android:color/black"
                                app:toggle_text="WEBP" />

                            <nl.bryanderidder.themedtogglebuttongroup.ThemedButton
                                android:id="@+id/image_bmp"
                                android:layout_width="wrap_content"
                                android:layout_height="38dp"
                                app:toggle_selectedBackgroundColor="@color/my_accent"
                                app:toggle_selectedTextColor="@android:color/black"
                                app:toggle_text="BMP" />

                        </nl.bryanderidder.themedtogglebuttongroup.ThemedToggleButtonGroup>

                    </androidx.appcompat.widget.LinearLayoutCompat>

                </androidx.cardview.widget.CardView>

                <androidx.cardview.widget.CardView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:cardUseCompatPadding="true"
                    app:cardCornerRadius="8dp"
                    android:layout_marginEnd="4dp"
                    android:layout_marginStart="4dp"
                    android:elevation="2dp"
                    android:layout_marginTop="8dp">

                    <androidx.appcompat.widget.LinearLayoutCompat
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                        android:padding="12dp">

                        <androidx.appcompat.widget.AppCompatTextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_marginBottom="18dp"
                            android:text="Compress Options"
                            android:textColor="@color/black"
                            android:textSize="15sp"
                            android:textStyle="bold" />

                        <RadioGroup
                            android:id="@+id/compression_group"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:orientation="vertical">

                            <androidx.appcompat.widget.AppCompatRadioButton
                                android:id="@+id/without_compression"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="Without Compression"
                                android:textColor="@color/black" />

                            <androidx.appcompat.widget.AppCompatRadioButton
                                android:id="@+id/auto_compression"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="Auto Compression"
                                android:textColor="@color/black" />

                            <androidx.appcompat.widget.AppCompatRadioButton
                                android:id="@+id/length_compression"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="Compression by Length"
                                android:textColor="@color/black" />

                            <androidx.appcompat.widget.AppCompatRadioButton
                                android:id="@+id/size_compression"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="Compression by Length"
                                android:textColor="@color/black" />

                        </RadioGroup>


                        <androidx.appcompat.widget.AppCompatEditText
                            android:id="@+id/image_length_value"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginTop="6dp"
                            android:background="@drawable/border_corner"
                            android:hint="Image length"
                            android:inputType="number"
                            android:padding="12dp"
                            android:visibility="gone" />

                        <androidx.appcompat.widget.AppCompatEditText
                            android:id="@+id/image_size_value"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginTop="6dp"
                            android:background="@drawable/border_corner"
                            android:hint="Image Size (KB)"
                            android:inputType="number"
                            android:padding="12dp"
                            android:visibility="gone" />

                    </androidx.appcompat.widget.LinearLayoutCompat>

                </androidx.cardview.widget.CardView>

            </androidx.appcompat.widget.LinearLayoutCompat>

        </androidx.appcompat.widget.LinearLayoutCompat>

    </ScrollView>


    <androidx.appcompat.widget.LinearLayoutCompat
        android:id="@+id/adview_wrapper"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#fafafa"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:orientation="vertical">

        <androidx.appcompat.widget.LinearLayoutCompat
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:orientation="vertical">

        </androidx.appcompat.widget.LinearLayoutCompat>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:padding="12dp">

            <androidx.appcompat.widget.LinearLayoutCompat
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="12dp"
                android:layout_alignParentEnd="true"
                android:orientation="horizontal">

                <androidx.appcompat.widget.AppCompatImageView
                    android:id="@+id/open_image_btn"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:scaleType="centerCrop"
                    android:layout_marginEnd="21dp"
                    android:elevation="4dp"
                    android:src="@drawable/imageadd"/>

                <androidx.appcompat.widget.AppCompatImageView
                    android:id="@+id/save_image_btn"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:scaleType="centerCrop"
                    android:elevation="4dp"
                    android:src="@drawable/imagesave"/>

            </androidx.appcompat.widget.LinearLayoutCompat>


        </RelativeLayout>

    </androidx.appcompat.widget.LinearLayoutCompat>

</androidx.constraintlayout.widget.ConstraintLayout>

Image Compression Activity Java Page

Open the Java page and get instances of the View components in the XML layout file.

The image file picker uses a library. Add the line below to your project build.gradle file.

implementation 'com.github.dhaval2404:imagepicker:2.1'

Copy and paste the code to the activity page.

public class CompressImageActivity extends AppCompatActivity {

    private static final String TAG = CompressImageActivity.class.getSimpleName();

    private ActivityCompressImageBinding binding;
    private AppCompatTextView openImageDialog;
    private AppCompatImageView selectedImageView;
    private LinearLayoutCompat featureContainer;

    private ThemedToggleButtonGroup themeGroup;

    private AppCompatTextView selectedImageName, selectedImageSize;

    private RadioGroup compressionGroup;

    private AppCompatImageView saveImageBtn, openImageBtn;

    private AppCompatEditText imageLengthValue, imageSizeValue;

    private FileUtility fileUtility;

    private int compressionStatus = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityCompressImageBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        setTitle("Compress Image");

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);

        selectedImageView = binding.selectedImage;

        featureContainer = binding.featureContainer;
        featureContainer.setVisibility(View.GONE);

        selectedImageName = binding.selectedImageName;
        selectedImageSize = binding.selectedImageSize;

        imageLengthValue = binding.imageLengthValue;
        imageSizeValue = binding.imageSizeValue;

        themeGroup = binding.fileFormatOptions;

        openImageDialog = binding.clickToUploadImage;
        openImageDialog.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                openGallery();
            }
        });

        openImageBtn = binding.openImageBtn;
        openImageBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                openGallery();
            }
        });

        compressionGroup = binding.compressionGroup;
        compressionGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int checkedViewId) {

                imageLengthValue.setVisibility(View.GONE);
                imageSizeValue.setVisibility(View.GONE);

                if(checkedViewId == R.id.without_compression){
                    compressionStatus = 1;
                }
                if(checkedViewId == R.id.auto_compression){
                    compressionStatus = 2;
                }
                if(checkedViewId == R.id.length_compression){
                    imageLengthValue.setVisibility(View.VISIBLE);
                    compressionStatus = 3;
                }
                if (checkedViewId == R.id.size_compression) {
                    imageSizeValue.setVisibility(View.VISIBLE);
                    compressionStatus = 4;
                }

            }
        });

        saveImageBtn = binding.saveImageBtn;
        saveImageBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (compressionStatus == 0) {
                    Toast.makeText(CompressImageActivity.this, "Please select compression option", Toast.LENGTH_SHORT).show();
                    return;
                }
                if(compressionStatus == 1){
                    noCompression();
                }
                if(compressionStatus == 2){
                    autoCompression();
                }
                if(compressionStatus == 3){
                    String lengthValue = imageLengthValue.getText().toString();
                    if(lengthValue.isEmpty()){
                        Toast.makeText(CompressImageActivity.this, "Please enter image length", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    int lengthVal = Integer.parseInt(lengthValue);
                    lengthCompression(lengthVal);
                }
                if (compressionStatus == 4) {
                    String sizeValue = imageSizeValue.getText().toString();
                    if(sizeValue.isEmpty()){
                        Toast.makeText(CompressImageActivity.this, "Please enter image size", Toast.LENGTH_SHORT).show();
                        return;
                    }

                    int sizeVal = Integer.parseInt(sizeValue);
                    File file = fileUtility.getUploadedFile();
                    compressBySize(sizeVal, file);
                }
            }
        });
    }

    private String selectedImageExtension(){
        String selectedExtension = "";
        List<ThemedButton> buttons = themeGroup.getButtons();
        for (ThemedButton button : buttons) {
            if (button.isSelected()) {
                selectedExtension = button.getSelectedText();
                selectedExtension = selectedExtension.toLowerCase();
            }
        }
        return selectedExtension;
    }

    private void noCompression(){
        // isConvertedSupported
        String userSelectedExt = selectedImageExtension();

        //No conversion
        StorageUtil storageUtil = new StorageUtil(this);
        String resizePath = storageUtil.createInnerFolderStorage("Resize");

        ResizeImageHelper helper = new ResizeImageHelper(this);
        File reFile = helper.saveImageWithoutCompress(userSelectedExt, fileUtility.getFilenameWithoutExtension(), resizePath, fileUtility.getUploadedFile());

        this.showCompressedResult(reFile);
    }

    private void autoCompression(){
        // isConvertedSupported
        String userSelectedExt = selectedImageExtension();

        //No conversion
        StorageUtil storageUtil = new StorageUtil(this);
        String resizePath = storageUtil.createInnerFolderStorage("Resize");
        int progressValue = 80;

        ResizeImageHelper helper = new ResizeImageHelper(this);
        File reFile = helper.resizeImageQuality(progressValue, userSelectedExt, fileUtility.getFilenameWithoutExtension(), resizePath, fileUtility.getUploadedFile());

        this.showCompressedResult(reFile);
    }

    private void lengthCompression(int length){
        String userSelectedExt = selectedImageExtension();

        //No conversion
        StorageUtil storageUtil = new StorageUtil(this);
        String resizePath = storageUtil.createInnerFolderStorage("Resize");

        ResizeImageHelper helper = new ResizeImageHelper(this);
        File reFile = helper.resizeImageLength(length, userSelectedExt, fileUtility.getFilenameWithoutExtension(), resizePath, fileUtility.getUploadedFile());

        this.showCompressedResult(reFile);
    }


    private void showCompressedResult(File file){
        FileUtility newFileUtility = new FileUtility(file);

        String resolution = newFileUtility.getFileResolution();
        String fileSize = newFileUtility.getFileSize();
        String fileExtension = newFileUtility.getExtension();
        String absolutePath = newFileUtility.getFullPath();

        Intent resultIntent = new Intent(this, CompressResultActivity.class);
        resultIntent.putExtra(ConstantUtils.IMAGE_RESOLUTION, resolution);
        resultIntent.putExtra(ConstantUtils.IMAGE_SIZE, fileSize);
        resultIntent.putExtra(ConstantUtils.IMAGE_EXT, fileExtension);
        resultIntent.putExtra(ConstantUtils.IMAGE_ABSOLUTE_PATH, absolutePath);

        startActivity(resultIntent);
        Bungee.slideLeft(this);
        finish();
    }



    private void openGallery() {
        ImagePicker.with(this)
                .start();
    }

    private void toggleViews(){
        openImageDialog.setVisibility(View.GONE);
        featureContainer.setVisibility(View.VISIBLE);
    }

    private void setDefaultFileExtension(String ext) {
        List<ThemedButton> buttons = themeGroup.getButtons();

        buttons.forEach(themedButton -> {
            if (themedButton.getText().equals(ext)) {
                themeGroup.selectButton(themedButton.getId());
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {

            Uri uri = Objects.requireNonNull(data).getData();
            File helperFile = FileHelper.getFileFromIntentUri(CompressImageActivity.this, data);

            Picasso.get()
                    .load(helperFile)
                    .resize(400, 300)
                    .centerCrop()
                    .into(selectedImageView);

            //Process file
            fileUtility = new FileUtility(helperFile);
            String ext = Files.getFileExtension(helperFile.getAbsolutePath());

            //Show Image name and size
            selectedImageName.setText(fileUtility.getFilename());
            selectedImageSize.setText(fileUtility.getFileSize());

            // Show Image extension
            setDefaultFileExtension(fileUtility.getExtension().toUpperCase());

            //Toggle Visibility
            toggleViews();


        } else if (resultCode == ImagePicker.RESULT_ERROR) {
            Toast.makeText(CompressImageActivity.this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(CompressImageActivity.this, "Task Cancelled", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        int menuId = item.getItemId();
        if(menuId == android.R.id.home){
            onBackPressed();
        }

        return super.onOptionsItemSelected(item);
    }


    @Override
    public void onBackPressed() {
        super.onBackPressed();
        Bungee.slideRight(this);
    }

    private void compressBySize(int size, File file){

        Luban.compress(CompressImageActivity.this, file)
                .setMaxSize(size)
                .putGear(Luban.CUSTOM_GEAR)
                .asObservable()
                .subscribe(new Consumer<File>() {
                    @Override
                    public void accept(File file) throws Exception {

                        //get compress file and save in another folder.
                        FileUtility fUtil = new FileUtility(file);

                        //Process size compression
                        processImageSizeCompression(fUtil);

                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        Log.d(TAG, "Error compressing file size : " + throwable.getMessage());
                    }
                });
    }

    private void processImageSizeCompression(FileUtility fUtil){
        String filename = fUtil.getFilenameWithoutExtension();
        String extension = fUtil.getExtension();
        String size = fUtil.getFileSize();
        System.out.println("Size Output : " + size);

        StorageUtil storageUtil = new StorageUtil(this);
        String destinationFolder = storageUtil.createInnerFolderStorage("Resize");



        ResizeImageHelper helper = new ResizeImageHelper(this);
        File resizeFiled = helper.resizeImageSize(extension, filename, destinationFolder, fUtil.getUploadedFile());

        this.showCompressedResult(resizeFiled);
    }
}

There are some helper classes we have created that will be used in upcoming tutorials. They will be covered as we move along with the tutorial.

In the upcoming tutorial, we will learn how to resize an image on Android.

All the topics in this Android project is accessible here.

If you have any questions or suggestions about this project, kindly use the comment box and get in touch.

Leave a Reply