我一直在努力在Android上制作自定义相机活动,但是当旋转相机时,表面视图的纵横比会变得混乱.
在我的oncreate活动中,我设置了framelayout,它保存了显示摄像机参数的表面视图.
//FrameLayout that will hold the camera preview
FrameLayout previewHolder = (FrameLayout) findViewById(R.id.camerapreview);
//Setting camera's preview size to the best preview size
Size optimalSize = null;
camera = getCameraInstance();
double aspectRatio = 0;
if(camera != null){
//Setting the camera's aspect ratio
Camera.Parameters parameters = camera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
optimalSize = CameraPreview.getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
aspectRatio = (float)optimalSize.width/optimalSize.height;
}
if(optimalSize!= null){
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, (int)(getResources().getDisplayMetrics().widthPixels*aspectRatio));
previewHolder.setLayoutParams(params);
LayoutParams surfaceParams = new LayoutParams(LayoutParams.MATCH_PARENT, (int)(getResources().getDisplayMetrics().widthPixels*aspectRatio));
cameraPreview.setLayoutParams(surfaceParams);
}
cameraPreview.setCamera(camera);
//Adding the preview …
Run Code Online (Sandbox Code Playgroud) 我开发了一个小应用程序,用于全屏显示摄像头预览.我正在使用Camera API.
这是活动布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- This is the container for the camera preview screen -->
<FrameLayout android:id="@+id/camera_preview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
当设备处于纵向状态时,显示器将垂直缩放以匹配设备屏幕的高度 - 因此纵横比与本机相机的纵横比不同.这些是2张图片,更好地解释了我所说的内容:
第一张图像是使用原生相机设备制作的.第二张图片是用我的应用程序制作的,相机全屏 - 图像歪斜,拉伸以适应屏幕.
无论getSupportedPreviewSizes()
mehod 提供的预览尺寸和无失真,我都需要将相机预览设置为全屏.有没有办法实现这个目标?当相机预览全屏时,有没有办法保持适当的宽高比?我希望这可以通过操作系统自动完成 - 裁剪图像以匹配所请求的分辨率,同时保持宽高比,但这不会发生.
我试图使SurfaceView
显示器大于显示器(遵循这个问题:将相机预览适合大于显示器的SurfaceView),但在我的情况下不行,因为我捕获快照(6帧/秒)和那些不是用户在屏幕上看到的内容(框架包含所有相机预览,即使并非所有相机都在屏幕上可见).
我在这里发布:https://www.dropbox.com/s/3d52xt8kazynsae/CameraFullScreen.7z?v = 0mcn我做的整个项目.
任何想法/解决方案对我来说都非常重要.非常感谢.
================================================== ======================
由于ss1271答案更新:
我将分析你为三星Galaxy Ace II上面写的一些分辨率.
I.屏幕分辨率:480x800 - 宽高比3:5 = 0,6
II.getSupportedPreviewSizes
- 我几乎可以肯定这些值来自后置摄像头.以下是这些决议的方面比率:
2560x1920 - 0,75
2560x1536 - 0,60
2048x1536 - 0,75
2048x1232 - …
Run Code Online (Sandbox Code Playgroud) 我有一个自定义相机应用程序,我想要任何预览尺寸以全屏模式显示它而不拉伸相机预览图像.对于这一点,我需要做的surfaceView大于屏幕,以保持宽高比,所以实际上用户将看到小于照相机实际拍摄.
出于某种原因,我无法使SurfaceView
屏幕尺寸大于屏幕尺寸.
到目前为止我尝试过的:
调整surfaceChanged
方法中的相机预览
调整on onMeasure
方法中的相机预览
onLayout
FLAG_LAYOUT_NO_LIMITS
到活动 - 信息clipChildren
用于表面视图 - 信息android:layout_width="852px"
getWindow().setLayout(852, 1280);
在活动中但是没有任何成功 - 每次的行为都是一样的:它看起来好一秒钟,然后就会拉长.
这是代码:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final int CAMERA_ROTATE_ANGLE = 90;
private SurfaceHolder cameraHolder;
private Camera androidHardCamera;
private Context context;
public CameraPreview(Context context) {
super(context);
this.context = context;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is …
Run Code Online (Sandbox Code Playgroud) 我需要做的很简单,我想使用相机回调手动显示来自相机的预览,我想在真实设备上获得至少15fps.我甚至不需要颜色,我只需要预览灰度图像.来自相机的图像是YUV格式,你必须以某种方式处理它,这是主要的性能问题.我正在使用API 8.
在所有情况下,我都使用camera.setPreviewCallbackWithBuffer(),它比camera.setPreviewCallback()更快.如果我没有显示预览,我似乎无法在这里获得大约24 fps.所以没有问题.
我试过这些解决方案:
1.在SurfaceView上将相机预览显示为位图.它有效,但性能约为6fps.
baos = new ByteOutputStream();
yuvimage=new YuvImage(cameraFrame, ImageFormat.NV21, prevX, prevY, null);
yuvimage.compressToJpeg(new Rect(0, 0, prevX, prevY), 80, baos);
jdata = baos.toByteArray();
bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length); // Convert to Bitmap, this is the main issue, it takes a lot of time
canvas.drawBitmap(bmp , 0, 0, paint);
Run Code Online (Sandbox Code Playgroud)
2.在GLSurfaceView上将相机预览显示为纹理.这里我只显示亮度数据(灰度图像),这非常简单,每帧只需要一个arraycopy().我可以得到大约12fps,但我需要在预览中应用一些过滤器,看起来,它无法在OpenGL ES 1中快速完成.所以我不能使用这个解决方案.另一个问题中的一些细节.
3.使用NDK在(GL)SurfaceView上显示相机预览以处理YUV数据.我在这里找到了一个使用一些C函数和NDK 的解决方案.但我没有设法使用它,这里有更多细节.但无论如何,这个解决方案是为了返回ByteBuffer在OpenGL中将其显示为纹理,并且它不会比之前的尝试更快.所以我必须修改它以返回int []数组,可以使用canvas.drawBitmap()绘制,但我不理解C足以执行此操作.
那么,我有没有其他方法可以避免或尝试一些改进?
我想有效地为相机预览做一个简单的数码变焦,所以我想我只需要将SurfaceView的大小调整为大于屏幕.其他问题(例如3813049)似乎表明这很容易,所以我创建了下面的示例代码,我希望让我只能看到水平图像的一半(因为SurfaceView的宽度是屏幕的两倍)并且具有图像只占水平屏幕的一半.但是,运行它(当我的Thunderbolt上使用Android 2.2.1定位到SDK版本4时)可以在水平填充屏幕时水平查看整个图像.SurfaceView似乎垂直行为(当我使它小于屏幕时),但Android不允许我使SurfaceView大于屏幕.
如何实现数码变焦?(不,我不能使用Camera.Parameters.setZoom;不仅Android 1.6不支持这种功能,而且不同的相机支持和实现这一点不同)
public class MagnifyTestActivity extends Activity implements SurfaceHolder.Callback {
private MagnificationView mPreview;
private SurfaceHolder mHolder;
private Camera mCamera = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPreview = new MagnificationView(this);
setContentView(mPreview);
mHolder = mPreview.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public class MagnificationView extends SurfaceView {
public MagnificationView(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth()*2;
int height = display.getHeight()/2;
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
heightMeasureSpec …
Run Code Online (Sandbox Code Playgroud) 我想在观看youtube视频时记录用户的反应,因此屏幕上会有两个视频同时被录制.一个是摄像机视频(反应视频),其他一个是YouTube视频(反应).
below should be recorded as one video
__________________________
| |
| Camera Video |
| |
| __________|
| | Youtube |
| | Video |
---------------------------
Run Code Online (Sandbox Code Playgroud)
一些类似的问题与我的问题无关,但回答了我的问题中提到的一些要点.Q1,Q2,Q3
请建议一些方法来解决这个问题,我该如何实现它.