Android Image clipping function implementation code _android

Source: Internet
Author: User
Tags gety

In Android applications, image clipping is also a feature that is often used. The Android system can be cropped with an implicit intent to invoke the system application. But doing so may have different effects on different phones, and even more bizarre problems on some exotic phones, so calling system features for image clipping is not a good choice for us in many cases. This is what we need to do to achieve this cutting function.

Functional analysis

To complete the image clipping function, we need to know what the image clipping function. Before the picture is cropped, we need to have a box indicating the size of the style we need to crop. The size and position of the picture may not be what we expected, so we need to move, zoom, and so on. After determining the position and size, we need to actually crop the picture and save the cropped picture for use. That is to say, you need to implement the image clipping function after the following:

1. Display indicator box
2. Picture moving and zooming
3. Picture cropping and saving

The final effect is shown as follows:

function realization

Show Indicator box

There are a number of ways to implement an indicator box like the one shown above, which is implemented by using a custom drawable as the background of the view, and then overwriting the view on the original picture as the indicator box. In order to meet more requirements to a certain extent, we let the indicator box be set to a rectangle or to a circle, and the color of the shaded area can also be set.
To draw a layer as indicated, we can split it into two halves, turn it into two closed path, draw the translucent overlay, and then crop a hole in the middle. Obviously, considering that the shape of the hole is not fixed, the way to cut it is much simpler than splitting it into two closed path.
Canvas's Canvas.clippath (Path, region.op); method, you can crop the canvas, you can easily get such an indicator box. However, Canvas's Clippath cropped curve graphics will be jagged, I have not been able to remove the sawtooth, so I have to give up this method. The results are then implemented using the Paint paint.setxfermode (new Porterduffxfermode (mode)) method.
The Android 4.4 path adds the ability to crop, and we can use the path Path.op (path, Path.op) method to crop the path to the shape we need to draw, which is more efficient.

The core code for the drawable of the indicator box is as follows:

@Override public void Draw (@NonNull Canvas Canvas) {int cwidth=canvas.getwidth ();
 int Cheight=canvas.getheight ();
 if (rect==null) {rect=new rect (CWIDTH/2-WIDTH/2,CHEIGHT/2-HEIGHT/2,CWIDTH/2+WIDTH/2,CHEIGHT/2+HEIGHT/2);
 } canvas.drawcolor (Color.transparent);
 Path path=new path ();
 Path.addrect (0,0,cwidth,cheight, Path.Direction.CW);
 Croppath=new Path ();
 if (shape==shape_rect) {croppath.addrect (Rect.left,rect.top,rect.right,rect.bottom, Path.Direction.CW); }else if (shape==shape_circle) {croppath.addcircle (Rect.centerx (), Rect.centery (), Rect.width ()/2, Path.Direction.CW
 ); } if (Build.VERSION.SDK_INT >= build.version_codes. 
 KitKat) {//Can be anti-aliasing Path.op (Croppath, Path.Op.DIFFERENCE);
 Canvas.drawpath (Path,paint); }else{//This method can remove the sawtooth//here Savelayer then Restoretocount operation can not be less, otherwise will not get the desired effect int layerid = Canvas.savelayer (0, 0, Cwidth, Cheigh
 T, NULL, CANVAS.ALL_SAVE_FLAG);
 Canvas.drawpath (Path,paint); What has been drawn can be seen as the target figure Paint.setxfermode (new Porterduffxfermode (PorterDuff.Mode.CLEAR));
 Canvas.drawpath (Croppath,paint);
 Paint.setxfermode (NULL);
 Canvas.restoretocount (Layerid);
 The cropped way will be jagged, not found method to remove Sawtooth//canvas.clippath (Oppath, Region.Op.DIFFERENCE);
 Canvas.drawrect (0,0,cwidth,cheight,paint);

 }
}

Picture Move and Zoom

The move and zoom function of a picture, in the preview of the larger picture will also be used, in the picture cropping, we need to the picture's movement and zoom range to limit, prohibit the picture after the completion of the operation of the show Beyond the indicator box (according to the requirements also have in the process of operation is not allowed to exceed the indicator box). ImageView has a Imageview.setimagematrix (matrix) method that can directly set the transformation matrix of a picture. So we can also use this method, combined with ImageView ontouchlistener monitoring, to do the image movement and scaling processing.
Move the zoom core code as follows:

