这里先给出zxing包的源码地址
zip包:https://codeload.github.com/zxing/zxing/zip/master
Github:https://github.com/zxing/zxing
包可能较大,因为包含了其它平台的源码,这里主要分析Android平台
首先说一下zxing包中扫描实现的是被固定为横屏模式,在不同的手机屏幕下可能会出现图像变形情况,近日得空,研究了一下,首先分析一下源码Barcode scanner中的一些问题。
- 首先解释设置为横屏模式的原因,android手机中camera 在我们调用的时候,他的成像是被顺时针旋转90°的,在Barcode scanner中并没有对camera旋转,因此成像在横向手机屏幕上才是正常方向,camera的成像一般来说,宽比高的值要大,如果想让手机方向切换为其它模式时,若要显示成像正常,则可以调用setDisplayOrientation(度数)方法,参数中应该设置的参数与getWindowManager().getDefaultDisplay().getRotation()中得到的不同,可参考下面的代码。
public int getOrientationDegree() { int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation(); switch (rotation) { case Surface.ROTATION_0: return 90; case Surface.ROTATION_90: return 0; case Surface.ROTATION_180: return 270; case Surface.ROTATION_270: return 180; default: return 0; } }
-
关于部分手机屏幕可能会变形问题,大家知道不同的手机,摄像头的像素数是不同的,这里列出部分1920x1080,1280x960,1280x720,960x720,864x480,800x480,720x480,768x432,640x480,576x432,480x320,384x288,352x288,320x240,这些列出的都是camera所支持的宽x高的大小,想知道camera支持哪些像素大小可通过Camera.Parameters.getSupportedPreviewSizes()方法得到支持的列表。camera成像以后要在surfaceView上显示,成像会变形的原因就是camera设置的像素参数的大小,与surfaceView的长宽比不相同,camera在preview时,会自动填充满surfaceView,导致我们看到的成像变形
- Camera在preview时,我们自然就可以去取我们看到的成像,当然我们只是取框中的一部分,那么我们就要计算框的位置及大小,下面先看源码中的计算方法
<resources> <style name="CaptureTheme" parent="android:Theme.Holo"> <item name="android:windowFullscreen">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowActionBarOverlay">true</item> <item name="android:windowActionModeOverlay">true</item> </style> </resources>
<com.google.zxing.client.android.ViewfinderView android:id="@+id/viewfinder_view" android:layout_width="fill_parent" android:layout_height="fill_parent"/>
/** * 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 */ 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; }
源码中,我们可以看到应用的主题是全屏模式,因此计算取成像大小的时候用的是屏幕的大小,首先是得到屏幕中ViewfinderView的框的大小,也就是我们在屏幕上看到的大小,然后根据camera与屏幕的比值去计算camera中应该取图像的大小。
/** * A factory method to build the appropriate LuminanceSource object based