【问题标题】:Grafika's CameraCaptureActivity - camera preview distorted on preview size changeGrafika 的 CameraCaptureActivity - 相机预览在预览大小变化时失真
【发布时间】:2015-02-12 14:41:46
【问题描述】:

我参考了Grafika's CameraCaptureActivity 来录制视频,同时显示相机预览。

我对代码所做的更改(相关)是 -

用户单击按钮启动PreferencesActivity,选择首选相机分辨率(存储widthheight 值)并单击“返回”按钮返回CameraCaptureActivity

openCamera 方法中——我不是硬编码widthheight,而是从SharedPreferences 中选择值

AspectFrameLayout's 属性以这种方式设置android:background="@android:color/holo_blue_bright"。所以预览与AspectFrameLayout的大小相匹配

此问题主要发生在将尺寸从较大分辨率更改为较小分辨率时。

在较小的屏幕中(HTC One M7 / Xperia SP)

在更大的屏幕上(三星 Galaxy Tab S / Nexus 9) -

我注意到发生这种情况是因为onSurfaceChanged 被调用了两次。第一次是 widthheight 的值错误,第二次是正确的值。

但是,如果我离开活动并返回它而不做任何更改,布局看起来很好。 (例如转到PreferencesActivity 并单击“返回”而不更改分辨率。)

我在AndroidManifest.xml中设置了以下内容 -

<activity android:name=".activity.camera.CameraCaptureActivity"
 android:launchMode="singleInstance"
 android:screenOrientation="landscape"
 android:theme="@android:style/Theme.Holo.Light.NoActionBar">
</activity>

编辑:只有预览会出现此问题。录制的视频大小正确。

编辑 2:这是我的 layout.xml

    <RelativeLayout xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cameracapturescreen_rootparent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
tools:context="com.myapp.CameraCaptureActivity">

<com.myapp.activity.camera.PreviewFrameLayout
    android:id="@+id/surfaceview_framelayout"
    android:layout_width="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_centerVertical="true"
    android:background="@android:color/holo_blue_bright"
    android:layout_height="wrap_content">

    <android.opengl.GLSurfaceView
        android:id="@+id/cameraPreview_surfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="left"/>

</com.myapp.activity.camera.PreviewFrameLayout>

我确信我传递了正确的值来设置视图的宽度和高度,因为如果我离开活动并返回它而不做任何更改,预览设置正确。 (比如去另一个活动并点击“返回”返回CameraCaptureActivity。)

【问题讨论】:

  • 请添加您的 sn-p,这就是为什么我可以实际找到您的问题
  • 你在使用这个活动的 opengl 部分吗.. 那里写有着色器程序.. 这会让你的应用表现得像 thta
  • @VishalPatel :代码位于我在问题第一行给出的链接中。
  • @PreethiRao :是的,我正在使用 OpenGL 部分。我会研究一下着色器程序,看看我能不能解决这个问题。

标签: android android-camera surfaceview grafika


【解决方案1】:

如果问题出在预览中,我不清楚您要说什么......那么您可以在打开相机方法中使用以下代码

在你的 openCamera() 方法中添加这个东西代码,我刚刚检查过这个......希望这会有所帮助

    if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
        mCamera.setDisplayOrientation(90);
    } else {
        mCamera.setDisplayOrientation(180);
    }

在您的 handleSetSurfaceTexture() 方法中添加此代码

    if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
        mCamera.setDisplayOrientation(90);
     } else {
        mCamera.setDisplayOrientation(180);
    }
          Camera.Parameters parms = mCamera.getParameters();

          CameraUtils.choosePreviewSize(parms, mCameraPreviewWidth, mCameraPreviewHeight);

          // Give the camera a hint that we're recording video.  This   can have a big
          // impact on frame rate.
          parms.setRecordingHint(true);
          mCamera.setParameters(parms);

以及您的 onPause() 中的这部分代码

InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(((EditText)findViewById(R.id.username)).getWindowToken(), 0);

if(imm.isAcceptingText()) {
Intent intent = new Intent(this, CameraCaptureActivity.class);
startActivity(intent);
}