@Override public boolean Ontouch (View V, motionevent event) {if (v!=null&& (ImageView) v). Getdrawable ()!=null) {
 ImageView view = (ImageView) v;
 Rect rect=view.getdrawable (). getbounds (); Event Handling switch (event.getaction () & Motionevent.action_mask) {//When one finger is pressed, mark as Move mode case MotionEvent.ACTION_DOWN:matr
 Ix.set (View.getimagematrix ());
 Savedmatrix.set (matrix);
 Start.set (Event.getx (), event.gety ());
 mode = DRAG;
 Break
 When the second finger is pressed, it is marked as the zoom mode case MotionEvent.ACTION_POINTER_DOWN:oldDist = distance (event);
  if (Olddist > 10f) {savedmatrix.set (matrix);
  Midpoint (Mid, event);
 mode = ZOOM;
 } break;
 Case MotionEvent.ACTION_UP:case MotionEvent.ACTION_POINTER_UP:checkMatrix (rect);
 mode = NONE;
 Break
  When the finger moves, according to the current move mode or zoom mode to do the corresponding processing case MotionEvent.ACTION_MOVE:if (mode = = DRAG) {matrix.set (Savedmatrix);
 Matrix.posttranslate (Event.getx ()-Start.x, Event.gety ()-START.Y);
  else if (mode = = ZOOM) {Float newdist = distance (event); if (Newdist &GT
  10f) {matrix.set (Savedmatrix);
  float scale = newdist/olddist;
  Matrix.postscale (scale, scale, mid.x, MID.Y);
 }} break;
 } view.setimagematrix (matrix);
return true;

 }

When the finger is raised, we need to judge the current state of the picture to avoid the absence of a picture area in the scope:

private void Checkmatrix (Rect Rect) {if (limit==null&&croppath!=null) {limit=croppath.limit ();
 } if (Limit!=null) {if (mode==zoom) {matrix.getvalues (values); if (Rect.width () *values[0]<limit.width ()) {//current width less than minimum width float scale = limit.width ()/(float) rect.width ()/values[0]
 ;
 Matrix.postscale (scale, scale, mid.x, MID.Y);
 } matrix.getvalues (values); if (Rect.height () *values[4]<limit.height ()) {//The current height is less than the minimum height float scale = limit.height ()/(float) rect.height ()/
 VALUES[4];
 Matrix.postscale (scale, scale, mid.x, MID.Y);
 } matrix.getvalues (values);
 if (values[2]>=limit.left) {matrix.posttranslate (limit.left-values[2],0);
 } matrix.getvalues (values); if (Values[2]+rect.width () *values[0]<limit.right) {matrix.posttranslate (Limit.right-rect.width () *values[0]-
 values[2],0);
 } matrix.getvalues (values);
 if (values[5]>limit.top) {matrix.posttranslate (0,limit.top-values[5]);
 } matrix.getvalues (values); if (Values[5]+rect.height () *values[4]<limit.bottom) {matrix. Posttranslate (0,limit.bottom-rect.height () *values[4]-values[5]);

 }
 }
}

Cropping and saving

After the picture is scaled and moved to the size and position we expected, we can crop the area that appears in the indicator box. We have two ways to cut this area out, one is to cut the original image, the other is to cut the ImageView displayed. When the original image is too large or the picture is a network picture and so on, the original cut is not what we expect, and relatively direct to the ImageView display of the content of the cut, the original artwork to be cut also need us to calculate the area we expect in the original image position. So we still directly to the ImageView display of the pictures to crop, and then get the cutting results more convenient. Of course, if this cut is intended to deal with the original image, it can only be cropped.

View has a View.getdrawingcache () method, you can get the contents of the current view display, it returns a bitmap. Note that before using View.getdrawingcache (), we need to invoke view.setdrawingcacheenabled (true) to turn on the drawing cache, otherwise the content displayed by the current view is not available. When you are finished, call view.setdrawingcacheenabled (false) to close the drawing cache, or the next time you call View.getdrawingcache (), you get the previous content ...

Cut the core code:

Public Bitmap crop () {
 if (imageview!=null&&croppath!=null) {
 if (limit==null) {
 limit= Croppath.limit ();
 }
 Paint paint=new Paint ();
 Paint.setantialias (true);
 Imageview.setdrawingcacheenabled (true);
 Bitmap Bmp=bitmap.createbitmap (Limit.width (), Limit.height (), Bitmap.Config.ARGB_8888);
 Canvas canvas=new Canvas (BMP);
 Canvas.drawcolor (color.transparent);
 int Lid=canvas.savelayer (0,0,limit.width (), Limit.height (), null,canvas.all_save_flag);
 Path path=new path ();
 Path.addpath (Croppath.path (),-limit.left,-limit.top);
 Canvas.drawpath (path,paint);
 Paint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.SRC_IN));
 Canvas.drawbitmap (Imageview.getdrawingcache (),-limit.left,-limit.top,paint);
 Paint.setxfermode (null);
 Canvas.restoretocount (lId);
 Imageview.setdrawingcacheenabled (false);
 return bmp;
 }
 return null;
}

After cropping, saves the results to the specified directory:

public string Cropandsave (string path) throws IOException {
 Bitmap bmp=crop ();
 if (bmp==null) return null;
 File File=new file (path);
 if (!file.getparentfile (). exists ()) {
 Boolean b=file.mkdirs ();
 if (!B) return null;
 }
 if (file.exists ()) {
 Boolean c=file.delete ();
 if (!C) return null;
 }
 FileOutputStream fos=new fileoutputstream (file);
 Bmp.compress (Bitmap.compressformat.png,100,fos);
 Fos.flush ();
 Fos.close ();
 Bmp.recycle ();
 return File.getabsolutepath ();
}

Source

The complete class of code snippets in the blog, in the form of code snippets in the CSDN code notes, the need for friends to build their own projects using related classes.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.