Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Circular Crop an Image and Save it to the File in Android

  • Last Updated : 05 Aug, 2021

There are multiple applications available in the market that help in dealing with image processing, while most of them fail to produce very basic operations. Cropping is a simple application when one could resize an image by cutting it down. This task becomes complex when it comes to free-hand or shape cropping, meaning cropping the image in the desired shape.

In this article, we will show you how you create an application to crop an image in a circular manner and store it in the local device. No external library or service is used to generate this application.

Step by Step Implementation

Step 1: Create a New Project in Android Studio

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. We demonstrated the application in Kotlin, so make sure you select Kotlin as the primary language while creating a New Project.

Step 2: Add an ImageView and two Buttons in the activity_main.xml or the layout file

XML




<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
      <!-- Image will be loaded here -->
    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="500dp"
        android:layout_centerInParent="true" />
  
      <!-- Button to perform Cropping -->
    <Button
        android:id="@+id/btnCrop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="Crop" />
  
      <!-- Button to save the image in ImageView -->
    <Button
        android:id="@+id/btnSave"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:text="Save" />
  
</RelativeLayout>

Step 3: Add the desired image in the res > drawable folder

While adding, give it the desired name. For our reference, this image is “image.png” which is downloaded from the Internet and copied directly into the drawable folder.

Step 4: Write the following code for MainActivity.kt

There are two functions inside this code:

  1. getCircularBitmap(Bitmap) : To crop the image
  2. saveMediaToStorage(Bitmap) : To save the image. Refer How to Capture Screenshot of a View and Save it to Gallery in Android?

Refer to the comments for better understanding.

Kotlin




import android.content.ContentValues
import android.graphics.*
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import android.widget.Button
import android.widget.ImageView
import android.widget.Toast
import androidx.annotation.RequiresApi
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream
import java.lang.Integer.min
  
class MainActivity : AppCompatActivity() {
  
    // Declaring the UI elements from the layout file
    private lateinit var buttonCrop: Button
    private lateinit var buttonSave: Button
    private lateinit var imageView: ImageView
    
    // Declaring the Bitmap
    private lateinit var bitmap: Bitmap
  
    @RequiresApi(Build.VERSION_CODES.N)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        // Initializing the UI elements
        imageView = findViewById(R.id.iv)
        buttonCrop = findViewById(R.id.btnCrop)
        buttonSave = findViewById(R.id.btnSave)
  
        // Declaring resource address ( type integer)
        val bitmapResourceID: Int = R.drawable.image
        
        // Setting the ImageView with the Image
        imageView.setImageBitmap(BitmapFactory.decodeResource(resources, bitmapResourceID))
        bitmap = BitmapFactory.decodeResource(resources, bitmapResourceID)
  
        // When Crop button is clicked
        buttonCrop.setOnClickListener {
              // runs a custom function on the original image
            bitmap = getCircularBitmap(bitmap)
              
            // Sets the ImageView with the editted/cropped Image
            imageView.setImageBitmap(bitmap)
        }
  
        // When Save button is clicked
        buttonSave.setOnClickListener {
             // Save whatever the bitmap is (edited/uneditted) into the device.
            saveMediaToStorage(bitmap)
        }
    }
  
    // Function to crop the image in a circle
    @RequiresApi(Build.VERSION_CODES.N)
    private fun getCircularBitmap(srcBitmap: Bitmap?): Bitmap {
        
        // Select whichever of width or height is minimum
        val squareBitmapWidth = min(srcBitmap!!.width, srcBitmap.height)
          
        // Generate a bitmap with the above value as dimensions
        val dstBitmap = Bitmap.createBitmap(
            squareBitmapWidth,
            squareBitmapWidth,
            Bitmap.Config.ARGB_8888
        )
          
        // Initializing a Canvas with the above generated bitmap
        val canvas = Canvas(dstBitmap)
          
        // initializing Paint
        val paint = Paint()
        paint.isAntiAlias = true
        
        // Generate a square (rectangle with all sides same)
        val rect = Rect(0, 0, squareBitmapWidth, squareBitmapWidth)
        val rectF = RectF(rect)
          
        // Operations to draw a circle
        canvas.drawOval(rectF, paint)
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        val left = ((squareBitmapWidth - srcBitmap.width) / 2).toFloat()
        val top = ((squareBitmapWidth - srcBitmap.height) / 2).toFloat()
        canvas.drawBitmap(srcBitmap, left, top, paint)
        srcBitmap.recycle()
          
        // Return the bitmap
        return dstBitmap
    }
  
    // Function to save an Image
    private fun saveMediaToStorage(bitmap: Bitmap) {
        val filename = "${System.currentTimeMillis()}.jpg"
  
        var fos: OutputStream? = null
  
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            this.contentResolver?.also { resolver ->
                val contentValues = ContentValues().apply {
                    put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
                    put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
                    put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
                }
                val imageUri: Uri? = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
                fos = imageUri?.let { resolver.openOutputStream(it) }
            }
        } else {
            val imagesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
            val image = File(imagesDir, filename)
            fos = FileOutputStream(image)
        }
  
        fos?.use {
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)
            Toast.makeText(this , "Captured View and saved to Gallery" , Toast.LENGTH_SHORT).show()
        }
    }
}

Step 4: Add Storage permission in the AndroidManifest.xml file

This permission is needed to store the image in the device.

XML




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

Output:


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!