프로그램 자료/안드로이드
안드로이드 바코드 스캐너 세로모드 zxing
motolies
2017. 2. 6. 15:05
출처 : http://blog.naver.com/airwindtree/220255139786
zxing 2.3이하에서만 가능하다.
zxing 3.1.0 에서 안되더라...
A4용지 를 가로로 놓고
카메라 또한 가로로 놓고 찍는것을 원칙으로 하겠다.


소스 있는 그대로 실행시켜서 바코드 스캐너를 실행하면 위와 같다.
1. AndroidManifest.xml
<activity android:name="com.google.zxing.client.android.CaptureActivity" android:screenOrientation="landscape" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:configChanges="orientation|keyboardHidden" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:windowSoftInputMode="stateAlwaysHidden">
-------------------------------------------- * 변경부분 * 이부분을 android:screenOrientation="portrait" 로 변경 |
1. 변경후 실행화면

| 메뉴, 바코드 인식 선이 세로로 되었다.
사진상에서는 이상한점을 느끼지 못할지 모르겠지만,
직접 실행해 보면 가로로 상태인데 카메라가 세로로 변경되어서 나온다
실제 화상과 카메라 화상이 90도가 꺽여있는 상태이다. | 내가 원하는 카메라 상태 왼쪽 | | | 아래 <------------>위 | | | 오른쪽
|
|
2. src/com.google.zxing.client.android.camera/CameraConfigurationManager.java
void setDesiredCameraParameters(Camera camera, boolean safeMode) { camera.setDisplayOrientation(90); //<--- 코드를 추가한다 Camera.Parameters parameters = camera.getParameters(); if (parameters == null) { Log.w(TAG, "Device error: no camera parameters are available. Proceeding without configuration."); return; } -------------------------------------------- * 변경부분 코드 추가 (빨간색 코드) |
2. 변경후 실행화면

내가 원하는데로 화상 또한 돌아갔다.
그런데...
현 문제 : 바코드 인식이 세로일때 안되고, 가로일때 인식이 된다
가로일때 인식해도 결과값이 가로로 나오면서 화면이 깨진다.
세로일때 인식시킬 수 있게 바꿔보자
3. src/com.google.zxing.client.android.camera/CameraManager.java
private static final int MAX_FRAME_WIDTH = 1200; // = 5/8 * 1920 , 1920/2 : 960 private static final int MAX_FRAME_HEIGHT = 675; // = 5/8 * 1080, 1080/2 :540
/** * Like {@link #getFramingRect} but coordinates are in terms of the preview frame, not UI / screen. * @return {@link Rect} expressing barcode scan area in terms of the preview size
{#getFramingRect을 @link}하지만 좌표는 미리보기 프레임이 아닌 UI / 화면의 측면에있는 것처럼. 미리보기 크기의 측면에서 @return {@link RECT} 표현 바코드 스캔 영역 */ public synchronized Rect getFramingRectInPreview() { if (framingRectInPreview == null) { Rect framingRect = getFramingRect(); if (framingRect == null) { return null; } Rect rect = new Rect(framingRect); Point cameraResolution = configManager.getCameraResolution(); Point screenResolution = configManager.getScreenResolution(); if (cameraResolution == null || screenResolution == null) { // Called early, before init even finished 초기화도 완성하기 전에, 초기 호출 return null; } rect.left = rect.left * cameraResolution.x / screenResolution.x; rect.right = rect.right * cameraResolution.x / screenResolution.x; rect.top = rect.top * cameraResolution.y / screenResolution.y; rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
framingRectInPreview = rect; } return framingRectInPreview; }
-------------------------------------------- * 변경부분 위 코드를 이 코드로 변경 rect.left = rect.left * cameraResolution.y / screenResolution.x; rect.right = rect.right * cameraResolution.y / screenResolution.x; rect.top = rect.top * cameraResolution.x / screenResolution.y; rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y; |
3. 변경후 실행화면

여전히 가로일때 인식된다.

결과 화면이 세로로 정상적으로 잘 나온다.
4. src/com.google.zxing.client.android/DecodeHandler.java
/** * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,reuse the same reader objects from one decode to the next. * * @param data The YUV preview frame. * @param width The width of the preview frame. * @param height The height of the preview frame.
그것이 걸린 시간 뷰 파인더 사각형 내에서 데이터 및 시간을 디코딩. 효율성을 위해, 하나의 디코드에서 다음에 같은 리더 객체를 다시 사용합니다. * @param data YUV 미리보기 프레임 * @param width 프리뷰 프레임의 폭 * @param height 미리보기 프레임의 높이입니다. */ private void decode(byte[] data, int width, int height) { //---------------------------------------------------------------- //코드 추가 byte[] portraitData = new byte[data.length]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { portraitData[x * height + height - y - 1] = data[x + y * width]; } } int tmp = width; width = height; height = tmp; data=portraitData; // 회전한 데이터를 buildLuminanceSource 에서 사용 해야 함 * data로 되어있는것 portraitData 로 변경 //---------------------------------------------------------------- long start = System.currentTimeMillis(); Result rawResult = null; PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource( data, width, height);
if (source != null) { BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); try { rawResult = multiFormatReader.decodeWithState(bitmap); } catch (ReaderException re) { // continue } finally { multiFormatReader.reset(); } } Handler handler = activity.getHandler(); if (rawResult != null) { // Don't log the barcode contents for security. // 보안을 위해 바코드 내용을 기록하지 않습니다. long end = System.currentTimeMillis(); Log.d(TAG, "Found barcode in " + (end - start) + " ms"); if (handler != null) { Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult); Bundle bundle = new Bundle(); bundleThumbnail(source, bundle); message.setData(bundle); message.sendToTarget(); } } else { if (handler != null) { Message message = Message.obtain(handler, R.id.decode_failed); message.sendToTarget(); } } }
-------------------------------------------- * 변경부분 빨간 부분 코드 추가 |
4. 변경후 실행화면

세로로 바코드 스캔이 인식이 된다.

결과물이 잘 나온다.
- 사각형 위치 조정
CameraManager.java public final class CameraManager { private static final int MAX_FRAME_WIDTH = 960; // 1920/2 private static final int MAX_FRAME_HEIGHT= 540; // = 1080/2
public synchronized Rect getFramingRect() { int topOffset = (screenResolution.y - height) / 9; // 2->10 세로 수정 }
private static int findDesiredDimensionInRange(int resolution, int hardMin, int hardMax) { int dim = 7 * resolution / 10; // Target 50% of each dimension } |
."끝"