最近在搞一个关于条形码扫描的软件,需求需要扫描时是竖屏。
最后在zxing官方wiki上面找到解决办法。基本思路如下。
There are 4 relative files:
1, manifest.xml, you need to make CaptureActivity portrait.
2, DecodeHandler.java, rotate data before buildLuminanceSource, it works becuase in YCbCr_420_SP and YCbCr_422_SP, the Y channel is planar and appears first
//decode()方法中
1 |
byte [] rotatedData = new byte [data.length]; |
2 |
for ( int y = 0 ; y < height; y++) { |
3 |
for ( int x = 0 ; x < width; x++) |
4 |
rotatedData[x * height + height - y - 1 ] = data[x + y * width]; |
3, CameraManager.java, getFramingRectInPreview() need to be modified.
1 |
rect.left = rect.left * cameraResolution.y / screenResolution.x; |
2 |
rect.right = rect.right * cameraResolution.y / screenResolution.x; |
3 |
rect.top = rect.top * cameraResolution.x / screenResolution.y; |
4 |
rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y; |
4, CameraConfigurationManager.java, set camera orientation to portrait in setDesiredCameraParameters() use
1 |
parameters.set( "orientation" , "portrait" ); |
注:版本兼容请看下面。
and in getCameraResolution(), you need to swap x and y, because camera preview size is something like 480*320, other than 320*480.
1 |
int tmp = cameraResolution.x; |
2 |
cameraResolution.x = cameraResolution.y; |
3 |
cameraResolution.y = tmp; |
4 |
return cameraResolution; |
说明:
关于摄像头旋转90度的时候,不同的sdk版本方法不同。
兼容方法如下
01 |
if (Integer.parseInt(Build.VERSION.SDK) >= <img src= "http://www.andcoder.com/wp-includes/images/smilies/icon_cool.gif" alt= "8)" class = "wp-smiley" > |
02 |
setDisplayOrientation(camera, 90 ); |
04 |
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { |
05 |
parameters.set( "orientation" , "portrait" ); |
06 |
parameters.set( "rotation" , 90 ); |
08 |
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { |
09 |
parameters.set( "orientation" , "landscape" ); |
10 |
parameters.set( "rotation" , 90 ); |
14 |
protected void setDisplayOrientation(Camera camera, int angle) { |
15 |
Method downPolymorphic; |
17 |
downPolymorphic = camera.getClass().getMethod( |
18 |
"setDisplayOrientation" , new Class[] { int . class }); |
19 |
if (downPolymorphic != null ) |
20 |
downPolymorphic.invoke(camera, new Object[] { angle }); |
21 |
} catch (Exception e1) { |
感谢原作者,转载自:http://www.andcoder.com/archives-2011-10-383.html#comment-95
上面的方法可以解决摄像头竖屏的时候失真的问题,但图像在竖屏的时候还是90度倾斜,再设置一下图像的显示就可以了。
同时还有一个高手的分析,也挺好,图画的不错:
我在做Android照相机研究时曾写过关于照相机摄像头的成像研究报告,在此我对报告重写,以作为照相机竖屏问题研究的讨论引导,起抛砖引玉作用。
经过我的查证和实验,可以证实:Android提供的SDK(android.hardware.Camera)里大概不能正常的使用竖屏(portrait layout)加载照相机,当用竖屏模式加载照相机时会产生以下情况:1. 照相机成像左倾90度(倾斜);2. 照相机成像长宽比例不对(失比)。之所以是“大概”,原因是因为可能可以通过一些比较复杂的手段解决。如果以上成立,那为什么竖屏不能正常成像也就很显然了。为什么会产生这样的情况,请看下面的研究分析。
照相机在一般情况下是必须用landscape layout(横屏)的,可以证明,先写一个照相机(只要能preview就行),如果Manifest的activity里不加入android:screenOrientation="landscape",即默认了 android:screenOrientation="portrait"(竖屏),照相机preview时就会出现左倾90度的现象,并且失比。原因是这样的(我推测的),摄像头对照物的映射是Android底层固定了的,以landscape方式为正,并且产生大小为320*480的像,如果换成portrait方式了,摄像头还是产生320*480的像,然后分别对应的放入到一个480*320的屏内,显然会失比,然后根据竖、横屏的规则,就产生了左倾90度的情况(图例见左)。为了进一步证实我对失比原因的推测,我照相机内加载的SurfaceView调成了320*213,比例大概是(320:213)*1.5=(480:320),所成像结果如愿的形成左倾但是没有失比的状况,这就证实了我的想法。
综上可以看出,左倾是因为摄像头映射产生的,而失比是由于像素比例映射产生的。OK,这就是我的研究引导,欢迎朋友们留言讨论以及分享想法,或者提出解决竖屏的解决方法,谢谢