7

I have a Base64 String that represents a BitMap image.

I need to transform that String into a BitMap image again to use it on a ImageView in my Android app

How to do it?

Overwatch
  • 27
  • 1
  • 7
Mughira Dar
  • 103
  • 1
  • 1
  • 6
  • Does this answer your question? [How to convert a Base64 string into a BitMap image to show it in a ImageView?](https://stackoverflow.com/questions/4837110/how-to-convert-a-base64-string-into-a-bitmap-image-to-show-it-in-a-imageview) – Vishal Thakkar Nov 20 '19 at 13:32
  • 1
    you can find a Java implementation, and convert it to kotlin using Android Studio's tool – Vladyslav Matviienko Nov 20 '19 at 13:48

6 Answers6

18

You can use this code to decode: -

val imageBytes = Base64.decode(base64String, Base64.DEFAULT)
val decodedImage = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length)
imageView.setImageBitmap(decodedImage)
Prashant Sable
  • 1,003
  • 7
  • 19
4

You can use the android methods

Here imageString is your base64String of image.

Here is the java code:

byte[] decodedByte = Base64.decode(imageString, Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(decodedByte, 0, decodedString.length); 

Here is the kotlin code:

val decodedByte = Base64.decode(imageString, Base64.DEFAULT)
val bitmap = BitmapFactory.decodeByteArray(decodedByte, 0, decodedString.length) 

After that, you can set it into the image view

yourimage.setImageBitmap(bitmap);
Sunny
  • 3,134
  • 1
  • 17
  • 31
  • 1
    this doesn't look like `kotlin` – Vladyslav Matviienko Nov 21 '19 at 07:31
  • @VladyslavMatviienko If you paste the code in kotlin it automatically converts into the kotlin code. But I have added the code for kotlin as well. – Sunny Nov 21 '19 at 07:36
  • 3
    This kotlin code did not work for me until I changed the BitmapFactory.decodeByteArray(decodedByte, 0, decodedString.length) to BitmapFactory.decodeByteArray(decodedByte, 0, decodedString.size). decodedString doesn't have a "length" method, just the "size" method. After the change everything worked like a charm, so thank you for the code. – akrelj Nov 12 '20 at 08:57
1

From the answer above, I made it as a function.

KOTLIN: you could create a function like this

 fun decodePicString (encodedString: String): Bitmap {

    val imageBytes = Base64.decode(encodedString, Base64.DEFAULT)
    val decodedImage = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)

    return decodedImage
}    

then call it and set it to your imgView like this:

val mImgView = findViewById<ImageView>(R.id.imageView)
mImageView.setImageBitmap(decodePicString(your encoded string for the picture))
1

In Kotlin You can just use decode function for byteArray...

private fun stringToBitmap(encodedString: String): Bitmap {
        val imageBytes = decode(encodedString, DEFAULT)
        return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
    }
Hamza Rasheed
  • 179
  • 1
  • 2
0

For those who seek a general answer for Base64 conversions (not just Android):

You can make use of java.util.Base64

to encode

val imageString = Base64.getEncoder().encode(imageBytes)

to decode

val imageBytes = Base64.getDecoder().decode(imageString)
Fatih
  • 507
  • 4
  • 15
0
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.util.Base64
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import java.io.ByteArrayOutputStream
import java.io.File

class MainActivity : AppCompatActivity() {

    lateinit var imgView: ImageView
    lateinit var btnChange: Button
    lateinit var imageUri: Uri
    lateinit var btnConvert: Button
    lateinit var txtView: TextView

    //give uri to the camera apk
    private val contract = registerForActivityResult(ActivityResultContracts.TakePicture()) {
        //assgin null bcz when we click next image it will update
        imgView.setImageURI(null)
        //callback - calls when the data comes from the camera
        imgView.setImageURI(imageUri)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        imgView = findViewById(R.id.imgView)
        btnChange = findViewById(R.id.btnChange)
        btnConvert = findViewById(R.id.button)
        txtView = findViewById(R.id.txtView)
        //call fun createImageUri -so it can be set
        imageUri = createImageUrl()!!

        btnConvert.setOnClickListener {
            val base64Image = getFileToByte(imageUri)
            txtView.text = base64Image
        }

        btnChange.setOnClickListener {
            contract.launch(imageUri)
        }
    }

//    private fun getFileToByte(uri: Uri): String? {
//        var bmp: Bitmap? = null
//        var bos: ByteArrayOutputStream? = null
//        var bt: ByteArray? = null
//        var encodeString: String? = null
//        try {
//            bmp = BitmapFactory.decodeStream(contentResolver.openInputStream(uri))
//            bos = ByteArrayOutputStream()
//            bmp.compress(Bitmap.CompressFormat.JPEG, 100, bos)
//            bt = bos.toByteArray()
//            encodeString = Base64.encodeToString(bt, Base64.DEFAULT)
//        } catch (e: Exception) {
//            e.printStackTrace()
//        } finally {
//            bos?.close()
//        }
//        return encodeString
//    }


    private fun getFileToByte(uri: Uri): String? {

        //allows us to set decoding preferences when decoding a bitmap.
        val options = BitmapFactory.Options()

        options.inSampleSize = 4 // Reduces the decoded image decoded will be halved twice (1/4 of the original).

        var bmp: Bitmap? = null
        var bos: ByteArrayOutputStream? = null
        var bt: ByteArray? = null
        var encodeString: String? = null
        try {

            // Decode the image file referenced by the URI into a Bitmap.
            // The third argument provides decoding options.
            // The result is a smaller version of the image to reduce memory usage.

            bmp = BitmapFactory.decodeStream(contentResolver.openInputStream(uri), null, options)
            //will capture the output of the compressed bitmap
            bos = ByteArrayOutputStream()
            // Compress the bitmap into JPEG format and write the bytes to the ByteArrayOutputStream.
            // The second argument is the quality setting, which is set to 50 (range is 0-100).
            // This reduces the quality to save space and speed up encoding.

            bmp!!.compress(Bitmap.CompressFormat.JPEG, 50, bos) // 50% quality compression

            // Convert the ByteArrayOutputStream to a byte array.
            bt = bos.toByteArray()
            // Convert the byte array to a Base64 encoded string.
            encodeString = Base64.encodeToString(bt, Base64.DEFAULT)
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            // Always close the ByteArrayOutputStream to free up resources.
            bos?.close()
        }
        return encodeString
    }


    //fun for create image file in private space
    private fun createImageUrl(): Uri? {
        //find Uri (for it we use FileProvider) and then return it.
        val image = File(applicationContext.filesDir, "camera_photo.png")
        return FileProvider.getUriForFile(
            applicationContext,
            "com.company0ne.demoproject_2.fileProvider",
            image
        )
    }
}