canhub / android-image-cropper Goto Github PK
View Code? Open in Web Editor NEWImage Cropping Library for Android, optimised for Camera / Gallery.
Home Page: https://canhub.github.io/
License: Apache License 2.0
Image Cropping Library for Android, optimised for Camera / Gallery.
Home Page: https://canhub.github.io/
License: Apache License 2.0
Hi. I have java.lang.NullPointerException: Attempt to invoke virtual method 'void com.theartofdev.edmodo.cropper.CropImageView.setOnSetImageUriCompleteListener(com.theartofdev.edmodo.cropper.CropImageView$OnSetImageUriCompleteListener)' on a null object reference when i try start activity whith this code from fragment
CropImage.activity()
.setGuidelines(CropImageView.Guidelines.ON)
.start(requireContext(), this)
Uri lacks 'file' scheme: content: //packagename.cropper.fileprovider/my_images/Pictures/imagename.jpg
I cannot Get path from URI
With the new OS the permission WRITE_EXTERNAL_STORAGE
got deprecated.
And now need to use scope storage.
Version 2.0.3
The Issue
CropImage.getActivityResult(data).bitmap = NULL
The Code
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
when (requestCode) {
GALLERY_REQUEST_CODE -> {
data?.data?.let { uri ->
activity?.let {
Log.d(TAG, "UpdateBlogFragment: onActivityResult: $uri")
launchImageCrop(uri)
}
} ?: showImageSelectionError()
}
CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE -> {
val resultBitmap: ByteArray?
Log.d(TAG, "CROP: CROP_IMAGE_ACTIVITY_REQUEST_CODE")
val result = CropImage.getActivityResult(data)
if (result == null) {
Log.d(TAG, "UpdateBlogFragment: onActivityResult: result = NULL")
}
val resultUri = result?.uri
Log.d(TAG, "UpdateBlogFragment: onActivityResult resultUri: ${resultUri.toString()}")
resultBitmap = result?.bitmap?.toByteArray()
Log.d(TAG, "UpdateBlogFragment: onActivityResult resultBitmap Size: ${resultBitmap?.size}")
val resultImage: String = Base64.decode(resultBitmap, Base64.DEFAULT).decodeToString()
viewModel.setUpdatedUri(resultImage)
}
CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE -> {
Log.d(TAG, "CROP: ERROR")
showImageSelectionError()
}
}
}
}
// extension function to convert bitmap to byte array
private fun Bitmap.toByteArray(): ByteArray {
ByteArrayOutputStream().apply {
compress(Bitmap.CompressFormat.JPEG, 10, this)
return toByteArray()
}
}
// extension function to convert byte array to bitmap
private fun ByteArray.toBitmap(): Bitmap {
return BitmapFactory.decodeByteArray(this, 0, size)
}
Expected behavior
I store my Images for the application in the backend and cashe as base64 strings (Works nice!)
I need the result to be in ByteArray not URI (I actually dont know how to extract a ByteArray from the URI)
So I try and extract the bitmap with .bitmap from th URI and then convert it to a ByteArray with the Extention function I wrote below
My viewModel also expects a base64 string or ByteArray
What happens
D/AppDebug: CROP: CROP_IMAGE_ACTIVITY_REQUEST_CODE
UpdateBlogFragment: onActivityResult resultUri: content://za.co.zone.cupio.cropper.fileprovider/my_images/Pictures/cropped7411884326467077015.jpg
UpdateBlogFragment: onActivityResult resultBitmap Size: null
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
...
Caused by: java.lang.NullPointerException: Attempt to get length of null array
at android.util.Base64.decode(Base64.java:138)
at za.co.zone.cupio.ui.main.blog.UpdateBlogFragment.onActivityResult(UpdateBlogFragment.kt:132)
Code Involved
val resultImage: String = Base64.decode(resultBitmap, Base64.DEFAULT).decodeToString()
Smartphone
AVD Pixel 4 XL API 30 64
Hello! I was wandering how difficult it would be to add support for free cropping. Allow the user to choose the point for every corner. This is a feature i am really interested in and i would like to contribute, but i would like some feedback from someone who is familiar with this project.
Thank you!
I suppose it's in the list of planned things to do, but I really don't like including credentials in build.gradle 😅 (or in gradle.properties like you mention in the guide)
EDIT: By this I mean doing whatever changes are needed so a Personal Access Token for GitHub isn't necessary, i've edited the previous title
I'm using 1.1.1 version of the library.
I'm getting error:
java.lang.RuntimeException: Failed to load sampled bitmap: content://example.com.example.cropper.fileprovider/my_images/Pictures/pickImageResult2620448784152359897.jpeg
File is not a picture when using CropImage activity.
Error occurs on Android 10 (Nokia 5.3 device) but I have also received error from our users that the same error occurs also on Android 11 devices.
I have previously used ArthurHub / Android-Image-Cropper version of the library and It didn't have this problem on Android 10. Only on Android 11.
Do you have any idea what I'm doing wrong or is there something on the library what should be fixed?
Thanks.
Is your feature request related to a problem? Please describe.
I have a particular use case where we would only like to crop the top or bottom of an image off.
Describe the solution you'd like
The ability to configure CropImageView
to only allow cropping the top or bottom off of an image. This would probably be coded as a new cropShape
, similar to rectangle, but with handles at the top and bottom rather than at the corners.
Describe alternatives you've considered
None (or a different library! :P)
Additional context
I want something similar to this iOS app, though with an Android look and feel:
(The app is PlayScore2.)
Describe the bug
When I am trying to launch CropImage activity on Google pixel 4 XL, It won't show camera option.
To Reproduce
Steps to reproduce the behavior:
On button click I am launching CropImage activity and I am expecting it should ask user to choose from below options
Camera or Gallery
But on Google Pixel 4 XL It directly shows photos from device
Expected behavior
It should ask user to chose photo from Camera or Gallery
Screenshots
If applicable, add screenshots to help explain your problem.
Smartphone (please complete the following information):
Additional context
Add any other context about the problem here.
Suppose i have three images to crop. inside onActivityResult()
how will i come to know that this result is for which image?
Describe the bug
For Rectangle shape: if you drag too far outside the crop window, nothing happens.
For Oval shape: if you drag far outside the crop window, it resizes the crop window as if you were touching the nearest handle (corners or sides).
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Both crop shapes are consistent. I think I'd expect both to behave like the rectangular shape, i.e. if you touch too far outside the crop window nothing happens.
Smartphone (please complete the following information):
Additional context
This issue is caused, essentially, by the fact that getOvalPressedMoveType
(in CropWindowHandler.kt
) doesn't return null values for touches far outside the crop window, whereas getRectanglePressedMoveType
does.
This is not a pressing issue for me. It could be a good first issue for someone to fix.
Describe the bug
Nothing too complex. It sometimes simply takes a lot of time to load the image and perform the cropping. This doesn't occur every time, but it does from time to time (say 1 out of 3).
To Reproduce
Steps to reproduce the behavior:
Expected behavior
3 and 4 are supposed to occur reasonably fast, but it takes minutes to load the image and to crop it. Sometimes, after more than 10 minutes, I simply gave up.
Screenshots
If applicable, add screenshots to help explain your problem.
Smartphone (please complete the following information):
Additional context
My device, OnePlus 6, has a pretty good hardware, so I definitely do not think it's a matter of resources.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.zak.setscanner, PID: 29662
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 37498368 bytes
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:161)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
Caused by: android.os.TransactionTooLargeException: data parcel size 37498368 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(BinderProxy.java:526)
at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4561)
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
After cropping image i found this issue that says Error: open failed: ENOENT (No such file or directory)
To Reproduce
Steps to reproduce the behavior:
Expected behavior
In previous library of https://github.com/edmodo/cropper its working fine but in your library its showing above error
Smartphone :
The library today already rotate images using 90
, 180
, 270
and 360
angles
The goal is to be able to rotate it by 1 degree difference.
For that will be need to auto zoom crop the image:
Add ui rotation selector, like a carrousel from 0-360
Describe the bug
They say an image is a thousand words. How about a video?
To Reproduce
Write a fragment whose layout file contains a CropImageView
which does simply the following:
onActivityCreated
, kick off some work in the background to produce a bitmap whose width is the same as the width of the CropImageView
(which is smaller in portrait mode than in landscape mode) and whose height is twice its with. When it's done, on the main thread call cropImageView.setImageBitmap(theBitmap)
. (As long as you have images of different dimensions across the two cases, you will see this issue.)Run the app in portrait mode and navigate to the fragment. Notice that the crop rectangle is defaulted to cover most of the image.
Rotate the device to landscape mode. Notice that the old crop rectangle has been restored, which is way smaller than what the default crop rectangle should be.
Expected behavior
Since I called cropImageView.setImageBitmap
to a potentially arbitrary unrelated bitmap, it should not restore the old image's crop rectangle.
Screenshots
See video above
Smartphone (please complete the following information):
Additional context
I would like to be in charge of how the CropImageView's state is restored. I have my own system which renders a bitmap image from JPEG file or from PDF page, and subsamples according to the size of the view it needs to fill. Everytime the fragment is recreated after a configuration change, I expect to be able to set up the CropImageView completely fresh, and restore it's state myself using my business logic. I don't need it to restore state.
Setting a new bitmap image should be enough to reset the CropImageView's state, including state remembered from before it was recreated.
It looks like this is a very simple fix. Consider the difference between setImageUriAsync
and setImageBitmap
. In the former, the following code is run:
clearImageInt();
mRestoreCropWindowRect = null;
mRestoreDegreesRotated = 0;
mCropOverlayView.setInitialCropWindowRect(null);
However, in the latter, only the following is run:
mCropOverlayView.setInitialCropWindowRect(null);
[...]
clearImageInt();
In particular mRestoreCropWindowRect
and mRestoreDegreesRotated
are never cleared. Then, later on, in onLayout
, once there is an image available these kick in and incorrectly restore the old window rect and degrees rotated.
I think the restoring code is fine to live in onLayout
, since you often want to wait until your view has been measured before doing some logic. However, we definitely should be clearing the old remembered state when setting a new bitmap image.
Otherwise, there should be a way to clear the saved instance state, or a flag that tells the CropImageView
not to bother with managing its state.
Describe the bug
When it was in Java, I could use :
cropImageView.setOnSetImageUriCompleteListener { _, _, error ->
...
Now I have to use :
cropImageView.setOnSetImageUriCompleteListener(object : CropImageView.OnSetImageUriCompleteListener {
override fun onSetImageUriComplete(view: CropImageView, uri: Uri, error: Exception?) {
To Reproduce
Expected behavior
Should still allow to do it.
Screenshots
No need
Smartphone (please complete the following information):
None.
Additional context
I think whoever converted to Kotlin didn't look enough at the resulting code...
To fix this, I think it's possible to use "fun interface" instead of just "interface". This should be added for each interface in the project that has a single function.
getting Null in intent data while clicking the image from the camera in Android 11
below in data i'm getting null in intent data
@OverRide
@SuppressLint("NewApi")
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// handle result of pick image chooser
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CropImage.PICK_IMAGE_CHOOSER_REQUEST_CODE) {
if (resultCode == Activity.RESULT_CANCELED) {
// User cancelled the picker. We don't have anything to crop
setResultCancel();
}
if (resultCode == Activity.RESULT_OK) {
mCropImageUri = CropImage.getPickImageResultUri(this, data);
savedState.putString("mCropImageUri", mCropImageUri.toString());
// For API >= 23 we need to check specifically that we have permissions to read external
// storage.
if (CropImage.isReadExternalStoragePermissionsRequired(this, mCropImageUri)) {
// request permissions and handle the result in onRequestPermissionsResult()
requestPermissions(
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
CropImage.PICK_IMAGE_PERMISSIONS_REQUEST_CODE);
} else {
// no permissions required or already grunted, can start crop image activity
mCropImageView.setImageUriAsync(mCropImageUri);
}
}
} else {
Toast.makeText(CropImageActivity.this, "Pressed Back", Toast.LENGTH_SHORT).show();
finish();
}
}
Describe the bug
This:
val wholeImageRect: Rect?
get() {
...
} // get the points of the crop rectangle adjusted to source bitmap
// get the rectangle for the points (it may be larger than original if rotation is not straight)
To Reproduce
Expected behavior
Shouldn't have comments after the "}"
Smartphone (please complete the following information):
None.
Additional context
Nothing.
Improve the code base to be clear usage for new people
Make the app easier to test all cases
Cover all calls from the library
I spent like 1-2 hours trying to migrate the plugin using this guide but it refused to work.
But then I found the issue, this line in the migration guide is like this:
implementation 'com.canhub.cropper:android-image-cropper:${version}'
When it should be like this (just like on the README):
implementation 'com.github.CanHub:Android-Image-Cropper:${version}'
Wanted to report here so people trying to migrate don't need to pull out their hair.
Describe the bug
A user that opts to take a photo can capture a picture and upon accepting the photo (aka, tapping on the check mark) they are returned to destination that launched CropImageActivity.
What's happening is an NPE is thrown (see below) when user accepts the photo, CropImageActivity.onActivityResult is called with resultCode == RESULT_CANCELED
.
2021-02-10 09:45:14.860 6815-6815/? E/CAM_StateMachine: Failed to process event: com.android.camera.captureintent.event.EventTapOnConfirmPhotoButton@f96e55
2021-02-10 09:45:14.861 6815-6815/? E/AndroidRuntime: FATAL EXCEPTION: main Process: com.android.camera2, PID: 6815 java.lang.NullPointerException at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:890) at com.google.common.base.Optional.of(Optional.java:103) at com.android.camera.captureintent.state.StateSavingPicture.onEnter(StateSavingPicture.java:77) at com.android.camera.captureintent.stateful.StateMachineImpl.jumpToState(StateMachineImpl.java:62) at com.android.camera.captureintent.stateful.StateMachineImpl.processEvent(StateMachineImpl.java:110) at com.android.camera.captureintent.state.StateOpeningCamera$9.onClick(StateOpeningCamera.java:307) at android.view.View.performClick(View.java:7448) at android.view.View.performClickInternal(View.java:7425) at android.view.View.access$3600(View.java:810) at android.view.View$PerformClick.run(View.java:28305) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7656) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Screenshots
N/A
Smartphone (please complete the following information):
Additional context
Add any other context about the problem here.
Describe the bug
My action mode is truncate. This is due to a bug in the dependency of appcompat.
Please don't used non released dependencies to solve this issue.
Current lib dependencies version :
androidXAppCompatVersion = '1.3.0-beta01'
My workaround :
implementation ('com.github.CanHub:Android-Image-Cropper:2.2.1'){
exclude group: 'androidx.appcompat'
}
Smartphone (please complete the following information):
I set CropMaxDimensions(640, 360) in my App
and I ran some Test:
In Device with Android 9:
Image from Gallery with size 16MB can be compress to 760kb
and Image from Camera with size 5.7MB can be compress to 380kb
In Device with Android 10:
Image from Gallery with size 16MB can be compress to 760kb
but Image from Camera with size 3.5MB only compress to 3.4MB
is this possible ?
is this capable of zooming to a pixel by pixel zoom level? eg where each individual pixel is visible?
Library version
Describe the bug
The app crashes after some time on the camera screen if the One-time permission chosen.
"If the user sends your app to the background, your app can continue to access the data for a short period of time." (https://developer.android.com/training/permissions/requesting#one-time)
The app went to the background when the camera is opened.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The app shouldn't crash
Smartphone (please complete the following information):
Describe the bug
After adding implementation 'com.github.CanHub:Android-Image-Cropper:2.1.0' build failed with error /Users/oc/.gradle/caches/transforms-2/files-2.1/225e0e7423424895791e1e3386ede31a/Android-Image-Cropper-2.1.0/AndroidManifest.xml:11:5-22:15: AAPT: error: unexpected element found in .
Smartphone (please complete the following information):
Additional context
Add any other context about the problem here.
I am trying cropImageView.cropRect = myRect
then when I try cropImageView.croppedImage immediattly not getting the exact myRect area cropped bitmap.
Is your library taking some time to draw a rectangle on the image?
If yes is there any callback available so that I can know - Yeah my area is ready now I can call getCroppedImage() method on it.
Can add this to the kotlin sample module with an option to use default activity or a custom one, like
CustomActivity : CropImageActivity
This will be blocker by #34
I want to add two different request codes to the same activity but it is only giving one
public static final int PICK_IMAGE_CHOOSER_REQUEST_CODE = 200;
I cannot use the same CHOOSER on both image pickers.
Hi, i really love your project, but i see that we are still using OnActivityResult which is deprecated.
Maybe we can use this one : https://developer.android.com/reference/androidx/activity/result/contract/ActivityResultContract
I am able to crop the image and put in ImageView successfully.
But when I am using the same URI path to create a file it's throwing FileNotFoundException
.
The URI path is starting like content://..something/package name/ myfiles/...
something like this.
When I debugged I am able to see some data like NO CACHE inside the URI value.
I am pasting my code below:
Calling Method to crop:
public void onSelectImageClick() {
CropImage
.activity(null)
.setOutputCompressFormat(Bitmap.CompressFormat.JPEG)
.setGuidelines(CropImageView.Guidelines.ON)
.setFixAspectRatio(true)
.start(this);
}
Getting cropped result in onActivityResuly()
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if (resultCode == RESULT_OK) {
Glide.with(this)
.load(result.getUri())
.into(actorPic);
isImageViewAdded = true;
//handleCropResult(CropImage.getActivityResult(data))
imagePath = result.getUri();
//imagePath = CropImage.getPickImageResultUri(this, data);
//insertSingleItem(result.getUri());
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
Toast.makeText(this, "Cropping failed: " + result.getError(), Toast.LENGTH_LONG).show();
}
}
if(requestCode == CropImage.PICK_IMAGE_CHOOSER_REQUEST_CODE){
Uri imageUri = CropImage.getPickImageResultUri(AddActorsActivity.this, data);
imagePath = imageUri;
}
}
But the imageview is able to find the path and successfully update the cropped image inside it through Glide.
Expected behavior
I think the cropped Image is not caching and so it's happening like this.
This is part of the pre kotlin refactor.
To be sure we are not breaking anything in the library (public method) when refactoring into kotlin is important we have all cases usage in our sample code.
What help when someone make a library suggestion or find a bug!
This sample should call CropImage.activity(photoUri)
passing the image URI. (e.g. from camera photo taken)
Describe the bug
From Java to Kotlin we have a null case for CompressFormat.
I had this special requirement
We need to get the 4 ratios, Top left right bottom
of the selected rect and original rect
For this purpose i need to access the CropWindowHandler
variable which is private
Can it be made public or a getter method?
Issue:
When selecting the default "camera" option, app does not go to crop screen after taking photo.
Expected Behavior
Device
Android 10.
Galaxy Note 10+
implementation 'com.canhub.cropper:android-image-cropper:1.1.1'
Code used to open selector
CropImage.activity().setGuidelines(CropImageView.Guidelines.ON).setAspectRatio(1,1).start(activity);
Extra Info
I just need to change toolbar icon and text color according to my app theme.
Describe the bug
When extending CropImageActivity some methods are running null point exception.
To Reproduce
class CustomActivity : CropImageActivity {...}
cropImage()
or onBackPressed()
Expected behavior
Custom activity should work as expected
To fix this bug is import we have ability to test in the sample project.
For this, we need to add a new kotlin code that extend the activity
Is your feature request related to a problem? Please describe.
This is a specific use-case that I have. It's particularly convenient when used in conjunction with #76.
Describe the solution you'd like
The ability to disable (in XML, activity builder or via methods on the CropImageView) the ability to translate the crop window.
Describe alternatives you've considered
None.
Additional context
As with my other issue, see the PlayScore 2 app for iOS. I wonder if you can guess what app I'm working on? :)
Describe the bug : I want to upgrade to this version because I am facing issues in android 11 for Camera option . It is giving me empty black screen instead of crop preview and error code is coming file is not image . Can you please confirm which version works fine with android 11 and how to include this library in project.
A clear and concise desc
ription of what the bug is.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
A clear and concise description of what you expected to happen.
Screenshots
If applicable, add screenshots to help explain your problem.
Smartphone (please complete the following information):
Additional context
Add any other context about the problem here.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.