Android PhotoView 기반 프로필 사진/원형 재단 컨트롤

머리말
흔히 볼 수 있 는 그림 재단 은 두 가지 가 있 는데 하 나 는 그림 이 고정 되 고 재단 상자 가 이동 하여 축소 되 어 재단 구역 을 확정 하 는 것 이다.초기 에 보 이 는 것 이 비교적 많 고 재단 후의 효 과 를 직접 미리 볼 수 없다 는 단점 이 있다.그리고 지금 은 재단 상자 가 고정 되 어 있 고 크기 조정 그림 을 직접 드래그 하여 재단 결 과 를 미리 볼 수 있 습 니 다.
내 가 만 든 이 컨트롤 은 후자 에 속한다.일반적으로 그림 재단 을 하 는 사고방식 은 제스처 를 감청 하고 좌 표를 얻 은 다음 에 그림 을 변형 시 키 는 것 이다.마지막 으로 재단 구역 의 좌 표를 확정 하고 비트 맵 을 재단 한 다음 에 그림 을 현지 에 저장한다.저 는 기술 이 하 얀 사람 입 니 다.제스처 를 감시 해 야 한 다 는 생각 에 머리 가 아 픕 니 다.공교롭게도 프로젝트 전에 큰 그림 을 보기 위해 유명한 제3자 사진 조회 컨트롤 인 PhotoView 를 도 입 했 습 니 다.(사용 절 차 는 이 글 을 참고 하 세 요Android PhotoView 사용 절차 인 스 턴 스 상세 설명)그래서 생각해 보 니 그림 이 변 형 될 때 까지 의 몇 단 계 를 PhotoView 에 맡 겨 서 해결 할 수 있 을 까 하 는 생각 이 들 었 습 니 다.저 는 재단 구역 뒤의 이 몇 단 계 를 확인 하 는 일 만 맡 으 면 됩 니 다.나중에 구덩이 가 몇 개 떨어져 서 게 으 름 피 우 는 것 도 쉽 지 않 았 어 요.사실은...ε=(´ο`*)))에이~


먼저 디자인 방향 을 간략하게 소개 해 야 한다.위의 그림 에서 보 듯 이 주로 두 부분 으로 나 뉘 는데 상층 부 는 가리개(재단 틀 로 도 이해 할 수 있다)로 재단 후의 효 과 를 미리 볼 수 있다.아래쪽 은 PhotoView 입 니 다.여 기 는 한 겹 더 싸 서 정사각형 으로 바 꾸 었 습 니 다.
다음은 가 려 진 코드 입 니 다.비교적 간단 합 니 다.여 기 는 군말 하지 않 겠 습 니 다.

/**
 * Created by MandyLu on 2018/7/14.
 *      
 */
public class CircleCropView extends View {
 public final int CIRCLE_MARGIN = 50;

 public CircleCropView(Context context) {
 super(context);
 }

 public CircleCropView(Context context, @Nullable AttributeSet attrs) {
 super(context, attrs);
 }

 public CircleCropView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 }

 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
 public CircleCropView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
 super(context, attrs, defStyleAttr, defStyleRes);
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, widthMeasureSpec);
 }

 @RequiresApi(api = Build.VERSION_CODES.O)
 @Override
 protected void onDraw(Canvas canvas) {
 canvas.save();

 Path path = new Path();
 Rect viewDrawingRect = new Rect();
 getDrawingRect(viewDrawingRect);

 float radius = viewDrawingRect.width() / 2 - CIRCLE_MARGIN;
 path.addCircle(viewDrawingRect.left + radius + CIRCLE_MARGIN,
 viewDrawingRect.top + radius + CIRCLE_MARGIN, radius, Path.Direction.CW);

 Paint outsidePaint = new Paint();
 outsidePaint.setAntiAlias(true);
 outsidePaint.setARGB(151, 0, 0, 0);

 canvas.clipPath(path, Region.Op.DIFFERENCE);
 canvas.drawRect(viewDrawingRect, outsidePaint);
 canvas.restore();
 }
}
Square PhotoView 는 PhotoView 를 바탕 으로 길 이 를 바 꾸 었 을 뿐 onMeasure 방법 을 다시 쓰 면 됩 니 다.

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, widthMeasureSpec);
 }
그렇다면 현재 가장 중요 한 단 계 는 PhotoView 에서 현재 그림 표시 영역의 Drawable 이나 Bitmap 를 가 져 오 는 것 입 니 다.PhotoView 의 함 수 를 대충 보 았 지만 쓸 만 한 것 을 찾 지 못 했다.첫 번 째 구 덩이 를 해결 하 는 어 리 석 은 방법 은 바로 자신 이 먹고 입 는 것 이다―원 그림 의 bitmap 를 직접 가 져 온 다음 에 PhotoView 에 게 현재 그림 의 변형 행렬 을 물 어보 고 자신 이 행렬 을 통 해 한 걸음 한 걸음 변형 하여 해당 하 는 비트 맵 을 얻 는 것 이다.
생각 은 사실 문제 가 없 지만 두 번 째 구덩이 가 또 나 타 났 다.이곳 의 변형 행렬 은 제 가 최초 로 바 이 두 의 결 과 는 getSuppMatrix 입 니 다.소스 코드 는 자세히 보지 않 았 지만 구덩이 에 빠 지 는 과정 에서 제 가 관찰 한 바 에 의 하면 최신 제스처 변형 결과(불확실==다른 구덩이 가 종합 적 으로 발생 한 잘못된 결과 일 수도 있 습 니 다)라 고 추측 합 니 다.아무튼 마지막 으로 소스 코드 를 찾 아 봤 는데 getDisplayMatrix 를 사용 한 것 이 확실 합 니 다.
이 어 세 번 째 구덩이 로 구덩이 가 많 으 면 습관 이 된다.행렬 의 XY 변위 량 은 원래 그림 의 중심 보다 영역 중심 을 표시 하 는 것 이 라 고 생각 했 습 니 다.즉,크기 조정 작업 만 있 으 면 변위 가 0 이 어야 합 니 다.그러나 실제 특수 한 위치(예 를 들 어 네 개의 정점 을 가 져 오 는 것)의 재단 결 과 를 통 해 볼 때 이곳 의 XY 변위 량 은 실제 마지막 으로 구역 왼쪽 상단 의 점 이 원점(즉,원 그림 왼쪽 상단)의 위 치 를 나타 낸다.쉽게 말 하면 변위 량 을 최종 적 으로 구역 왼쪽 상단 을 나타 내 는 좌표 로 할 수 있다.
그리고 나 서 나 는 네 번 째 구 덩이 를 맞 았 다(🙂)。이 구 덩이 는 지금 뒤 돌아 보 니 간단 해서 넘 어 지지 말 았 어야 했 는데,그때 납득 하지 못 했 을 때 는 정말 당 황 스 러 웠 다.이 구덩이 의 문 제 는 바로 Matrix 의 값 은 제스처 에 기반 한 것 이다.즉,화면 픽 셀(다시 말 하면 실제 디 스 플레이 에 기반 한 그림)에 기반 한 것 이다.비트 맵 을 재단 할 때 는 원본 픽 셀 을 기반 으로 한다.그러면 여기 에는 정상 적 인 디 스 플레이 를 위해 크기 조정 비례 가 존재 합 니 다.예 를 들 어 원 도 는 3000 x 4000 입 니 다.화면 해상도 가 1080*1920 이기 때문에 실제 디 스 플레이 할 때 그림 이 축소 되 었 습 니 다.이 비율 은 9/25 입 니 다.따라서 재단 과정 에서 변위 량 을 25/9 배 더 늘 려 복원 해 야 한다.
다음은 커팅 부분의 핵심 코드 입 니 다.

fun cropImage(){
 var degree = ImageUtils.readPictureDegree(imagePath)
 var bitmap = ImageUtils.getRotatedBitmap(BitmapFactory.decodeFile(imagePath),degree)

 var width: Int = 0
 var startX: Int = 0
 var startY: Int = 0
 if (bitmap.width < bitmap.height){
 startY = (bitmap.height - bitmap.width) / 2
 width = bitmap.width
 }else{
 startX = (bitmap.width - bitmap.height) / 2
 width = bitmap.height
 }

 var matrix = Matrix()
 photo_preview.getDisplayMatrix(matrix)//      ,   scaleX translationX  
 var values = FloatArray(9, {0.0f})
 matrix.getValues(values)

 var expWidth = Math.round(bitmap.width * values[0])//  x
 var expHeight = Math.round(bitmap.height * values[4])//  y
 
 var bitmap1 = Bitmap.createScaledBitmap(bitmap, expWidth, expHeight, false)

 val ratio = width * 1.0f / photo_preview.width
 startX = Math.round(startX * values[0] - values[2] * ratio)
 startY = Math.round(startY * values[4] - values[5] * ratio)
 var bitmap2 = Bitmap.createBitmap(bitmap1, startX, startY, width, width, null, false)

 saveImage(bitmap2)
 }
여기에 또 몇 개의 작은 구덩이 가 있 으 니 설명해 야 한다.
bitmap 를 읽 을 때 각 도 를 주의해 야 합 니 다.이것 은 내 가 로 컬 사진 과 인터넷 사진 을 재단 할 때 발견 한 것 이 고,어떤 것 은 바로 90 도 돌 았 다.휴대 전화 마다 다 르 기 때문에 안전 을 위해 서 는 사진 의 EXIF 정보 에서 회전 이 필요 한 각 도 를 얻 은 다음 에 더 처리 해 야 한다.
나 는 최종 적 으로 정사각형 을 표시 하고 scale Type 을 선택 한 것 은 centerCrop 이기 때문이다.그래서 기본 값 은 중간 에 있 는 것 을 보 여 주 는 것 입 니 다.그래서 감축 할 때의 원점 도 정사각형 의 왼쪽 상단 부터 시작 해 야 한다.여 기 는 두 가지 상황 을 계산 하 는 원점 좌표 입 니 다.

var startX: Int = 0
 var startY: Int = 0
 if (bitmap.width < bitmap.height){
 startY = (bitmap.height - bitmap.width) / 2
 width = bitmap.width
 }else{
 startX = (bitmap.width - bitmap.height) / 2
 width = bitmap.height
 }
크기 조정 작업 후 원점 좌표 도 이에 따라 바 뀌 고 해당 하 는 크기 조정 비율 을 곱 한 다음 에 해당 하 는 변위 량 에 따라 재단 구역 의 위 치 를 확정 합 니 다.
매트릭스 로 직접 변형 하려 고 했 는데 실 패 했 습 니 다(원인 불명).다른 재단 컨트롤 원본 코드 를 보고 createcaledBitmap 를 사용 하여 방법 을 결정 합 니 다.
마지막 으로 검토 해 야 한다.잔 머리 를 굴 려 서 가 까 운 길 로 가 려 고 했 는데 소스 코드 에 익숙 하지 않 아서 구 덩이 를 만 났 을 때 도 블랙박스 로 만 여 길 수 밖 에 없 었 다.끊 임 없 는 실험 을 통 해 문제 의 소 재 를 추측 할 수 있 을 뿐,오히려 더 많은 시간 을 들 여 얻 는 것 보다 잃 는 것 이 많다.앞으로 시간 이 있 을 때 는 소스 코드 를 꼼꼼 히 연구 하고 원리 적 으로 문 제 를 해결 해 야 합 니 다(*~커튼)~
마지막 으로,몇 명의 블 로 거들 의 사심 없 는 공유 에 감 사 드 립 니 다.이에 감 사 드 립 니 다~
>>>Android Bitmap 에서 흔히 볼 수 있 는 몇 가지 동작:크기 조정,재단,회전,오프셋
>>>Android ImageCropper 사각형 원형 재단 상자
>>>Android 재단 그림 이 원형 그림 의 실현 원리 와 코드
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기