【讨论】:

  • 是的,此代码已经存在,问题在于预览。录制的视频很好。就像我在问题中所说的那样,onSurfaceChanged 被调用了两次,第一次是表面的高度和宽度的任意值。这导致 Surface 宽度和高度被设置为第一组错误(和更低)的值。
  • @ShreyaBS 我不认为这会导致问题,因为第二次将使用正确的值调用它,一旦我们旋转预览,我们就会遇到同样的问题,这是 opengl 部分的问题。 .. 尝试检查 Texture2dProgram 类。
  • 并检查 camerasurfacehandler onDrawframe 方法。在此检查中使用 fullScreen 对象
  • 是的,如果方向改变,我会遇到这个问题。我检查了 OnDrawFrame 中的 FullScreen 对象,它得到了正确的宽度和高度值。我不确定要在 Texture2DProgram 类中检查什么。我没有使用任何着色器。我使用的唯一程序类型是“TEXTURE_EXT”我应该修改什么?
  • 是的!发生此问题是因为在启动 CameraCaptureActivity 时,前一个屏幕的软键盘仍处于打开状态。关闭它可以更正预览大小。谢谢。
【解决方案2】:

用这个打开相机

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);    
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI); 
startActivityForResult(i, CAMERA_RESULT);

这里是 MyFileContentProvider 类

public class MyFileContentProvider extends ContentProvider {

 public static final Uri CONTENT_URI = Uri.parse("content://com.algorithmapps.dmsimagesave/");

 private static final HashMap<String, String> MIME_TYPES = new         HashMap<String, String>();

 static {

  MIME_TYPES.put(".jpg", "image/jpeg");

  MIME_TYPES.put(".jpeg", "image/jpeg");

 }

 @Override

 public boolean onCreate() {

  try {

   File mFile = new File(getContext().getFilesDir(), "newImage.jpg");

   if(!mFile.exists()) {

mFile.createNewFile();

   }

   getContext().getContentResolver().notifyChange(CONTENT_URI, null);

   return (true);

  } catch (Exception e) {

   e.printStackTrace();

   return false;

  }

 }

 @Override

 public String getType(Uri uri) {

  String path = uri.toString();

  for (String extension : MIME_TYPES.keySet()) {

   if (path.endsWith(extension)) {

    return (MIME_TYPES.get(extension));

   }

  }

  return (null);

 }

 @Override

 public ParcelFileDescriptor openFile(Uri uri, String mode)

 throws FileNotFoundException {

  File f = new File(getContext().getFilesDir(), "newImage.jpg");

  if (f.exists()) {

   return (ParcelFileDescriptor.open(f,

     ParcelFileDescriptor.MODE_READ_WRITE));

  }

  throw new FileNotFoundException(uri.getPath());

 }

 @Override

 public Cursor query(Uri url, String[] projection, String selection,

   String[] selectionArgs, String sort) {

  throw new RuntimeException("Operation not supported");

 }

 @Override

 public Uri insert(Uri uri, ContentValues initialValues) {

  throw new RuntimeException("Operation not supported");

 }

 @Override

 public int update(Uri uri, ContentValues values, String where,

   String[] whereArgs) {

  throw new RuntimeException("Operation not supported");

 }

 @Override

 public int delete(Uri uri, String where, String[] whereArgs) {

  throw new RuntimeException("Operation not supported");

 }

} 

在 onActivityResultMethod 中得到这样的图像

 if (resultCode == RESULT_OK && requestCode == CAMERA_RESULT) {

       File out = new File(getFilesDir(), "newImage.jpg");

         if(!out.exists()) {

                Toast.makeText(getBaseContext(),

                  "Error while capturing image", Toast.LENGTH_LONG)

                  .show();


       }             
          originalBitmap = BitmapFactory.decodeFile(out.getAbsolutePath());   
    }

比使用此代码调整位图大小,这里我调整为 200 宽度 * 200 高度

BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;

Bitmap resizedBitmap = Bitmap.createScaledBitmap(originalBitmap, 200, 200, false);

此方法不会让您调整大小的图像失真。 希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 2023-04-03
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多