앞서 바코드 스캔 라이브러리 ZXing.Delphi에 대한 소개와 버그 수정에 대한 포스트를 올렸는데요. 이번에는 이 라이브러리를 제대로 사용하기 위한 예제 프로젝트에 대해 설명해보겠습니다.
원론적으로 보면, ZXing.Delphi 라이브러리의 사용법 자체는 꽤 간단합니다.
- 먼저 TScanManager 객체를 생성해놓습니다.
- 카메라를 액티브시킨 후, TCameraComponent의 OnSampleBufferReady 이벤트가 발생되면 이벤트 핸들러를 통해 카메라 캡쳐 이미지를 비트맵으로 받습니다.
- 캡쳐된 비트맵을 TScanManager.Scan() 함수로 넘깁니다.
- TScanManager.Scan() 함수의 리턴값(TReadResult 타입)을 받아 그 안에 인식된 바코드 값이 담겨 있으면 인식이 성공한 경우입니다.
(실제로는 동기화를 위한 코드가 더 추가되는 등 조금 더 복잡합니다)
물론 ZXing.Delphi의 배포 소스에도 이런 과정을 보여주는 데모 프로젝트가 포함되어 있습니다. 그런데 이 데모 프로젝트는 실제로 사용하기에는 완성도가 좀 떨어져서, ZXing.Delphi의 뛰어난 성능을 제대로 보여주지 못합니다. 그래서 실무 프로젝트에 적용할 수 있을 정도로 개선된 데모 프로젝트를 만들어봤습니다.
[데모 소스코드] [안드로이드 데모 APK] [윈도우 데모 실행파일]
원래의 데모 프로젝트보다 개선된 주요 사항들은 다음과 같습니다.
1. 캡쳐 Quality를 MediumQuality로 설정하는 코드를 수정했습니다.
QR 코드 스캔 목적으로는 최고 해상도가 아닌 미디엄만 해도 충분하고 캡쳐 속도도 빠르기 때문에 원본 데모 소스에서도 카메라 컴포넌트의 Quality 속성을 MediumQuality로 지정하고 있었는데요. Firemonkey의 이 Quality 속성에는 약간의 버그가 있어서 제대로 값이 설정되지 않는 경우가 있습니다. 이에 대해서는 앞서 올린 포스트를 참고하시기 바랍니다.
1 2 |
CameraComponent1.Quality := TVideoCaptureQuality.HighQuality; CameraComponent1.Quality := TVideoCaptureQuality.MediumQuality; |
2. 카메라 컴포넌트에서 넘어온 비트맵을 잘라내도록 코드를 추가했습니다.
QR코드는 형태가 정사각형이고 다른 1차원 바코드들은 가로로 길쭉한 형태이기 때문에, 세로(혹은 가로)로 길쭉한 카메라 스캔 이미지는 바코드 인식을 위한 이미지로는 적합하지 않습니다. 또 스캔할 이미지에 바코드 이외에 다른 이미지가 함께 찍히면 그만큼 인식률이 떨어져 여러번, 더 긴 시간동안 스캔을 시도해야만 하게 됩니다. 특히 스캔 대상에 바코드가 여러개 연속되어 있는 경우에는 원하는 바코드가 아닌 엉뚱한 바코드가 함께 찍혀 딴 것이 먼저 인식되거나, 다른 바코드의 이미지 일부 때문에 인식 실패가 발생하는 경우도 잦습니다. 따라서 일반적으로 스캔할 이미지는 길쭉한 형태보다는 정사각형에 가까워 스캔 대상 이미지가 그 안에 가득 찰수 있도록 해주는 편이 스캔 인식이 훨씬 잘 됩니다.
그래서, 카메라 이미지를 바로 ScanManager로 넘기는 대신 프리뷰 이미지의 크기에 맞춰(정확하게는 가로세로 비율만 맞춰) 아래위를 잘라낸(crop) 비트맵을 전달하도록 코드를 추가했습니다. 이렇게 적절한 크기로 잘라냈을 때 스캔 인식률은, 잘라내지 않은 카메라 이미지를 그대로 스캔 시도할 때보다 현저하게 좋아집니다. (반드시 정사각형이어야 할 필요까지는 없지만 정사각형에 가까운 편이 좋습니다) 물론 비트맵을 한번 더 복사하는 작업이 들어가서 약간 느려지는 부분도 있지만, 잘라낸 만큼 스캔할 비트맵 데이터가 작아지므로 바코드 스캔 속도는 전보다 훨씬 빨라집니다. 실제 테스트를 해보면 잘라내지 않았을 때보다 몇배나 빠르게 바코드를 인식할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 |
tempBitmap := TBitmap.Create; try CameraComponent1.SampleBufferToBitmap(tempBitmap, True); iNewHeight := Trunc(tempBitmap.Width * imgCamera.Size.Height / imgCamera.Size.Width); ARect := Rect(0, (tempBitmap.Height-iNewHeight) div 2, tempBitmap.Width, tempBitmap.Height - (tempBitmap.Height-iNewHeight) div 2); imgCamera.Bitmap.SetSize(ARect.Width, ARect.Height); imgCamera.Bitmap.CopyFromBitmap(tempBitmap, ARect, 0, 0); finally tempBitmap.Free; end; |
이와 더불어, 원래의 데모 소스에서는 프리뷰 이미지의 WrapMode가 Stretch로 되어 있었던 것을 Fit로 수정했습니다. 사실 이미지의 가로세로 비율에 맞게 비트맵을 잘라냈으므로 Fit로 하든 Stretch로 하든 사용자의 눈에 보이는 결과는 차이가 없겠습니다만.
3. 지속적인 오토포커스를 하도록 했습니다.
TCameraComponent.FocusMode의 기본값은 AutoFocus입니다. ContinuousAutoFocus 값은 원래 움직이는 피사체를 대상으로 계속 포커스를 시도하는 모드인데, 바코드 스캔 동작 중에는 사용자가 카메라를 계속 움직이는 것이 당연하므로 AutoFocus보다 ContinuousAutoFocus가 훨씬 낫습니다. 당연히 인식 속도가 빨라집니다.
1 |
CameraComponent1.FocusMode := TFocusMode.ContinuousAutoFocus; |
4. 화면 Orientation을 Portrait로 고정시켰습니다.
앱의 화면이 자동회전 되면 위 2번 항목의 변경으로 가로세로 크기를 맞춰놓은 프리뷰 이미지 때문에 화면 레이아웃이 의도한 것과 다르게 이상하게 될 수밖에 없습니다. 따라서 디자인 단계에서 Portrait나 Ladscape 어느쪽으로든 Orientation을 고정시키는 것이 낫습니다.
5. 카메라가 없는 윈도우 PC에서 바코드 이미지를 불러들여 테스트하는 코드를 추가했습니다(Windows).
개발 테스트 및 디버깅 편의를 위해 추가한 것으로, Load Test 버튼을 누르면 OpenDialog로 바코드가 포함된 이미지를 선택해서 불러들여 바코드 인식을 할 수 있습니다. 한편 모바일에는 OpenDialog가 없으므로 모바일인 경우 로드 버튼이 나타나지 않도록 했습니다. (안드로이드 플랫폼에 오픈다이얼로그 기능이 없기 때문에, 코드상으로는 컴포넌트를 배치하고 기능 호출도 가능하지만 실제 다이얼로그가 뜨지 않습니다)
6. QR코드를 인식했을 때 Toast 메시지를 뿌리도록 코드를 추가했습니다(Android).
사소한 것이지만, 바코드가 인식되었을 때 명확하게 알려주기 위한 것입니니다. 토스트가 지원되지 않는 안드로이드 이외 플랫폼(Windows, iOS)에서는 ShowMessage로 나타납니다.
참고: 스캔을 시작하는 클래스인 TScanManager의 생성자의 첫번째 인자가 인식할 바코드의 포맷 종류인데요. 데모 코드에서는 TBarcodeFormat.Auto로서, 이 라이브러리가 인식 가능한 모든 바코드를 다 인식하도록 하는 옵션입니다. 짐작하시겠지만, 인식할 코드 종류의 수가 많을수록 인식 속도가 그만큼 느려집니다. 따라서 QR Code나 Code 128처럼 특정 코드를 인식하려는 대부분의 경우에는 Auto가 아니라 해당 코드 포맷을 지정하는 것이 좋습니다. (물론 저도 데모가 아닌 실제 프로젝트 코드에서는 Auto 대신 QR_CODE로 지정했습니다)
uMain.pas ‘BarcodeFormat’ not found라고 하는데 바코드 폼은 어떻게 받아오신건가요?
가능하시면 라이브러리 추가하는 방법도 알수 있을까요??
윈도우에서 하던 것과 별로 다르지 않습니다. ZXing.Delphi 패키지를 컴파일해서 설치하시고 Library Path에 ZXing.Delphi가 컴파일되어 나온 패스를 잡아주시면 됩니다. 다만 한가지 다른 것은, ZXing.Delphi 패키지를 두번 빌드해야 한다는 것입니다. 델파이/C++빌더 IDE 자체에 패키지 설치를 위해 Win32에서 한번 빌드해서 인스톨시키시고, 안드로이드로 플랫폼을 바꾸어 한번 더 빌드하셔야 합니다.
컴파일 오류 중에 [exec error] The command “PATH C:\… 이런 오류가 뜨는데 무슨 뜻인지 알려주실수 있을까요?
혹시가능하시다면 자세히 묻고 싶은데 가능하시나요
지금 윈도우로 컴파일하고 나서 안드로이드 폼으로 컴파일하라고 하셧는데
윈도우 하고 나서 안드로이드 폼으로 컴파일을 하면 [PAClient Error] Error:E2312 unable to excute..라는 에러가 나옵니다 ㅠㅠ
PAClient 에러는 아주 다양한 원인이 있어서 단적으로 원인을 짚기 힘듭니다.
아래의 헬프 페이지가 참고가 되실지 모르겠습니다.
http://docwiki.embarcadero.com/RADStudio/Berlin/en/Platform_Assistant_Server_Errors_Index
현재 제가 IBNS코드를 통한 도서 검색 프로그램을 제작하려고하는데 지금 QR코드는 인식이 되고 다른 바코드 종류에서 어떤건되고 어떤건 안되는데 무엇인 문제인지 알려주실수 있을까요?
ISBN은 EAN-13 코드의 확장입니다. 그런데 ZXing.Delphi 라이브러리에는 아직 EAN-13, EAN-8 코드가 구현되어 있지 않습니다. 즉 현재 상태의 ZXing.Delphi에서는 ISBN 코드를 인식할 수 없습니다. (깃허브의 ZXing.Delphi 홈페이지에서도 그렇게 써놨고 저도 라이브러리 소개를 하면서 구현된 것이 일부라고 말씀드렸었습니다)
사실은, 제가 ZXing.Delphi 라이브러리를 갖고 이래저래 갖고 노는 과정에서 EAN-13 코드의 구현을 시도해본 적이 있었습니다. 그런데 EAN-13 코드는 부가적인 규정이 많아서, 완전히 구현하려면 상당히 많은 노가다가 필요하더군요. 대략 2/3 정도 해보다가 일이 점점 눈덩이처럼 커지길래 당장 제 프로젝트에서 쓰이는 것도 아니고 해서 일단 보류했습니다.
혹시 다음에 또 짬이 나면 더 시도해보고 알려드리지요.
Olá Bakjihun Imp,
Eu baixei o apk e ELE Funciona Muito Bem, mas se eu USAR o código-fonte do Pará
Gerar o apk, ELE NÃO Funciona (Não ler o código).
Acho Que o Problema E A Minha Versão ZXing.
Eu Tentei correr em Delphi 10,1 Berlim e Delphi 10 Seattle,
mas NÃO trabalha em Nenhum Deles.
Poderia, por favor CRIAR Uma Outra Amostra com Fontes parágrafo Baixar
e Seu ZXing version juntos?
Sorry, my translator put text in portuguese.
In English.
Hello Bakjihun Imp.
I downloaded the APK and it works, but when I try to compile
source code, it’s not workin (do not read barcode).
I think it’s zxing problem.
It’s possible to create a zip package with zXing that you used?
Thanks.
Sorry for late reply, I was too busy for work.
Actually I’ve modified ZXing.Delphi somewhat, to support EAN-13 & EAN-8.
So it will not so simple to send you my version of ZXing.Delphi now.
But if you have some time I’ll let you know when I’ve done with it.
I guess it will take a week or more.
Hai jeehoon,
Nice share and thanks. I had test it and it looks great.
Please help me to send me your update xzing.delphi to my email chika.mamboo@gmail.com
Really appreciate for your help
Thank you so much.
Chika.
Great post and valuable knowledge. Thank you for publishing on how you modify ZXing.
I’m still waiting for your updates related EAN-13
Regards.
Ari.
안드로이드로 컴파일된 앱을 실행시켜서하면 EAN-13코드를 잘 인식합니다.
그런데 예제 소스를 컴파일해서 하면 인식이 안되더군요.
라이브러리 소스는 최근 github에 있는거 가져와서 앞 강좌에서 말씀하신 부분 수정해서 컴파일했습니다.
어떤 이유가 있을까요?
아니면 박지훈님이 쓰신 라이브러리 소스를 받아볼수 있을까요?
감사합니다.
mangchyda@naver.com
안드로이드apk 파일을 스마트폰에서 다운받아서 실행해보려하는데 열수없는 파일이라고 뜹니다.
알수없는 출처의 앱 설치도 허용했는데 무슨문제로 실행되지않는지 잘모르겠습니다.
답변 부탁드립니다.
후끈하군요..
역시 임프님…
Thanks, great blogposts.
I found recently this sample with autofocus working : https://github.com/flydev-fr/ZXing.Delphi.Demo