我有一个活动作为FrameLayout
布局,作为片段的容器视图。这个片段包含一个SurfaceView,我在其SurfaceHolder中显示相机预览。
使用PhotoHandler
回调调用相机的SurfaceView takePicture点击/点击,实现PictureCallback
。重写的方法onPictureTaken
接收包含图像数据的字节数组,它使用FileOutputStream存储。
我将活动限制为纵向(在清单中),并使用方法setCameraDisplayOrientation
(在stackoverflow上找到),它也会以纵向显示相机预览。
一切都很顺利......除了两件事:
所以我的问题是
我可以提高图像质量(全尺寸)吗?
我可以确保生成的图像文件有纵向吗?
以下是我的一些代码
的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.xxxxxxxxxxxxxxx" >
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".xxxxxxxxxx"
android:label="@string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
onPictureTaken
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Toast.makeText(context, "Can't create directory to save image.",
Toast.LENGTH_LONG).show();
return;
}
String filename = pictureFileDir.getPath() + File.separator + photoFile;
File pictureFile = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (Exception error) {
Toast.makeText(context, "Image could not be saved.",
Toast.LENGTH_LONG).show();
}
}
如果您还有其他需要,请告诉我......
编辑:我找到了尺寸问题的解决方案(见下面的答案)。但我仍然有旋转结果图像文件的问题。经过大量测试后,我得到的印象是,即使以纵向模式拍摄,图像也始终以横向格式存储。也许文件中的一些EXIF信息将其标记为肖像......我一直在测试,但您仍然可以在这里帮助我: - )
EDIT2:关于Exif信息的想法似乎是正确的起点。标准方向(至少在我手机的相机上)似乎是“风景向左旋转90度”。至少,这是图像文件的Exif信息告诉我的内容:图像的第0行位于顶部,第0列位于左侧(TAG_ORIENTATION为1)
即使我明确地以纵向模式拍摄照片,Exif信息也没有反映出来。它似乎“认为”图像处于横向模式,所以我必须向右旋转90度才能显示它。这似乎对我来说是错误的...我怎样才能确保图像中的Exif信息反映出相机/应用程序的方向? (TAG_ORIENTATION显然应该是6)
不要误会我的意思:我仍然需要向右旋转90度,但是Exif信息的TAG_ORIENT会告诉我这样做。目前,我必须依赖于我对照片拍摄方式的了解。
请参阅: Android: Bitmaps loaded from gallery are rotated in ImageView
和: http://sylvana.net/jpegcrop/exif_orientation.html
EDIT3:解决方案......见下文
答案 0 :(得分:4)
好的,我能够至少解决尺寸问题。我发现了PictureSize
参数,我可以根据手机/相机的功能设置所需的最终图像尺寸
Camera.Parameters params = camera.getParameters();
List<Camera.Size> sizeList = params.getSupportedPictureSizes();
int chosenSize = Helper.getPictureSizeIndexForHeight(sizeList, 800);
params.setPictureSize(sizeList.get(chosenSize).width, sizeList.get(chosenSize).height);
camera.setParameters(params);
和Helper方法帮助我选择最小高度的图片大小比第二个参数(或最大可用大小)更好
public static int getPictureSizeIndexForHeight(List<Camera.Size> sizeList, int height) {
int chosenHeight = -1;
for(int i=0; i<sizeList.size(); i++) {
if(sizeList.get(i).height < height) {
chosenHeight = i-1;
if(chosenHeight==-1)
chosenHeight = 0;
break;
}
}
return chosenHeight;
}
这样可行,但我有旋转图像结果文件的问题
编辑:我发现我需要设置另一个名为Rotation
的参数,具体取决于手机方向和UI方向。在这种情况下,手机将设置正确的exif信息,以便在以肖像方式拍摄时图像不会以横向显示。我不再需要旋转,图像也会在相册中正确显示。
public static void setRotationParameter(Activity activity, int cameraId, Camera.Parameters param) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
rotation = (rotation + 45) / 90 * 90;
int toRotate = (info.orientation + rotation) % 360;
param.setRotation(toRotate);
}