Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filters are not working when I use ActivityResultLauncher #419

Closed
Yumin2019 opened this issue Dec 7, 2021 · 5 comments
Closed

Filters are not working when I use ActivityResultLauncher #419

Yumin2019 opened this issue Dec 7, 2021 · 5 comments
Labels

Comments

@Yumin2019
Copy link
Contributor

I'm using PhotoEditor library. I've been really thankful for your PhotoEditor personally.
but while I'm using it, I got an error when I use registerForActivityResult functions

In your project, you're using startActivityForResult functions. when I used them, I didn't get this issue.
but registerForActivityResult are different.

    // registerForActivityResult
    protected lateinit var cameraLauncher: ActivityResultLauncher<Uri>
    protected lateinit var galleryLauncher: ActivityResultLauncher<String>

in EditProfileFragment

    fun cameraButton()
    {
        if(CB_SingleSystemMgr.isDialog(CB_SingleSystemMgr.DIALOG_TYPE.ITEM_LIST_DIALOG))
            return

        val listItem = arrayListOf(
            DialogItem(getString(R.string.str_camera), R.drawable.camera,
                callback =
                {
                    Log.i(strTag, "camera")
                    cameraLauncher.launch(imageUri)
                }),
            DialogItem(getString(R.string.str_gallery), R.drawable.image,
                callback =
                {
                    Log.i(strTag, "gallery")
                    galleryLauncher.launch("image/*")
                })
        )

        CB_ItemListDialog(requireActivity(), getString(R.string.str_change_profile_image), listItem, true)
    }

onCreate

// camera launcher
        cameraLauncher = registerForActivityResult(ActivityResultContracts.TakePicture())
        { isSaved ->

            if(!isSaved)
            {
                Log.e(strTag, "user canceled camera")
                return@registerForActivityResult
            }

            imageProcess()
        }

        galleryLauncher = registerForActivityResult(ActivityResultContracts.GetContent())
        { uri ->

            if(uri == null)
            {
                Log.e(strTag, "user canceled gallery")
                return@registerForActivityResult
            }

            imageUri = uri
            imageProcess()
        }

imageProcess function

 protected fun imageProcess()
    {
        CB_AppFunc.networkScope.launch {

            imageBitmap = CB_AppFunc.getBitmapFromUri(requireActivity().applicationContext.contentResolver, imageUri!!)
            if(imageBitmap == null)
            {
                Log.e(strTag, "failed to convert uri to bitmap")
                uploadFailed()
                return@launch
            }

            // N 버전 이상만 화면 회전을 시도한다. (외부 저장소 권한 제거) orientation
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
            {
                try
                {
                    val inputStream = CB_AppFunc.application.contentResolver.openInputStream(imageUri!!)!!
                    val exifInterface = ExifInterface(inputStream)
                    imageBitmap = CB_AppFunc.changeImageOrientation(imageBitmap!!, exifInterface)
                }
                catch (e: IOException)
                {
                    e.printStackTrace()
                    imageBitmap = null
                }

                if(imageBitmap == null)
                {
                    Log.e(strTag, "failed to change orientation on image")
                    uploadFailed()
                    return@launch
                }
            }

            // image is not null, go to EditImageActivity
            CB_AppFunc.mainScope.launch {
                CB_ViewModel.editorBitmap = imageBitmap
                CB_PhotoEditorActivity.cameraListener = this@CB_CameraBaseFragment
                startActivity(Intent(requireActivity(), EditImageActivity::class.java))
            }
        }
    }

onCreate in EditImageActivity

 Bitmap bitmap = CB_ViewModel.Companion.getEditorBitmap();

        if(bitmap == null)
            Log.e(TAG, "bitmap is null");

        mPhotoEditorView.getSource().setImageBitmap(bitmap);


startActivityForResult: Camera / gallery => bitmap => EditImageActivity (OK)
registerForActivityResult: Camera / gallery => bitmap => EditImageActivity (I got bitmap but filters are not working)

I'm testing Android API 30 Emulator

Thanks.

@Yumin2019
Copy link
Contributor Author

I was replacing my functions to startActivityForResult and added orientation logic and I got an error like this.

java.lang.IllegalStateException: Software rendering doesn't support hardware bitmaps

I googled it and I changed my getBitmapFromUri function like this.

Previous

 fun getBitmapFromUri(imageUri: Uri): Bitmap?
        {
            return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
            {
                ImageDecoder.decodeBitmap(ImageDecoder.createSource(application.contentResolver, imageUri))
            }
            else
            {
                MediaStore.Images.Media.getBitmap(application.contentResolver, imageUri)
            }
        } 

Now

  fun getBitmapFromUriSoftware(imageUri: Uri): Bitmap = let {

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
            {
                return@let ImageDecoder.decodeBitmap(ImageDecoder.createSource(application.contentResolver, imageUri))
                { decoder: ImageDecoder, _: ImageDecoder.ImageInfo?, _: ImageDecoder.Source? ->
                    decoder.isMutableRequired = true
                    decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
                }
            }

            BitmapDrawable(application.resources,
                MediaStore.Images.Media.getBitmap(application.contentResolver, imageUri)).bitmap
        }

And it works well without exception. and I tried this way to my ActivityResultLauncher issue as well.
and Magically it works too without any problem.

https://developer.android.com/reference/android/graphics/ImageDecoder#setMutableRequired(boolean)

according to google document

By default, a Bitmap created by decodeBitmap will be immutable i.e. Bitmap.isMutable() returns false. This can be changed with setMutableRequired(true).

Mutable Bitmaps are incompatible with ALLOCATOR_HARDWARE, because Bitmap.Config#HARDWARE Bitmaps cannot be mutable. Attempting to combine them will throw an IllegalStateException.

anyways, I think if we use decodeBitmap function, we need to care about this mutable attribution.
I think it's better to mention about this in readme file.

about IllegalStateException
http://bumptech.github.io/glide/doc/hardwarebitmaps.html

@github-actions
Copy link

github-actions bot commented Jan 3, 2022

This issue is stale because it has been open 20 days with no activity. Remove stale label or comment or this will be closed in 4 days.

@github-actions github-actions bot added the Stale label Jan 3, 2022
@Yumin2019
Copy link
Contributor Author

comment

@github-actions github-actions bot removed the Stale label Feb 3, 2022
@github-actions
Copy link

github-actions bot commented Mar 3, 2022

This issue is stale because it has been open 20 days with no activity. Remove stale label or comment or this will be closed in 4 days.

@github-actions github-actions bot added the Stale label Mar 3, 2022
@github-actions
Copy link

github-actions bot commented Apr 3, 2022

This issue was closed because it has been stalled for 5 days with no activity.

@github-actions github-actions bot closed this as completed Apr 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant