Android 用相机拍照并获取位图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23921128/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Take a picture with camera and get bitmap
提问by moobi
I am working on an app for android that uses the front facing camera to simulate a mirror for the user. I need the app to take a picture every 5 seconds as a bitmap(automatically and without user interaction), which I then combine with another bitmap later on.
我正在开发一个 android 应用程序,它使用前置摄像头为用户模拟镜子。我需要应用程序每 5 秒拍摄一张图片作为位图(自动且无需用户交互),然后我稍后将其与另一个位图组合。
The difficult part for me: How to take a picture and get it as a bitmap?
对我来说困难的部分:如何拍照并将其作为位图?
I tried several solutions, but none have worked yet.
我尝试了几种解决方案,但都没有奏效。
The other question that this is marked as a duplicate for is for doing this manually and not automatically.
另一个被标记为重复的问题是手动而不是自动执行此操作。
回答by mremremre1
I used the following code to show live camera feed in a layout background and the button saves the image as jpeg. Try and modify it as you wish : You can download the entire test project here so that you can test it fast : http://www.4shared.com/rar/v-ZQPybcce/Test.html
我使用以下代码在布局背景中显示实时摄像头馈送,并且该按钮将图像保存为 jpeg。根据需要尝试和修改它:您可以在此处下载整个测试项目,以便您可以快速进行测试:http: //www.4shared.com/rar/v-ZQPybcce/Test.html
--->>The difference of this code from others using intents is that it takes the picture automatically without opening the camera app which makes the app look better :) <----
--->>此代码与其他使用意图的代码的不同之处在于它无需打开相机应用程序即可自动拍照,这使应用程序看起来更好:) <----
package com.mreprogramming.test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
public class CameraActivity extends Activity implements SurfaceHolder.Callback{
protected static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 0;
private SurfaceView SurView;
private SurfaceHolder camHolder;
private boolean previewRunning;
private Button button1;
final Context context = this;
public static Camera camera = null;
private ImageView camera_image;
private Bitmap bmp,bmp1;
private ByteArrayOutputStream bos;
private BitmapFactory.Options options,o,o2;
private FileInputStream fis;
ByteArrayInputStream fis2;
private FileOutputStream fos;
private File dir_image2,dir_image;
private RelativeLayout CamView;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
CamView = (RelativeLayout) findViewById(R.id.camview);
SurView = (SurfaceView)findViewById(R.id.sview);
camHolder = SurView.getHolder();
camHolder.addCallback(this);
camHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
button1 = (Button)findViewById(R.id.button_1);
camera_image = (ImageView) findViewById(R.id.camera_image);
button1.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
button1.setClickable(false);
button1.setVisibility(View.INVISIBLE); //<-----HIDE HERE
camera.takePicture(null, null, mPicture);
}
});
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if(previewRunning){
camera.stopPreview();
}
Camera.Parameters camParams = camera.getParameters();
Camera.Size size = camParams.getSupportedPreviewSizes().get(0);
camParams.setPreviewSize(size.width, size.height);
camera.setParameters(camParams);
try{
camera.setPreviewDisplay(holder);
camera.startPreview();
previewRunning=true;
}catch(IOException e){
e.printStackTrace();
}
}
public void surfaceCreated(SurfaceHolder holder) {
try{
camera=Camera.open();
}catch(Exception e){
e.printStackTrace();
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
finish();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera=null;
}
public void TakeScreenshot(){
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
int nu = preferences.getInt("image_num",0);
nu++;
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("image_num",nu);
editor.commit();
CamView.setDrawingCacheEnabled(true);
CamView.buildDrawingCache(true);
bmp = Bitmap.createBitmap(CamView.getDrawingCache());
CamView.setDrawingCacheEnabled(false);
bos = new ByteArrayOutputStream();
bmp.compress(CompressFormat.JPEG, 100, bos);
byte[] bitmapdata = bos.toByteArray();
fis2 = new ByteArrayInputStream(bitmapdata);
String picId=String.valueOf(nu);
String myfile="MyImage"+picId+".jpeg";
dir_image = new File(Environment.getExternalStorageDirectory()+
File.separator+"My Custom Folder");
dir_image.mkdirs();
try {
File tmpFile = new File(dir_image,myfile);
fos = new FileOutputStream(tmpFile);
byte[] buf = new byte[1024];
int len;
while ((len = fis2.read(buf)) > 0) {
fos.write(buf, 0, len);
}
fis2.close();
fos.close();
Toast.makeText(getApplicationContext(),
"The file is saved at :/My Custom Folder/"+"MyImage"+picId+".jpeg",Toast.LENGTH_LONG).show();
bmp1 = null;
camera_image.setImageBitmap(bmp1);
camera.startPreview();
button1.setClickable(true);
button1.setVisibility(View.VISIBLE);//<----UNHIDE HER
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
dir_image2 = new File(Environment.getExternalStorageDirectory()+
File.separator+"My Custom Folder");
dir_image2.mkdirs();
File tmpFile = new File(dir_image2,"TempImage.jpg");
try {
fos = new FileOutputStream(tmpFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
}
options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
bmp1 = decodeFile(tmpFile);
bmp=Bitmap.createScaledBitmap(bmp1,CamView.getWidth(), CamView.getHeight(),true);
camera_image.setImageBitmap(bmp);
tmpFile.delete();
TakeScreenshot();
}
};
public Bitmap decodeFile(File f) {
Bitmap b = null;
try {
// Decode image size
o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
fis = new FileInputStream(f);
BitmapFactory.decodeStream(fis, null, o);
fis.close();
int IMAGE_MAX_SIZE = 1000;
int scale = 1;
if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
scale = (int) Math.pow(
2,
(int) Math.round(Math.log(IMAGE_MAX_SIZE
/ (double) Math.max(o.outHeight, o.outWidth))
/ Math.log(0.5)));
}
// Decode with inSampleSize
o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
fis = new FileInputStream(f);
b = BitmapFactory.decodeStream(fis, null, o2);
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
return b;
}
}
This is the camera.xml
这是camera.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/camview">
<SurfaceView
android:id="@+id/sview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
<ImageView
android:id="@+id/camera_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/app_name" />
<Button
android:id="@+id/button_1"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
Add this to your manifest :
将此添加到您的清单中:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Also in the manifest add the following to the "CameraActivity" activity tab to make sure that your activity will always be in landscape orientation because otherwise holding the phone in protrait(upright) unless you change the code it will reverse the image's aspect ratio and severely distort it.
同样在清单中,将以下内容添加到“CameraActivity”活动选项卡以确保您的活动始终处于横向状态,否则将手机保持直立(直立),除非您更改代码,否则它将反转图像的纵横比并严重扭曲它。
<activity
android:name="com.mreprogramming.test.CameraActivity"
android:label="@string/app_name"
android:screenOrientation="landscape" > <-------ADD THIS ---!!!!!
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
And save this as styles.xml to make your layout fullscreen
并将其保存为 styles.xml 以使您的布局全屏
<resources>
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.NoTitleBar.Fullscreen">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="android:Theme.NoTitleBar.Fullscreen">
<item name="android:windowFullscreen">true</item>
<item name="android:windowNoTitle">true</item>
</style>
In my app i want the image to capture every view of the layout not just the camera feed like this :
在我的应用程序中,我希望图像捕捉布局的每个视图,而不仅仅是像这样的相机提要:
The test code I posted here hides the capture button so that it wont appear in your photo. If you have more views in your app and don't won't them to show in the photo either hide them while capturing (see code to know where to hide) or edit the code.
我在这里发布的测试代码隐藏了捕获按钮,因此它不会出现在您的照片中。如果您的应用程序中有更多视图并且不想在照片中显示它们,请在捕获时隐藏它们(请参阅代码以了解隐藏位置)或编辑代码。
------>To sum up my post this code can do the basic capturing and saving a jpeg but if you want professional images you need to edit it a bit. Good Luck :)<------
------>总结我的帖子,这段代码可以做基本的捕获和保存jpeg,但如果你想要专业的图像,你需要稍微编辑一下。祝你好运:)<------
回答by Augusto Picciani
I don't know if this solution is what you want. However the basics to take a picture as bitmap should be like this:
我不知道这个解决方案是否是你想要的。但是,将图片拍摄为位图的基础知识应该是这样的:
private static final int CAMERA_REQUEST = 1888; // field
private void takePicture(){ //you can call this every 5 seconds using a timer or whenever you want
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
Bitmap picture = (Bitmap) data.getExtras().get("data");//this is your bitmap image and now you can do whatever you want with this
imageView.setImageBitmap(picture); //for example I put bmp in an ImageView
}
}
Don't forget to set permission for camera in your Manifest:
不要忘记在您的清单中设置相机权限:
<uses-feature android:name="android.hardware.camera" />
回答by MJ93
You should first take the picture by using an IMAGE_CAPTURE
Intent
您应该首先使用 IMAGE_CAPTURE
Intent
Then you will want to create a temporary file to store the photo at so it doesn't use all of the memory on the phone.
然后,您需要创建一个临时文件来存储照片,这样它就不会占用手机上的所有内存。
After that, grab the Bitmap using android.provider.MediaStore.Images.Media.getBitmap()
and select the temporary file.
之后,使用抓取位图android.provider.MediaStore.Images.Media.getBitmap()
并选择临时文件。
Here is a full code example on how to do it:
这是有关如何执行此操作的完整代码示例: