일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 안드로이드
- 브런치작가되기
- T자형인재
- 1일1커밋
- 베드테이블
- 북한살둘레길
- 슬기로운 온라인 게임
- 리얼하다
- 베드트레이
- 테트리스
- 지지않는다는말
- 프래그먼트
- 아비투스
- 면접
- 소프시스
- 소프시스 밤부 좌식 엑슬 테이블
- 한단어의힘
- 함수형 프로그래밍
- 커스텀린트
- 한달브런치북만들기
- 자취필수템
- 한달어스
- 한달독서
- 좌식테이블
- 목적 중심 리더십
- 끝말잇기
- 목적중심리더십
- 재택근무
- 캐치마인드
- 어떻게 나답게 살 것인가
- Today
- Total
정상에서 IT를 외치다
[Android, Camera] 2. 카메라 프리뷰를 이용한 화면 캡처 및 배경 이미지 적용 본문
안녕하세요. 블랙진입니다.
Capture the camera preview with image in android
Camera api 를 사용하여 화면을 캡처하고 캡처한 화면에 배경 이미지를 적용하는 방법에 대해 포스팅 해보겠습니다.
현 포스팅은 이전 포스팅의 연장입니다. ~!
저번 포스팅에는 카메라 프리뷰를 안드로이드 기기에 맞게 띄우는 법에 대해 살펴보았습니다.
이번에는 프리뷰 화면을 캡처하는 법에 대해 포스팅 해보겠습니다.
1. 캡처 기능 추가
_activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/cameraPreview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<LinearLayout
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/btnCapture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="캡처" />
</LinearLayout>
</RelativeLayout>
화면 하단에 캡처 버튼을 추가해 줍니다.
_MainAcitivty.kt
btnCapture.setOnClickListener {
myCameraPreview?.takePicture()
}
캡처 버튼에 takePicture() 함수를 적용해 줍니다.
_MyCameraPreview.java
/**
* 이미지 캡처
*/
public void takePicture(){
mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
/**
* 이미지 저장을 위한 콜백 함수
*/
private Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
}
};
private Camera.PictureCallback rawCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
}
};
private Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
//이미지의 너비와 높이 결정
int w = camera.getParameters().getPictureSize().width;
int h = camera.getParameters().getPictureSize().height;
int orientation = calculatePreviewOrientation(mCameraInfo, mDisplayOrientation);
//Log.d("MyTag","이미지 캡처 시 -> orientation : " + orientation);
//byte array 를 bitmap 으로 변환
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeByteArray( data, 0, data.length, options);
//이미지를 디바이스 방향으로 회전
Matrix matrix = new Matrix();
/**
* 셀카 모드에는 저장 시 좌우 반전을 해줘야 한다.
*/
if(mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
//Log.d("MyTag","180도 추가 회전 후 좌우반전을 해줍니다.");
//orientation += 180;
matrix.setScale(-1,1);
}
matrix.postRotate(orientation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
//bitmap 을 byte array 로 변환
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] currentData = stream.toByteArray();
//파일로 저장
new MyCameraPreview.SaveImageTask().execute(currentData);
}
};
위와 같이 takePicture 와 콜백 함수를 추가해 줍니다.
jpegCallback 함수를 통해 비트맵 이미지를 바이트 변환하여 JPEG 이미지로 정하게 됩니다.
그 하단에 이어서 SaveImageTask 클래스를 추가해 줍니다.
/**
* 이미지 저장을 위한 콜백 클레스
*/
private class SaveImageTask extends AsyncTask<byte[], Void, Void> {
@Override
protected Void doInBackground(byte[]... data) {
FileOutputStream outStream = null;
try {
File path = new File (Environment.getExternalStorageDirectory().getAbsolutePath() + "/camtest");
if (!path.exists()) {
path.mkdirs();
}
String fileName = String.format("%d.jpg", System.currentTimeMillis());
File outputFile = new File(path, fileName);
outStream = new FileOutputStream(outputFile);
outStream.write(data[0]);
outStream.flush();
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length + " to "
+ outputFile.getAbsolutePath());
mCamera.startPreview();
// 갤러리에 반영
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(Uri.fromFile(outputFile));
getContext().sendBroadcast(mediaScanIntent);
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
Log.d(TAG, "Camera preview started.");
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
위 클래스는 AsyncTask 로 동작합니다.
Environment.getExternalStorageDirectory().getAbsolutePath() + "/camtest"
위는 갤러리에 저장될 파일 경로 입니다. camtest 라는 폴더가 생성되어 그 안에 사진이 차곡 차곡 저장됩니다.
저장 폴더의 이름을 변경하고 싶으시면 camtest 명을 변경하시면 됩니다.
String fileName = String.format("%d.jpg", System.currentTimeMillis());
위는 camtest 폴더에 저장되는 파일명입니다. 파일 타입은 jpg 이고 파일 명은 중복되면 안되기 때문에 시스템 시간으로 설정하였습니다.
이렇게 하면 매 사진을 찍을 때마다 시스템 시간이 다르기 때문에 파일명이 겹칠 일이 없습니다.
아래는 MyCameraPreview.java 전체 코드 입니다.
짠! 이걸로 캡처 버튼을 누르시면 camTest 폴더에 이미지가 차곡차곡 저장되는 것을 확인하실 수 있을 겁니다.~!~!
다음 포스터는 캡처된 이미지에 배경을 넣는 방법을 포스팅 해보겠습니다.
< 참고 사이트 >
'안드로이드' 카테고리의 다른 글
[Android_ID] Android 0 대응 하기 - Android Id 변경 (2) | 2018.08.23 |
---|---|
[Android, Camera] 3. 카메라 프리뷰를 이용한 화면 캡처 및 배경 이미지 적용 (6) | 2018.08.22 |
[Android, Camera] 1. 카메라 프리뷰를 이용한 화면 캡처 및 배경 이미지 적용 (2) | 2018.08.22 |
[Android, Custom Switch] 안드로이드 스위치 버튼 꾸미기 (4) | 2018.08.17 |
[Android, Customizing Ripple Effect] 내맘대로 리플 효과 변경하기 (0) | 2018.08.13 |