Grafika 的 CameraCaptureActivity - 预览尺寸变化时相机预览失真
Grafika's CameraCaptureActivity - camera preview distorted on preview size change
我提到了 Grafika's CameraCaptureActivity 在录制视频的同时显示相机预览。
我对代码所做的更改(相关)是 -
用户单击按钮启动 PreferencesActivity
,选择首选相机分辨率(存储 width
和 height
值)并单击 "Back" 按钮return 到 CameraCaptureActivity
。
在 openCamera
方法中- 我不是硬编码 width
和 height
,而是从 SharedPreferences
中选取值
AspectFrameLayout's
属性是这样设置的 android:background="@android:color/holo_blue_bright"
。所以预览匹配 AspectFrameLayout
的大小
此问题主要发生在将尺寸从较大的分辨率更改为较小的分辨率时。
在较小的屏幕上 (HTC One M7 / Xperia SP)
在更大的屏幕上 (Samsung Galaxy Tab S / Nexus 9) -
我注意到发生这种情况是因为 onSurfaceChanged
被调用了两次。第一次是 width
和 height
的错误值,第二次是正确的值。
但是,如果我离开 activity 并在不做任何更改的情况下返回它,布局看起来不错。 (比如转到 PreferencesActivity
并单击 "Back" 而不更改分辨率。)
我在 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>
我确定我传递了正确的值来设置视图的宽度和高度,因为如果我离开 activity 并返回它而不做任何更改,预览设置正确。 (比如转到另一个 activity 并单击 "Back" 到 return 到 CameraCaptureActivity
。)
用这个打开相机
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI);
startActivityForResult(i, CAMERA_RESULT);
这是 MyFileContentProvider class
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);
此方法不会让您调整大小后的图像失真。
希望对你有帮助。
我不清楚你想说什么如果问题出在预览..那么你可以在你的打开相机方法中使用以下代码
在你的 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);
}
我提到了 Grafika's CameraCaptureActivity 在录制视频的同时显示相机预览。
我对代码所做的更改(相关)是 -
用户单击按钮启动 PreferencesActivity
,选择首选相机分辨率(存储 width
和 height
值)并单击 "Back" 按钮return 到 CameraCaptureActivity
。
在 openCamera
方法中- 我不是硬编码 width
和 height
,而是从 SharedPreferences
AspectFrameLayout's
属性是这样设置的 android:background="@android:color/holo_blue_bright"
。所以预览匹配 AspectFrameLayout
此问题主要发生在将尺寸从较大的分辨率更改为较小的分辨率时。
在较小的屏幕上 (HTC One M7 / Xperia SP)
在更大的屏幕上 (Samsung Galaxy Tab S / Nexus 9) -
我注意到发生这种情况是因为 onSurfaceChanged
被调用了两次。第一次是 width
和 height
的错误值,第二次是正确的值。
但是,如果我离开 activity 并在不做任何更改的情况下返回它,布局看起来不错。 (比如转到 PreferencesActivity
并单击 "Back" 而不更改分辨率。)
我在 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>
我确定我传递了正确的值来设置视图的宽度和高度,因为如果我离开 activity 并返回它而不做任何更改,预览设置正确。 (比如转到另一个 activity 并单击 "Back" 到 return 到 CameraCaptureActivity
。)
用这个打开相机
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI);
startActivityForResult(i, CAMERA_RESULT);
这是 MyFileContentProvider class
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);
此方法不会让您调整大小后的图像失真。 希望对你有帮助。
我不清楚你想说什么如果问题出在预览..那么你可以在你的打开相机方法中使用以下代码
在你的 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);
}