Reputation: 646
I want to do cropping of image i found some pretty useful ones but somehow is like lacking of the darken the unselected areas so I wondering do anyone know how? or lead me to the right direction? The online tutorial i found shows that is will darken the selected area but when I use it, it won't. Please help me thanks alot and sorry for my bad command of english.
Links to the tutorial I use.
I want it to be something like this.
editButton.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent goEdit;
goEdit = new Intent(PreviewActivity.this, CropImage.class);
goEdit.putExtra("image-path", path);
goEdit.putExtra("scale", true);
goEdit.putExtra("fileName", nameFromPath);
//finish();
checkEdit = true;
startActivityForResult(goEdit,0);
}
});
EDIT I use this button listener to call into the cropImage file by calling to the class CropImage activity. This is a custom intent not the crop feature inside android but I think is the copy of it so that make it support for all versions but when I call into it the selected area isnt brighten and I donno where is the problem can anyone guide me? Thanks This is the library I'm using drioid4you crop image
Upvotes: 40
Views: 165674
Reputation: 740
I just recently finished this one for my own project. Please customize it to your needs. You can also resize with 4 edges and 4 corners also! I'm not good at English but I did my best to add comments to the code. Please read them, they might be helpful.
...
XML
<your_package_name.CV4
android:id="@+id/cv4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/cropBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Crop"/>
<ImageView
android:id="@+id/croppedImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
code in activity or fragment
cropBtn.setOnClickListener {
val x = cv4.test()
croppedImage.setImageBitmap(x)
}
Mani Custom View Code
package your.package.name
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.voice.translator.app.speak.to.world.camerax.R
import kotlin.math.max
import kotlin.math.min
class CV4 @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
// onMeasure will be called before onSizeChanged and onDraw
// please see the View lifecycle for more details
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
screenWidth = MeasureSpec.getSize(widthMeasureSpec)
imageWidth = screenWidth
imageHeight = ((screenWidth.toFloat() / src.width) * src.height).toInt()
setMeasuredDimension(screenWidth, imageHeight)
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
val desiredWidthInPx = imageWidth
val derivedHeightInPx = (desiredWidthInPx / aspectRatio).toInt()
output = Bitmap.createScaledBitmap(src, desiredWidthInPx, derivedHeightInPx, true)
rectF2 = RectF(0f, 0f, imageWidth.toFloat(), derivedHeightInPx.toFloat())
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
parent.requestDisallowInterceptTouchEvent(true)
canvas?.apply {
// background image under overlay
drawBitmap(output, 0f, 0f, null)
// dark overlay
drawRect(rectF2, rectPaint2)
// clip rect same as movable rect. This will hide everything outside
clipRect(rectF)
// visible clear image covered by clip rect
drawBitmap(output, 0f, 0f, null)
// movable rect
drawRoundRect(rectF, 10f, 10f, rectPaint)
}
}
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent?): Boolean {
if (event != null) {
motionX = event.x
motionY = event.y
when (event.action) {
MotionEvent.ACTION_MOVE -> moveMove()
MotionEvent.ACTION_DOWN -> moveDown()
MotionEvent.ACTION_UP -> moveUp()
}
}
return true
}
private fun moveMove() {
//moving the whole rect
if (c5) {
if (pr < screenWidth && motionX > plx) {
pr = min(r + (motionX - plx), screenWidth.toFloat())
pl = min(l + (motionX - plx), screenWidth.toFloat() - (r - l))
}
if (pl > 0 && motionX < plx) {
pr = max(r - (plx - motionX), 0f + (r - l))
pl = max(l - (plx - motionX), 0f)
}
if (pb < imageHeight && motionY > pty) {
pb = min(b + (motionY - pty), imageHeight.toFloat())
pt = min(t + (motionY - pty), imageHeight.toFloat() - (b - t))
}
if (pt > 0 && motionY < pty) {
pb = max(b - (pty - motionY), 0f + (b - t))
pt = max(t - (pty - motionY), 0f)
}
rectF.set(pl + 5, pt + 5, pr - 5, pb - 5)
invalidate()
}
// moving while holding corners
if (c6) {
if (motionX > 0 && motionX < (pr - 100)) pl = motionX
if (motionY > 0 && motionY < (pb - 100)) pt = motionY
}
if (c7) {
if (motionY > 0 && motionY < (pb - 100)) pt = motionY
if (motionX > (pl + 100) && motionX < screenWidth) pr = motionX
}
if (c8) {
if (motionX > (pl + 100) && motionX < screenWidth) pr = motionX
if (motionY > (pt + 100) && motionY < imageHeight) pb = motionY
}
if (c9) {
if (motionX > 0 && motionX < (pr - 100)) pl = motionX
if (motionY > (pt + 100) && motionY < imageHeight) pb = motionY
}
// For moving the edge
if (c1) if (motionX > 0 && motionX < (pr - 100)) pl = motionX
if (c2) if (motionY > 0 && motionY < (pb - 100)) pt = motionY
if (c3) if (motionX > (pl + 100) && motionX < screenWidth) pr = motionX
if (c4) if (motionY > (pt + 100) && motionY < imageHeight) pb = motionY
rectF.set(pl + 5, pt + 5, pr - 5, pb - 5)
invalidate()
}
private fun moveDown() {
if (motionX > (pl + rng) && motionX < (pr - rng) && motionY > (pt + rng) && motionY < (pb - rng)) {
c5 = true
l = pl
t = pt
r = pr
b = pb
if (motionY >= 0 && motionY <= imageHeight) pty = motionY
if (motionX >= 0 && motionX <= screenWidth) plx = motionX
invalidate()
return
}
if (motionX in pl - rng..pl + rng && motionY in pt - rng..pt + rng) {
c6 = true
invalidate()
return
}
if (motionY in pt - rng..pt + rng && motionX in pr - rng..pr + rng) {
c7 = true
invalidate()
return
}
if (motionX in pr - rng..pr + rng && motionY in pb - rng..pb + rng) {
c8 = true
invalidate()
return
}
if (motionY in pb - rng..pb + rng && motionX in pl - rng..pl + rng) {
c9 = true
invalidate()
return
}
if (motionX > (pl - rng) && motionX < (pl + rng) && motionY > pt && motionY < pb) {
c1 = true
invalidate()
return
}
if (motionY > (pt - rng) && motionY < (pt + rng) && motionX > pl && motionX < pr) {
c2 = true
invalidate()
return
}
if (motionX > (pr - rng) && motionX < (pr + rng) && motionY > pt && motionY < pb) {
c3 = true
invalidate()
return
}
if (motionY > (pb - rng) && motionY < (pb + rng) && motionX > pl && motionX < pr) {
c4 = true
invalidate()
return
}
invalidate()
}
private fun moveUp() {
c1 = false
c2 = false
c3 = false
c4 = false
c5 = false
c6 = false
c7 = false
c8 = false
c9 = false
invalidate()
}
// pass bitmap image
private val src: Bitmap = BitmapFactory.decodeResource(resources, R.drawable.mountain)
private var screenWidth = 0
private var imageWidth = 0
private var imageHeight = 0
private val aspectRatio: Float = src.width / src.height.toFloat()
//get the bitmap from test():Bitmap? function
private lateinit var output: Bitmap
fun test(): Bitmap? {
val cropWidth: Float = (pr - pl)
val cropHeight: Float = (pb - pt)
invalidate()
//returning the bitmap
return Bitmap.createBitmap(
output,
pl.toInt(),
pt.toInt(),
cropWidth.toInt(),
cropHeight.toInt()
)
}
private var motionX = 0f
private var motionY = 0f
private var rng = 40f // Touch range for the 4 side and 4 corners of the rect
// p for point and l=left t=top r=right b=bottom
private var pl = 100f
private var plx = 100f //hold motionX value from moveDown() function
private var pt = 100f
private var pty = 100f //hold motionY value from moveDown() function
private var pr = 300f
private var pb = 400f
//hold left,top,right,bottom value from moveDown() function
private var l = 0f
private var t = 0f
private var r = 0f
private var b = 0f
// check user touch Down on rect edges, corners or inside
//edges point
private var c1 = false
private var c2 = false
private var c3 = false
private var c4 = false
private var c5 = false // for inside selection to move the whole rect
//corners point
private var c6 = false
private var c7 = false
private var c8 = false
private var c9 = false
// resizable rect
private var rectF = RectF(pl + 5, pt + 5, pr - 5, pb - 5)
private val rectPaint = Paint().apply {
style = Paint.Style.STROKE
strokeWidth = 10f
color = Color.YELLOW
}
// dark overlay rect
private val foregroundArcColor =
context.resources?.getColor(R.color.custom3, null) ?: Color.GRAY
private var rectF2 = RectF(0f, 0f, screenWidth.toFloat(), imageHeight.toFloat())
private val rectPaint2 = Paint().apply {
style = Paint.Style.FILL
color = foregroundArcColor
}
}
Upvotes: 0
Reputation: 79
I made a really cool library, try this out. this is really smooth and easy to use.
https://github.com/TakuSemba/CropMe
Upvotes: 3
Reputation: 2219
This library: Android-Image-Cropper is very powerful to CropImages. It has 3,731 stars on github at this time.
You will crop your images with a few lines of code.
1 - Add the dependecies into buid.gradle (Module: app)
compile 'com.theartofdev.edmodo:android-image-cropper:2.7.+'
2 - Add the permissions into AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3 - Add CropImageActivity into AndroidManifest.xml
<activity android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
android:theme="@style/Base.Theme.AppCompat"/>
4 - Start the activity with one of the cases below, depending on your requirements.
// start picker to get image for cropping and then use the image in cropping activity
CropImage.activity()
.setGuidelines(CropImageView.Guidelines.ON)
.start(this);
// start cropping activity for pre-acquired image saved on the device
CropImage.activity(imageUri)
.start(this);
// for fragment (DO NOT use `getActivity()`)
CropImage.activity()
.start(getContext(), this);
5 - Get the result in onActivityResult
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if (resultCode == RESULT_OK) {
Uri resultUri = result.getUri();
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
Exception error = result.getError();
}
}
}
You can do several customizations, as set the Aspect Ratio or the shape to RECTANGLE, OVAL and a lot more.
Upvotes: 11
Reputation: 2173
Can you use default android Crop functionality?
Here is my code
private void performCrop(Uri picUri) {
try {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
// indicate image type and Uri
cropIntent.setDataAndType(picUri, "image/*");
// set crop properties here
cropIntent.putExtra("crop", true);
// indicate aspect of desired crop
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1);
// indicate output X and Y
cropIntent.putExtra("outputX", 128);
cropIntent.putExtra("outputY", 128);
// retrieve data on return
cropIntent.putExtra("return-data", true);
// start the activity - we handle returning in onActivityResult
startActivityForResult(cropIntent, PIC_CROP);
}
// respond to users whose devices do not support the crop action
catch (ActivityNotFoundException anfe) {
// display an error message
String errorMessage = "Whoops - your device doesn't support the crop action!";
Toast toast = Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT);
toast.show();
}
}
declare:
final int PIC_CROP = 1;
at top.
In onActivity result method, writ following code:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PIC_CROP) {
if (data != null) {
// get the returned data
Bundle extras = data.getExtras();
// get the cropped bitmap
Bitmap selectedBitmap = extras.getParcelable("data");
imgView.setImageBitmap(selectedBitmap);
}
}
}
It is pretty easy for me to implement and also shows darken areas.
Upvotes: 53
Reputation: 1785
hope you are doing well.
you can use my code to crop image.you just have to make a class and use this class into your XMl
and java
classes.
Crop image.
you can crop your selected image into circle and square into many of option.
hope fully it will works for you.because this is totally manageable for you and you can change it according to you.
enjoy your work :)
Upvotes: 2