A small partner of the company writes that the picture can be cropped at any rate. I think it's very useful. Simply record it here and it will definitely be used later.
public class Seniorcropimageview extends ImageView implements Scalegesturedetector.onscalegesturelistener,
View.onlayoutchangelistener {/* For drawing Color field start/private static final int line_color = Color.White;
private static final int outer_mask_color = COLOR.ARGB (191, 0, 0, 0);
private static final int line_width_in_dp = 1;
Private final float[] mmatrixvalues = new FLOAT[9];
protected Matrix Msupportmatrix;
protected Scalegesturedetector Mscalegesturedetector;
/* For drawing Color Field end */protected Paint mpaint;
/* * wide ratio/protected float mratio = 1.0f;
protected RECTF Mcroprect;
Rectfpadding is to adapt to product requirements, to the crop box mcroprect set padding-chenglin April 18, 2016 protected float rectfpadding = 0;
protected int mlastx;
protected int mlasty;
protected OPERATION moperation;
Private Onbitmaploadlistener ibitmaploading = null;
Private Boolean menabledrawcropwidget = true;
/* For scale and drag * * Private Matrix Mbasematrix;
Private Matrix Mdrawmatrix; Private acceleratedecelerateinterpolator sinterpolator = new Acceleratedecelerateinterpolator ();
Private Path MPath;
private int mlinewidth;
private float Mscalemax = 3.0f;
Private RECTF Mboundaryrect;
private int mrotation = 0;
private int mimagewidth;
private int mimageheight;
private int mdisplayw;
private int mdisplayh;
Public Seniorcropimageview {This (context, NULL);
Public Seniorcropimageview (context, AttributeSet attrs) {This (context, attrs, 0); Seniorcropimageview (context, AttributeSet attrs, int defstyleattr) {Super (context, Attrs, defstyleattr
);
if (attrs!= null) {TypedArray a = Context.obtainstyledattributes (Attrs, r.styleable.life_cropimage);
Mratio = A.getfloat (R.styleable.life_cropimage_life_crop_ratio, 1.0f);
A.recycle ();
Init (); public static void Decodeimageforcropping (final String path, final Idecodecallback callback) {New Thread (new Runnable () {@Override public void run () {int rotation= 0;
Read the rotation try {exifinterface exif = new Exifinterface (path) in EXIF;
final int rotate = Exif.getattributeint (exifinterface.tag_orientation, exifinterface.orientation_undefined);
Switch (rotate) {case ExifInterface.ORIENTATION_ROTATE_90:rotation = 90;
Break
Case ExifInterface.ORIENTATION_ROTATE_180:rotation = 180;
Break
Case ExifInterface.ORIENTATION_ROTATE_270:rotation = 270;
Break
} catch (IOException e) {e.printstacktrace ();
Final Bitmapfactory.options Options = new Bitmapfactory.options ();
Options.injustdecodebounds = true;
Bitmapfactory.decodefile (path, options);
Final int texturelimit = Getmaxtexturesize ();
int scale = 1;
while (Options.outwidth/scale >= texturelimit) {scale *= 2;
while (Options.outheight/scale >= texturelimit) {scale *= 2;
} options.insamplesize = scale;
Options.injustdecodebounds = false;
Bitmap Bitmap = null;
try {bitmap = bitmapfactory.decodefile (path, options); catch (OutOfMemoryError E) {e.printstacktrace ();
Final Bitmap bimapdecoded = Bitmap;
if (bimapdecoded = = null) {return;
} if (callback!= null) {callback.ondecoded (rotation, bimapdecoded);
}}). Start ();
private static int getmaxtexturesize () {EGL10 EGL = (EGL10) Eglcontext.getegl (); Egldisplay display = Egl.eglgetdisplay (EGL10.
Egl_default_display);
Initialise int[] Version = new INT[2];
Egl.eglinitialize (display, version);
Query total number of configurations int[] totalconfigurations = new Int[1];
Egl.eglgetconfigs (display, NULL, 0, totalconfigurations);
Query actual list configurations eglconfig[] configurationslist = new Eglconfig[totalconfigurations[0]];
Egl.eglgetconfigs (Display, configurationslist, totalconfigurations[0], totalconfigurations);
int[] texturesize = new Int[1];
int maximumtexturesize = 0; Iterate through the configurations to located the maximum size for (int i = 0; i < texture 0]; i++) {//need to check for Width since OpenGL textures are always squared egl.eglgetconfigattrib (display, configurationslist[i], EGL10.
Egl_max_pbuffer_width, texturesize); Keep track of the maximum texture size if (Maximumtexturesize < texturesize[0]) {maximumtexturesize = Texturesize
[0];
}//Release egl.eglterminate (display);
return maximumtexturesize; @Override public void Onlayoutchange (View v., int left, int. top, int right, int bottom, int oldleft, int oldtop, int ol
dright, int oldbottom) {mdisplayw = Right-left;
Mdisplayh = Bottom-top; if (getdrawable ()!= null && (bitmapdrawable) getdrawable ()). Getbitmap ()!= null) {calculateproperties ((Bitma
pdrawable) getdrawable ()). Getbitmap ());
} private void Init () {mscalegesturedetector = new Scalegesturedetector (GetContext (), this);
Mbasematrix = new Matrix ();
Mdrawmatrix = new Matrix ();
Msupportmatrix = new Matrix ();
Mlinewidth = (int) diptopixels (LINE_WIDTH_IN_DP);
Mpaint = new Paint (); Represents the first solid segment length DashonwidtH, the first virtual segment length dashoffwidth MPath = new Path ();
Mcroprect = new RECTF ();
Mboundaryrect = new RECTF ();
Setscaletype (Scaletype.matrix);
Setclickable (TRUE); Private float diptopixels (float dip) {return typedvalue.applydimension (Typedvalue.complex_unit_dip, Dip, GetResource
S (). Getdisplaymetrics ());
} @Override protected void Onattachedtowindow () {Super.onattachedtowindow ();
Addonlayoutchangelistener (this);
} @Override protected void Ondetachedfromwindow () {Super.ondetachedfromwindow ();
Removeonlayoutchangelistener (this); /** * Sets the cropping ratio of the picture, such as 3:4 0.75 * * @param ratio/public void setcropratio (final float ratio) {if (Mratio = = ratio
) {return;
} mratio = ratio;
After selecting the proportions, restore the rotation angle//setimagerotation (0);
if (getdrawable () = = null) {return;
} calculateproperties ((bitmapdrawable) getdrawable ()). Getbitmap ());
Postinvalidate ();
public void setimagerotation (int rotation) {if (mrotation = = rotation) {return;
} mrotation = rotation; if (Getdrawable () = = null) {return;
} calculateproperties ((bitmapdrawable) getdrawable ()). Getbitmap ());
Postinvalidate ();
public void setcroprectpadding (float padding) {rectfpadding = padding;
public void setImagePath (final String path) {if (Textutils.isempty (path)) {return;
} if (ibitmaploading!= null) {Ibitmaploading.onloadprepare (); Decodeimageforcropping (Path, new Idecodecallback () {@Override public void ondecoded (final int rotation, final Bitmap
Bitmap) {post (new Runnable () {@Override public void run () {mrotation = rotation;
Setimagebitmap (bitmap);
if (ibitmaploading!= null) {ibitmaploading.onloadfinish ();
}
}
});
}
});
@Override public void Setimagebitmap (Bitmap bm) {calculateproperties (BM);
Super.setimagebitmap (BM);
public void Setbitmaploadinglistener (Onbitmaploadlistener ibitmapload) {ibitmaploading = Ibitmapload;
} protected void Calculateproperties (Bitmap bm) {msupportmatrix.reset ();
Mbasematrix.reset (); int widthsize = MDiSplayw;
int heightsize = Mdisplayh;
Generatecroprect (Widthsize, heightsize);
Mimagewidth = Bm.getwidth ();
Mimageheight = Bm.getheight ();
Final Boolean rotated = isimagerotated (); Final int bitmapwidth = rotated?
Mimageheight:mimagewidth; Final int bitmapheight = rotated?
Mimagewidth:mimageheight;
Mboundaryrect.set (0, 0, bitmapwidth, bitmapheight);
Final float Widthscale = mcroprect.width ()/bitmapwidth;
Final float Heightscale = mcroprect.height ()/bitmapheight;
Final float scale = Math.max (Widthscale, Heightscale);
Final float scaledheight = scale * bitmapheight;
Final float scaledwidth = scale * BITMAPWIDTH;
Move to the center point final int translatex = (int) (Mcroprect.left + mcroprect.width ()/2-SCALEDWIDTH/2);
Final int translatey = (int) (Mcroprect.top + mcroprect.height ()/2-SCALEDHEIGHT/2);
Mbasematrix.setscale (scale, scale);
Mbasematrix.posttranslate (Translatex, Translatey);
Mbasematrix.maprect (Mboundaryrect);
Setimagematrix (Getdrawmatrix ()); } PrivaTe boolean isimagerotated () {return (mrotation% 360) = = 90) | |
((mrotation% 360) = = 270); } private void Generatecroprect (int boundarywidth, int boundaryheight) {//rectfpadding is adapted to product requirements,
Set the clipping box mcroprect padding-chenglin April 18, 2016 boundarywidth = boundarywidth-(int) (rectfpadding * 2);
Boundaryheight = boundaryheight-(int) (rectfpadding * 2);
int left;
int top;
int right;
int bottom;
Boolean vertical;
Width/height in proportion, the description of the cropping box is "vertical" vertical = (float) boundarywidth/boundaryheight > mratio;
Final int recth = (int) (boundarywidth/mratio);
Final int rectw = (int) (boundaryheight * mratio);
if (vertical) {left = (BOUNDARYWIDTH-RECTW)/2;
top = 0;
right = (boundarywidth + rectw)/2;
bottom = Boundaryheight;
else {left = 0;
top = (BOUNDARYHEIGHT-RECTH)/2;
right = Boundarywidth;
Bottom = (boundaryheight + recth)/2; //rectfpadding is to adapt to product requirements, to the crop box mcroprect set padding-chenglin April 18, 2016 Mcroprect.set (left + rectfpadding, top + RECTFP adding,Right + rectfpadding, bottom + rectfpadding);
} @Override protected void OnDraw (Canvas Canvas) {Super.ondraw (Canvas);
if (!menabledrawcropwidget) {return;
} if (getdrawable () = = null) {return;
} mpaint.reset ();
Mpaint.setantialias (TRUE);
Mpaint.setcolor (Line_color);
Mpaint.setstrokewidth (Mlinewidth);
Mpaint.setstyle (Paint.Style.STROKE);
Mpath.reset ();
Upper Mpath.moveto (Mcroprect.left, mcroprect.top);
Mpath.lineto (Mcroprect.right, mcroprect.top);
Left Mpath.moveto (Mcroprect.left, mcroprect.top);
Mpath.lineto (Mcroprect.left, Mcroprect.bottom);
Right Mpath.moveto (mcroprect.right, mcroprect.top);
Mpath.lineto (Mcroprect.right, Mcroprect.bottom);
Lower Mpath.moveto (Mcroprect.right, Mcroprect.bottom);
Mpath.lineto (Mcroprect.left, Mcroprect.bottom);
Canvas.drawpath (MPath, mpaint);
Draw the outer shadow part Mpaint.reset ();
Mpaint.setantialias (TRUE);
Mpaint.setcolor (Color.parsecolor ("#B3333333"));
Mpaint.setstyle (Paint.Style.FILL); The following four rectangles are decorative, which is the four shadows around the clipping box final int LinEoffset = Mlinewidth;
if (Mcroprect.top > 0) {canvas.drawrect (0, 0, getmeasuredwidth (), Mcroprect.top-lineoffset, mpaint); } if (Mcroprect.left > 0) {canvas.drawrect (mcroprect.top-lineoffset-rectfpadding, Rectfpadding-lineoffset, MCr
Oprect.left-lineoffset, Mcroprect.bottom + Lineoffset, mpaint); } if (Mcroprect.right < Getmeasuredwidth ()) {Canvas.drawrect (mcroprect.right + lineoffset, MCROPRECT.TOP-LINEOFFSE
T, Getmeasuredwidth (), Mcroprect.bottom + Lineoffset, mpaint); } if (Mcroprect.bottom < Getmeasuredheight ()) {canvas.drawrect (0, Mcroprect.bottom + lineoffset, Getmeasuredwidth (),
Getmeasuredheight (), mpaint); } public boolean ontouchevent (motionevent ev) {if (Ev.getpointercount () > 1) {moperation = OPERATION.
SCALE;
return mscalegesturedetector.ontouchevent (EV);
Final int action = ev.getactionmasked ();
Final int x = (int) ev.getx ();
Final int y = (int) ev.gety (); Switch (action) {Case MotionEvent.ACTION_DOWN:mOperation = OPERATION.
DRAG;
MLASTX = x;
Mlasty = y;
Break Case MotionEvent.ACTION_MOVE:if (moperation = = OPERATION.
DRAG) {int deltax = X-MLASTX;
int deltay = Y-mlasty;
RECTF boundary = Getdrawboundary (Getdrawmatrix ());
if (Boundary.left + deltax > Mcroprect.left) {deltax = (int) (mcroprect.left-boundary.left);
else if (boundary.right + DeltaX < mcroprect.right) {deltax = (int) (mcroprect.right-boundary.right);
} if (Boundary.top + DeltaY > mcroprect.top) {deltay = (int) (mcroprect.top-boundary.top);
else if (Boundary.bottom + DeltaY < mcroprect.bottom) {DeltaY = (int) (mcroprect.bottom-boundary.bottom);
} msupportmatrix.posttranslate (DeltaX, DeltaY);
Setimagematrix (Getdrawmatrix ());
MLASTX = x;
Mlasty = y;
} break;
Case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_POINTER_UP:case MotionEvent.ACTION_UP:mLastX = 0;
mlasty = 0;
Moperation = null;
Break
return super.ontouchevent (EV);
Public Bitmap Getoriginbitmap () {Bitmapdrawable drawable = (bitmapdrawable) getdrawable (); return drawable = null?
Null:drawable.getBitmap ();
/** * Save Picture as Bitmap/public Bitmap Savecrop () throws OutOfMemoryError {if (getdrawable () = null) {return null;
} Bitmap origin = Getoriginbitmap ();
Matrix Drawmatrix = Getdrawmatrix ();
Reverse the matrix matrices inverse = the new matrix ();
Drawmatrix.invert (inverse);
The cropping box corresponds to the original image up RECTF cropmapped = new RECTF ();
Inverse.maprect (cropmapped, mcroprect);
Clampcroprect (cropmapped, Origin.getwidth (), Origin.getheight ());
If a rotation is generated, a rotation matrix rotationm = new Matrix () is required.
if (mrotation% 360!= 0) {rotationm.postrotate (mrotation, Origin.getwidth ()/2, Origin.getheight ()/2); } Bitmap cropped = Bitmap.createbitmap (origin, (int) cropmapped.left, (int) cropmapped.top, (int) cropmapped.width (), (
int) cropmapped.height (), rotationm, true);
return cropped; } private void Clampcroprect (RECTF croprect, int borderw, int borderh) {if (Croprect.left < 0) {CRoprect.left = 0;
} if (Croprect.top < 0) {croprect.top = 0;
} if (Croprect.right > Borderw) {croprect.right = Borderw;
} if (Croprect.bottom > Borderh) {croprect.bottom = Borderh;
@Override public boolean Onscale (Scalegesturedetector detector) {Float scale = detector.getscalefactor ();
if (scale = = 1.0f) {return true;
Final float Currentscale = Getscale (Msupportmatrix);
Final float CenterX = Detector.getfocusx ();
Final float centery = Detector.getfocusy (); if (Currentscale <= 1.0f && Scale < 1.0f) | | (Currentscale >= mscalemax && scale > 1.0f))
{return true;
} if (Currentscale * Scale < 1.0f) {scale = 1.0f/currentscale;
else if (Currentscale * scale > Mscalemax) {scale = Mscalemax/currentscale;
} msupportmatrix.postscale (scale, scale, CenterX, centery);
RECTF boundary = Getdrawboundary (Getdrawmatrix ());
float Translatex = 0; if (Boundary.left > Mcroprect.left) {Translatex = MCROPRECT.LEft-boundary.left;
else if (Boundary.right < mcroprect.right) {Translatex = Mcroprect.right-boundary.right;
} log.d ("scale", "x==>" + Translatex);
float Translatey = 0;
if (Boundary.top > Mcroprect.top) {translatey = Mcroprect.top-boundary.top;
else if (Boundary.bottom < mcroprect.bottom) {Translatey = Mcroprect.bottom-boundary.bottom;
} msupportmatrix.posttranslate (Translatex, Translatey);
Setimagematrix (Getdrawmatrix ());
return true;
} protected Matrix Getdrawmatrix () {mdrawmatrix.reset ();
if (mrotation% 360!= 0) {Final Boolean rotated = isimagerotated (); Final int width = rotated?
Mimageheight:mimagewidth; Final int height = rotated?
Mimagewidth:mimageheight;
Mdrawmatrix.postrotate (Mrotation, MIMAGEWIDTH/2, MIMAGEHEIGHT/2);
if (rotated) {final int translatex = (width-mimagewidth)/2;
Final int translatey = (height-mimageheight)/2;
Mdrawmatrix.posttranslate (Translatex, Translatey); }} Mdrawmatrix.postconcat(Mbasematrix);
Mdrawmatrix.postconcat (Msupportmatrix);
return Mdrawmatrix;
@Override public boolean Onscalebegin (Scalegesturedetector detector) {return true; @Override public void Onscaleend (Scalegesturedetector detector) {final float Currentscale = Getscale (Msupportmatrix)
;
if (Currentscale < 1.0f) {LOG.E ("Onscaleend", "currentscale==>" + Currentscale);
RECTF boundary = Getdrawboundary (Getdrawmatrix ());
Post (new Animatedzoomrunnable (Currentscale, 1.0f, Boundary.centerx (), Boundary.centery ()));
} protected RECTF getdrawboundary (Matrix matrix) {drawable drawable = getdrawable ();
if (drawable = = null) {return mboundaryrect;
Final int bitmapwidth = Drawable.getintrinsicwidth ();
Final int bitmapheight = Drawable.getintrinsicheight ();
Mboundaryrect.set (0, 0, bitmapwidth, bitmapheight);
Matrix.maprect (Mboundaryrect);
return mboundaryrect; public float Getscale (matrix matrix) {return (float) math.sqrt (float) Math.pow (GetValue matrix, Matrix.mscale_x), 2 + (float) Math.pow (GetValue (Matrix, matrix.mskew_y), 2)); /** * Helper Method "unpacks" a Matrix and returns the required value * * @param matrix-matrix to unpack * @ param Whichvalue-which value from matrix.m* to return * @return float-returned value */private float GetValue (matr
IX Matrix, int whichvalue) {matrix.getvalues (mmatrixvalues);
return Mmatrixvalues[whichvalue];
public void Enabledrawcropwidget (Boolean enable) {Menabledrawcropwidget = enable; } protected enum OPERATION {DRAG, SCALE} public enum Type {center_crop, center_inside} public interface Idecode
Callback {void ondecoded (final int rotation, final Bitmap Bitmap);
//setimagepath This method takes time and needs to display a progress bar, which listens to the public interface Onbitmaploadlistener {void Onloadprepare ();
void Onloadfinish ();
Private class Animatedzoomrunnable implements Runnable {private final float mfocalx, mfocaly;
Private final long mstarttime;
Private final float mzoomstart, mzoomend; PublIC animatedzoomrunnable (final float currentzoom, final float targetzoom, final float focalx, final float focaly) {Mfoca
LX = Focalx;
Mfocaly = Focaly;
Mstarttime = System.currenttimemillis ();
Mzoomstart = Currentzoom;
Mzoomend = Targetzoom;
@Override public void Run () {Float t = interpolate ();
Float scale = Mzoomstart + T * (Mzoomend-mzoomstart);
float Deltascale = Scale/getscale (Msupportmatrix);
Msupportmatrix.postscale (Deltascale, Deltascale, Mfocalx, mfocaly);
Setimagematrix (Getdrawmatrix ());
We Haven ' t hit our target scale yet, so post ourselves again if (T < 1f) {postonanimation (this);
} private float interpolate () {Float T = 1f * (System.currenttimemillis ()-mstarttime)/200;
t = math.min (1f, T);
t = sinterpolator.getinterpolation (t);
return t; }} <declare-styleable Name= "Life_cropimage" > <attr name= "life_crop_ratio" format= "float"/> <attr n Ame= "Life_crop_scale_type" format= "enum" > <enum name= "Life_center_"Crop "value=" 0 "/> <enum name=" Life_center_inside "value=" 1 "/> </attr> </declare-styleable>
The above is a small set of Android for everyone to cut the picture code to share any proportion, I hope to help you