어플리케이션 제작 중에 SurfaceView에 CameraPreview를 이용하여 카메라를 제어하는 프로그래밍 중

실시간으로 SurfaceView를 캡쳐해야하는 코드가 필요해 처리하는 과정 등을 정리하여 포스팅합니다.

SurfaceView는 일반적인 함수로 캡쳐하면 검은 화면만 출력되기 때문에...

여러가지 찾아본 후 적용되는 코드로 설명하곘습니다.

CameraPreview로 SurfaceView에 카메라 화면을 출력할 때, 실시간으로 사진파일이 필요할 때 사용합니다.


[CameraPreview.java]


public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback {

... 중략 ...

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

... 중략 ...

mCamera.setPreviewDisplay(mHolder);

mCamera.setPreviewCallback(new Camera.PreviewCallback(){

@Override

public void onPreviewFrame(byte[] data, Camera camera) {

// 현재 SurfaceView를 JPEG Format으로 변경

Camera.Parameters parameters = camera.getParameters();

int w = parameters.getPreviewSize().width;

int h = parameters.getPreviewSize().height;

int format = parameters.getPreviewFormat();

YuvImage image = new YuvImage(data, format, w, h, null);

ByteArrayOutputStream out = new ByteArrayOutputStream();

Rect area = new Rect(0, 0, w, h);

image.compressToJpeg(area, 100, out);

Bitmap bm = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.size());

byte[] currentData = out.toByteArray();         

                   

... 중략 ...

}

}

}


기본 코드입니다.

CameraView class에서 SurfaceHolder.Callback을 implements하고

surfaceChanged() 에서 mCamera.setPreviewCallback을 호출합니다.

onPreviewFrame 메소드는 CameraPreview에서 실시간으로 호출되는 함수입니다.

위 코드는 현재 SurfaceView 화면을 캡쳐해서 JPEG Format으로 만들어주는 코드입니다.


여기서 JPEG 파일을 PNG 파일로 바꾸는 방법입니다.


... 위 코드로 부터 계속 ...

int orientation = calculatePreviewOrientation(mCameraInfo, mDisplayOrientation);

Matrix matrix = new Matrix();

matrix.postRotate(orientation);


BitmapFactory.Options options = new BitmapFactory.Options();

options.inSampleSize = 1 // 이미지 사이즈 리스케일(2의 지수 승으로 해야 처리속도 빠름; 1,2,4,8,16...; 필요시)

options.inPreferredConfig = Bitmap.Config.ARGB_8888;

// RGB_565 : 16bit Bitmap, ARGB_8888 : 32bit Bitmap, 4444는 저품질이라 추천안함


Bitmap bitmap = BitmapFactory.decodeByteArray(currentData, 0, currentData.length, options);

bitmap =  Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);

// bitmap src, start x, start y, width, height, 회전, Flag


 // Bitmap 이미지를 surfaceView 좌표로 변환

bitmap = GetBinaryBitmap(bitmap); // bitmap 이진화 처리


//bitmap을 byte array로 변환

 ByteArrayOutputStream stream = new ByteArrayOutputStream();

bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); // 100 수치 변경해서 품질(Quality) 변경

currentData = stream.toByteArray();


// 이후 해당 Byte Array로 파일 저장 및 처리...

... 중략 ....

}

}

}


조금 복잡할 수도 있는 코드입니다.

한줄씩 주석 포함해서 해석하면서 코드 작성하시면 쉽게 처리 가능할 것 같습니다.


PNG(Bitmap으로) 파일 저장하는 방법은 Google에 많이 있고 또 예제코드가 있기 때문에 생략하겠습니다.


이상 CameraPreview에서 카메라 화면을 SurfaceView에 출력하고 그 화면을 캡쳐하는 방법에 대해 알아보았습니다.

질문 사항은 댓글로 남겨주세요!!


* 참고 글 : 

SurfaceView CameraPreview 연동

Bitmap 이진화 처리


to Top