android - programacion - recortar fotos
Recorte personalizado de imágenes de Android (3)
Solo quiero compartir este pedazo de código que escribí. Intenté buscar una actividad de recorte personalizada, pero la mayoría de ellos lleva al valor predeterminado "com.android.camera.action.CROP" a pesar de la pregunta de recorte personalizado o actividad de recorte a mano alzada. De todos modos, acabo de hacer una para mí, y espero que les ayude a ustedes.
public class CropView extends ImageView {
Paint paint = new Paint();
private int initial_size = 300;
private static Point leftTop, rightBottom, center, previous;
private static final int DRAG= 0;
private static final int LEFT= 1;
private static final int TOP= 2;
private static final int RIGHT= 3;
private static final int BOTTOM= 4;
private int imageScaledWidth,imageScaledHeight;
// Adding parent class constructors
public CropView(Context context) {
super(context);
initCropView();
}
public CropView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
initCropView();
}
public CropView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initCropView();
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if(leftTop.equals(0, 0))
resetPoints();
canvas.drawRect(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
previous.set((int)event.getX(), (int)event.getY());
break;
case MotionEvent.ACTION_MOVE:
if(isActionInsideRectangle(event.getX(), event.getY())) {
adjustRectangle((int)event.getX(), (int)event.getY());
invalidate(); // redraw rectangle
previous.set((int)event.getX(), (int)event.getY());
}
break;
case MotionEvent.ACTION_UP:
previous = new Point();
break;
}
return true;
}
private void initCropView() {
paint.setColor(Color.YELLOW);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(5);
leftTop = new Point();
rightBottom = new Point();
center = new Point();
previous = new Point();
}
public void resetPoints() {
center.set(getWidth()/2, getHeight()/2);
leftTop.set((getWidth()-initial_size)/2,(getHeight()-initial_size)/2);
rightBottom.set(leftTop.x+initial_size, leftTop.y+initial_size);
}
private static boolean isActionInsideRectangle(float x, float y) {
int buffer = 10;
return (x>=(leftTop.x-buffer)&&x<=(rightBottom.x+buffer)&& y>=(leftTop.y-buffer)&&y<=(rightBottom.y+buffer))?true:false;
}
private boolean isInImageRange(PointF point) {
// Get image matrix values and place them in an array
float[] f = new float[9];
getImageMatrix().getValues(f);
// Calculate the scaled dimensions
imageScaledWidth = Math.round(getDrawable().getIntrinsicWidth() * f[Matrix.MSCALE_X]);
imageScaledHeight = Math.round(getDrawable().getIntrinsicHeight() * f[Matrix.MSCALE_Y]);
return (point.x>=(center.x-(imageScaledWidth/2))&&point.x<=(center.x+(imageScaledWidth/2))&&point.y>=(center.y-(imageScaledHeight/2))&&point.y<=(center.y+(imageScaledHeight/2)))?true:false;
}
private void adjustRectangle(int x, int y) {
int movement;
switch(getAffectedSide(x,y)) {
case LEFT:
movement = x-leftTop.x;
if(isInImageRange(new PointF(leftTop.x+movement,leftTop.y+movement)))
leftTop.set(leftTop.x+movement,leftTop.y+movement);
break;
case TOP:
movement = y-leftTop.y;
if(isInImageRange(new PointF(leftTop.x+movement,leftTop.y+movement)))
leftTop.set(leftTop.x+movement,leftTop.y+movement);
break;
case RIGHT:
movement = x-rightBottom.x;
if(isInImageRange(new PointF(rightBottom.x+movement,rightBottom.y+movement)))
rightBottom.set(rightBottom.x+movement,rightBottom.y+movement);
break;
case BOTTOM:
movement = y-rightBottom.y;
if(isInImageRange(new PointF(rightBottom.x+movement,rightBottom.y+movement)))
rightBottom.set(rightBottom.x+movement,rightBottom.y+movement);
break;
case DRAG:
movement = x-previous.x;
int movementY = y-previous.y;
if(isInImageRange(new PointF(leftTop.x+movement,leftTop.y+movementY)) && isInImageRange(new PointF(rightBottom.x+movement,rightBottom.y+movementY))) {
leftTop.set(leftTop.x+movement,leftTop.y+movementY);
rightBottom.set(rightBottom.x+movement,rightBottom.y+movementY);
}
break;
}
}
private static int getAffectedSide(float x, float y) {
int buffer = 10;
if(x>=(leftTop.x-buffer)&&x<=(leftTop.x+buffer))
return LEFT;
else if(y>=(leftTop.y-buffer)&&y<=(leftTop.y+buffer))
return TOP;
else if(x>=(rightBottom.x-buffer)&&x<=(rightBottom.x+buffer))
return RIGHT;
else if(y>=(rightBottom.y-buffer)&&y<=(rightBottom.y+buffer))
return BOTTOM;
else
return DRAG;
}
public byte[] getCroppedImage() {
BitmapDrawable drawable = (BitmapDrawable)getDrawable();
float x = leftTop.x-center.x+(drawable.getBitmap().getWidth()/2);
float y = leftTop.y-center.y+(drawable.getBitmap().getHeight()/2);
Bitmap cropped = Bitmap.createBitmap(drawable.getBitmap(),(int)x,(int)y,(int)rightBottom.x-(int)leftTop.x,(int)rightBottom.y-(int)leftTop.y);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
cropped.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
}
}
Lo que hice fue extender el ImageView y agregar poderes de recorte. Es muy facil de usar. Una vez que la clase está guardada, solo úsala en el diseño como este.
<"your package name".CropView
android:id="@+id/image_preview"
android:layout_width="fill_parent"
android:layout_height="match_parent" />
¡Eso es! ¡Espero eso ayude! Si tiene algún problema, no dude en preguntar :)
Deberías intentarlo:
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.crop_layout);
myCropView = new CropView(this);
Uri imageUri = getIntent().getExtras().getParcelable("path");
b = (BitmapDrawable) BitmapDrawable.createFromPath(imageUri.getPath());
myCropView.setImageURI(imageUri);
}
(Tomado de una edición a su pregunta.)
Encontré una biblioteca que admite esto: SimpleCropView de https://android-arsenal.com/details/1/2366 . En general, no lo recomendaría, su rendimiento está lejos de las aplicaciones nativas de recorte de Android.
He intentado usarlo, y mis pensamientos son:
Realmente sencillo de implementar en su aplicación, me llevó aproximadamente 5 minutos obtener la funcionalidad de recorte y rotación que funciona con mi aplicación existente
El cambio de tamaño del área de cultivo es dolorosamente lento, no me gustaría que mi usuario lo vea.
ACTUALIZACIÓN: De hecho, he encontrado una solución realmente buena como jdamcd / android-crop en Github: https://github.com/jdamcd/android-crop Resumen:
Muy simple de usar en tu aplicación
Rápido, ya que utiliza el código de la aplicación de galería nativa.
Personalizable, si quieres pasar un rato jugando con él. De forma predeterminada, le proporciona una Actividad en la que realiza el recorte. Si desea integrarlo en su propia actividad, tomará un poco más de tiempo. (Para mi proyecto me hubiera gustado integrarlo, y lo haré en el futuro, pero por ahora una actividad separada es suficiente).
Espero que esto proporcione una idea!
gracias thehippo ... pero he resuelto encontrar la vista por el diseño
Uri imageUri = getIntent().getExtras().getParcelable("path");
b = (BitmapDrawable) BitmapDrawable.createFromPath(getRealPathFromURI(imageUri));
myCropView = (CropView) findViewById(R.id.image_preview);
myCropView.setBackground(b);
Pero ahora no puedo manejar el evento táctil. El rectángulo se queda quieto incluso si toco la pantalla ...
EDIT: ok, he hecho que funcione. Pero ahora, el rectángulo se mueve solo dentro de un área más pequeña, no en toda la imagen. Supongo que hay algo mal aquí.
private boolean isInImageRange(PointF point) {
// Get image matrix values and place them in an array
float[] f = new float[9];
getImageMatrix().getValues(f);
// Calculate the scaled dimensions
imageScaledWidth = Math.round(getBackground().getIntrinsicWidth() * f[Matrix.MSCALE_X]);
imageScaledHeight = Math.round(getBackground().getIntrinsicHeight() * f[Matrix.MSCALE_Y]);
return (point.x>=(center.x-(imageScaledWidth/2))&&point.x<=(center.x+(imageScaledWidth/2))&&point.y>=(center.y-(imageScaledHeight/2))&&point.y<=(center.y+(imageScaledHeight/2)))?true:false;
}
He hecho un pequeño cambio para hacer funcionar el código: getBackground () en lugar de getDrawable
EDITAR 2: OK lo tengo, estaba haciendo esto de manera incorrecta. Tu código es bueno. Para configurar la imagen, estaba usando view.seBackground () ... en lugar de view.setImageDrawable (). Ahora todo funciona. Tal vez solo compruebe si es posible crear un área más grande que dispare la escala del rectángulo