I'm using google ml kit for face detection, then use bounding Box function to crop faces.
I successfully integrate cameras ,then want to add select from gallery function, which I successfully implement previous training app that I wrote in Java, yet I can find why App written in Kotlin can not identify image Uri from gallery.
I tried multiple methods InputImage.fromBirmap(), InputImage.fromFilePath() and InputImage.fromByteArray("use nv21"), and used Image View to display images with rotation degrees that seems perfect. You can find codes that initiated by on click method below, except InputImage.fromFilePath() and InputImage.fromByteArray("use nv21") which tried first, then delete the codes.
Also thank you before hand.
private fun selectImage() {
val intent = Intent()
intent.type = "image/*"
intent.action = Intent.ACTION_GET_CONTENT
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 11)
}
#RequiresApi(Build.VERSION_CODES.N)
#Deprecated("Deprecated in Java")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
if (requestCode == 11) {
if (data != null){
val bitmap = getBitmapFromUri(data.data!!)
Log.d(TAG, "onActivityResult: ${data.data!!}")
val inputStream = contentResolver.openInputStream(data.data!!)
val exif = ExifInterface(inputStream!!)
val rotation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL
)
val rotationInDegrees: Int = exifToDegrees(rotation)
inputStream.close()
Log.d(TAG, "onActivityResult: rotation: $rotation")
if (bitmap != null) selectedImageAnalyser(bitmap, rotationInDegrees)
}
}
}
}
private fun exifToDegrees(exifOrientation: Int): Int {
return when (exifOrientation) {
ExifInterface.ORIENTATION_ROTATE_90 -> {
90
}
ExifInterface.ORIENTATION_ROTATE_180 -> {
180
}
ExifInterface.ORIENTATION_ROTATE_270 -> {
270
}
else -> 0
}
}
private fun getBitmapFromUri(uri: Uri): Bitmap? {
var bitmap: Bitmap? = null
try {
bitmap = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1) {
val source = ImageDecoder.createSource(
contentResolver, uri
)
ImageDecoder.decodeBitmap(source)
} else {
MediaStore.Images.Media.getBitmap(contentResolver, uri)
}
} catch (e: IOException) {
e.printStackTrace()
}
return bitmap
}
private fun selectedImageAnalyser(bitmap: Bitmap, rotationDegree: Int) {
val mBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
val inputImage = InputImage.fromBitmap(mBitmap, rotationDegree)
val rotation = inputImage.rotationDegrees
Log.d(TAG, "onActivityResult: rotation: $rotation")
binding!!.ivFace.apply {
visibility = View.VISIBLE
setImageBitmap(inputImage.bitmapInternal)
}
faceDetector.process(inputImage)
.addOnSuccessListener { faces ->
if (faces.isNullOrEmpty()){
val croppedFace = cropToBox(bitmap,faces[0].boundingBox,rotation)
startEnrollDialog(croppedFace)
} else{
Log.d(TAG, "selectedImageAnalyser: face can not identified")
}
}
.addOnFailureListener { Log.d(TAG, "selectedImageAnalyser: \n\t Cause: ${it.cause} \n\t Message: ${it.message}") }
.addOnCompleteListener { }
}
Related
I am new to Android development, and im making simple aplication that capture image then save. I can capture the image and show into imageview, but unfortunately i cannot save into gallery.
i tryed many ways but cannot save. this is original code to take and show.
// EDITED //
I add function to save file, but still not working
class TomarFotos : AppCompatActivity() {
lateinit var photoPath: String
val REQUEST_IMAGE_CAPTURE = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tomar_fotos)
val foto = findViewById<Button>(R.id.tomarfotos)
foto.setOnClickListener{
tomarFoto()
}
}
fun tomarFoto() {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if(intent.resolveActivity(packageManager) != null){
var photoFile: File? = null
try{
photoFile = createImageFile()
}catch (e: IOException){}
if(photoFile != null){
val photoUri = FileProvider.getUriForFile(
this,
"com.example.android.fileprovider",
photoFile
)
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
startActivityForResult(intent,REQUEST_IMAGE_CAPTURE)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val fotoTomada = findViewById<ImageView>(R.id.fotopreview)
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
fotoTomada.rotation = 90f
fotoTomada.setImageURI(Uri.parse(photoPath))
}
}
private fun createImageFile(): File? {
val fileName = "foto"
val storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
val image = File.createTempFile(
fileName,
".jpg",
storageDir
)
photoPath = image.absolutePath
return image
}
}
i try developer.android.com already but didnt work
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val fotoTomada = findViewById<ImageView>(R.id.fotopreview)
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
val imageBitmap = data?.extras?.get("data") as Bitmap
fotoTomada.setImageBitmap(imageBitmap)
saveImage(imageBitmap)
}
}
Call this function to save image to gallery
private fun saveImage(bitmap: Bitmap) {
var outStream: FileOutputStream? = null
// Write to SD Card
try {
val dir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + "AppName/")
dir.mkdirs()
val fileName = "IMG_${System.currentTimeMillis()}"
val outFile = File(dir, fileName)
outStream = FileOutputStream(outFile)
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream)
outStream.flush()
outStream.close()
Toast.makeText(this#MainActivity, "Image Saved Successfully", Toast.LENGTH_LONG).show()
} catch (e: FileNotFoundException) {
Log.d("TAG", "saveImage: ${e.message}")
} catch (e: IOException) {
Log.d("TAG", "saveImage: ${e.message}")
}
}
i'm trying to capture image in android 11 device but request is keep cancelled. i have added also. still unable to capture image. pick image from gallery is working. image is not storing in Android/data folder.
i have added val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) also still unable to create temp file in storage. please provide any solutions
private fun selectImage() {
imageUtils.createImageFile(applicationContext).let {
viewModel.setFileTempPath(it.absolutePath, "doc_name")
startActivityForResult(imageUtils.captureImage(applicationContext, it), 300)
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
300 -> when (resultCode) {
RESULT_OK -> {
Log.d("tmppath", data?.data.toString())
if (data != null && data.data != null) {
val selectedImage: Bitmap =
imageUtils.getBitmap(data.data, this#TaggingActivity)!!
viewModel.dataModel.selectedImagesArrayList.value.let {
if (it == null) {
viewModel.dataModel.selectedImagesArrayList.value = ArrayList()
}
val a = it
a?.add(
ImageDetailsToUpload(
"",
selectedImage,
Constant.CUSTOMER_GEO_TAG,
viewModel.dataModel.documentName.value,
viewModel.commonModel.currentLocation.value!!
)
)
viewModel.dataModel.selectedImagesArrayList.postValue(a)
}
} else {
if (viewModel.dataModel.tmpPath.value != null) {
imageUtils.getBitmapFromPath(viewModel.dataModel.tmpPath.value)
?.let { selectedImage ->
val a = viewModel.dataModel.selectedImagesArrayList.value
a?.add(
ImageDetailsToUpload(
"",
selectedImage,
Constant.CUSTOMER_GEO_TAG,
viewModel.dataModel.documentName.value,
viewModel.commonModel.currentLocation.value!!
)
)
viewModel.dataModel.selectedImagesArrayList.postValue(a)
} ?: run {
viewModel.commonModel.showToastTextView("Sorry Try Again..!")
}
} else {
viewModel.commonModel.showToastTextView("Sorry Try Again..!")
return
}
}
viewModel.dataModel.tmpPath.value = null
}
RESULT_CANCELED -> {
viewModel.setFileTempPath("", "")
Toast.makeText(this,"cancelled",Toast.LENGTH_LONG).show()
}
}
}
//Intent class
fun getCameraIntent(file: File): Intent {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file))
if (Build.VERSION.SDK_INT >= 24) {
try {
val m =
StrictMode::class.java.getMethod("disableDeathOnFileUriExposure")
m.invoke(null)
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
} else {
takePictureIntent.putExtra("return-data", true)
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
val pickPhoto = Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
)
val intents: ArrayList<Intent> = arrayListOf()
intents.add(takePictureIntent)
intents.add(pickPhoto)
val chooserIntent = Intent.createChooser(
intents.removeAt(intents.size - 1),
" Document Upload"
)
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(arrayOf<Parcelable>()))
return chooserIntent
}
i need to upload image to php server but i need the image to be at max quality before it would capture and upload a bitmap but i need the image to be clear so i tried this code but cant seem to get it to work.
so basically i need to upload the image stored on this line
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri)
class capture : AppCompatActivity() {
private val PERMISSION_CODE = 1000;
private val IMAGE_CAPTURE_CODE = 1001
var image_uri: Uri? = null
var bitmap: Bitmap? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_capture)
//button click
btn_take_photo.setOnClickListener {
//if system os is Marshmallow or Above, we need to request runtime permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if (checkSelfPermission(Manifest.permission.CAMERA)
== PackageManager.PERMISSION_DENIED ||
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_DENIED){
//permission was not enabled
val permission = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
//show popup to request permission
requestPermissions(permission, PERMISSION_CODE)
}
else{
//permission already granted
openCamera()
}
}
else{
//system os is < marshmallow
openCamera()
}
}
}
private fun openCamera() {
val values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "New Picture")
values.put(MediaStore.Images.Media.DESCRIPTION, "From the Camera")
image_uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
//camera intent
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri)
startActivityForResult(cameraIntent, IMAGE_CAPTURE_CODE)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
//called when user presses ALLOW or DENY from Permission Request Popup
when(requestCode){
PERMISSION_CODE -> {
if (grantResults.size > 0 && grantResults[0] ==
PackageManager.PERMISSION_GRANTED){
//permission from popup was granted
openCamera()
}
else{
//permission from popup was denied
Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show()
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
//called when image was captured from camera intent
if (resultCode == Activity.RESULT_OK){
val takenImage: Bitmap = BitmapFactory.decodeFile(image_uri.toString())
//set image captured to image view
imgv_capture_image_preview.setImageURI(image_uri)
val url = connection.server_url + "body_pictures.php"
val rq: RequestQueue = Volley.newRequestQueue(this)
val sr = object : StringRequest(Method.POST, url, Response.Listener { response ->
val check: String = response
val checknew = check.replace("\\s".toRegex(), "")
if (checknew == "success") {
Toast.makeText(
this,
"Image uploaded Successful",
Toast.LENGTH_LONG
).show()
} else {
Toast.makeText(
this,
"ERROR image upload failed, " + checknew,
Toast.LENGTH_LONG
).show()
}
}, Response.ErrorListener { error ->
Toast.makeText(
this,
"Server TIME OUT",
Toast.LENGTH_LONG
).show()
}) {
override fun getParams(): MutableMap<String, String> {
val map = HashMap<String, String>()
val images = takenImage?.let { getStringImage(it) }
if (images != null) {
map.put("image_data", images)
}
return map
}
}
rq.add(sr)
}
}
fun getStringImage(bitmap: Bitmap): String? {
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val b = baos.toByteArray()
return Base64.encodeToString(b, Base64.DEFAULT)
}
My onActivityResult is not working because getBitmap is deprecated. Is there any alternative code to achieve this?
Here is the code that needs to be changed (any suggestions?):
val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, selectedPhotoUri)
The getBitmap is crossed out in my tooling with a message that says it's deprecated.
This worked for me,
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == 1 && resultCode == Activity.RESULT_OK && data != null) {
val selectedPhotoUri = data.data
try {
selectedPhotoUri?.let {
if(Build.VERSION.SDK_INT < 28) {
val bitmap = MediaStore.Images.Media.getBitmap(
this.contentResolver,
selectedPhotoUri
)
imageView.setImageBitmap(bitmap)
} else {
val source = ImageDecoder.createSource(this.contentResolver, selectedPhotoUri)
val bitmap = ImageDecoder.decodeBitmap(source)
imageView.setImageBitmap(bitmap)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
This worked well for me in java
ImageDecoder.Source source = ImageDecoder.createSource(this.getContentResolver(), pictureUri);
Bitmap bitmap = ImageDecoder.decodeBitmap(source);
You can use:
private fun getCapturedImage(selectedPhotoUri: Uri): Bitmap {
val bitmap = when {
Build.VERSION.SDK_INT < 28 -> MediaStore.Images.Media.getBitmap(
this.contentResolver,
selectedPhotoUri
)
else -> {
val source = ImageDecoder.createSource(this.contentResolver, selectedPhotoUri)
ImageDecoder.decodeBitmap(source)
}
}
Check the official doc:
This method was deprecated in API level 29.
loading of images should be performed through ImageDecoder#createSource(ContentResolver, Uri), which offers modern features like PostProcessor.
You can use this code for creating bitmap
Bitmap bitmap;
if (Build.VERSION.SDK_INT >= 29) {
ImageDecoder.Source source = ImageDecoder.createSource(getApplicationContext().getContentResolver(), imageUri);
try {
bitmap = ImageDecoder.decodeBitmap(source);
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
bitmap = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(), imageUri);
} catch (IOException e) {
e.printStackTrace();
}
}
It was evident that the getBitmap API doesn't work with the latest Android SDK - 29. So, this worked for me
Uri contentURI = data.getData();
try {
imageView.setImageURI(contentURI);
} catch (Exception e) {
e.printStackTrace();
}
Please let me know if this doesn't work for any of you, shall other options!
I have created a class for loading a Bitmap from uri:
public class BitmapResolver {
private final static String TAG = "BitmapResolver";
#SuppressWarnings("deprecation")
private static Bitmap getBitmapLegacy(#NonNull ContentResolver contentResolver, #NonNull Uri fileUri){
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(contentResolver, fileUri);
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
#TargetApi(Build.VERSION_CODES.P)
private static Bitmap getBitmapImageDecoder(#NonNull ContentResolver contentResolver, #NonNull Uri fileUri){
Bitmap bitmap = null;
try {
bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(contentResolver, fileUri));
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
public static Bitmap getBitmap(#NonNull ContentResolver contentResolver, Uri fileUri){
if (fileUri == null){
Log.i(TAG, "returning null because URI was null");
return null;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
return getBitmapImageDecoder(contentResolver, fileUri);
} else{
return getBitmapLegacy(contentResolver, fileUri);
}
}
}
Just to save you some time ...
ImageDecoder.createSource(this.getContentResolver(), pictureUri)
works fine, but to be able to use this code, mindSdkVersion should be at least 28.
Have you tried this?
val bitmap = ImageDecoder.createSource(contentResolver, uri)
hi freind you check api device
var Image_select: String? = null
var bitmap:Bitmap?=null
you show image set
binding?.ImAvator?.setImageURI(data!!.data)
try {
val uri: Uri? = data!!.data
bitmap = if(Build.VERSION.SDK_INT>=29){
val source: ImageDecoder.Source = ImageDecoder.createSource(requireActivity()
.contentResolver, uri!!)
ImageDecoder.decodeBitmap(source)
} else{
MediaStore.Images.Media.getBitmap(requireActivity().contentResolver, uri!!)
}
} catch (e: IOException) {
e.printStackTrace()
}
when upload image
compress bitmap send server
fun Camparse() {
val size = (bitmap!!.height * (812.0 / bitmap!!.width)).toInt()
val b = Bitmap.createScaledBitmap(bitmap!!, 812, size, true)
val by = ByteArrayOutputStream()
b.compress(Bitmap.CompressFormat.JPEG, 100, by)
val bytes = by.toByteArray()
Image_select = Base64.encodeToString(bytes, 0)
}
For deprecated MediaStore.Images.Media.getBitmap() in API level 29, You can use this code:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == Activity.RESULT_OK) {
if (requestCode == GALLERY_REQUEST) {
Uri selectedImage = data.getData();
try {
if (Build.VERSION.SDK_INT < 29) {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), selectedImage);
imageView2.setImageBitmap(bitmap);
} else {
ImageDecoder.Source source = ImageDecoder.createSource(getActivity().getContentResolver(), selectedImage);
Bitmap bitmap = ImageDecoder.decodeBitmap(source);
imageView2.setImageBitmap(bitmap);
}
} catch (IOException e) {
Toast.makeText(getContext(), R.string.error_read_image, Toast.LENGTH_LONG).show();
}
}
}
}
Regards.
if(result.resultCode == Activity.RESULT_OK && result.data != null {
binding?.ivImage?.setImageURI(result.data?.data)}
For anyone getting unsupported bitmap configuration : "Hardware" error or you need mutable bitmap for Canvas or reading pixels use this
ImageDecoder.decodeBitmap(
ImageDecoder.createSource(context.contentResolver, uri)
) { decoder, info, source ->
decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
decoder.isMutableRequired = true
}
This code works for my case:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
try {
when (requestCode) {
//get the image with camera
SECTIONCAMERA -> {
val imageBitmap = data?.extras?.get("data") as Bitmap
ImageView_imagePerfil.setImageBitmap(imageBitmap)
}
//get the image in gallery
SECTIONGALLERY -> {
val imageUri = data?.data
ImageView_imagePerfil.setImageURI(imageUri) }
}
} catch (e: Exception){
e.printStackTrace()
}
}
I need help. On my onCreate() I have this code:
takePhotoDialog = DialogGetPhotoFrom.getInstance().apply {
setListener(object : DialogGetPhotoFrom.DialogListener {
override fun onTakeFromGallery() {
Log.v("ProjectDetails", "onTakeFromGallery called")
val intent = Intent().apply {
type = "image/*"
action = Intent.ACTION_GET_CONTENT
}
startActivityForResult(Intent.createChooser(intent, "Select Image"), REQUEST_PICK_IMAGE)
}
override fun onTakePhoto() {
dispatchTakePictureIntent()
}
})
}
projectDetails_pickImage.setOnClickListener { takePhotoDialog?.show(supportFragmentManager) }
An on my onActivityResult, I wrote:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_PICK_IMAGE -> {
Log.v("ProjectDetails", "REQUEST_PICK_IMAGE called")
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
try {
val inputStream = contentResolver.openInputStream(data.data)
val bitMap = BitmapFactory.decodeStream(inputStream)
projectDetails_image.setImageBitmap(bitMap)
// TODO Save image URI to database
} catch (e: Exception) {
Toast.makeText(this, "Can't set background.", Toast.LENGTH_SHORT).show()
}
} else {
Log.v("ProjectDetails", "data is null")
}
}
}
}
}
The problem is, onActivityResult() doesn't fire when an image is selected. What should I do?
Solved it! The solution is to put the codes inside my onTakeGallery() function to a function that belongs to the Activity class. So my code will look like this:
takePhotoDialog = DialogGetPhotoFrom.getInstance().apply {
setListener(object : DialogGetPhotoFrom.DialogListener {
override fun onTakeFromGallery() {
dispatchSelectFromGalleryIntent()
}
override fun onTakePhoto() {
dispatchTakePictureIntent()
}
})
}
projectDetails_pickImage.setOnClickListener {
takePhotoDialog?.show(supportFragmentManager)
}
And the extracted codes goes here:
private fun dispatchSelectFromGalleryIntent() {
val intent = Intent().apply {
type = "image/*"
action = Intent.ACTION_GET_CONTENT
}
startActivityForResult(Intent.createChooser(intent, "Select Image"), REQUEST_PICK_IMAGE)
}