我正在开发一款Android应用,它使用前置摄像头为用户模拟镜像。我需要应用程序每隔5秒拍一张照片作为位图(自动且无需用户交互),然后我将其与另一个位图结合使用。
对我来说困难的部分:如何拍照并将其作为位图?
我尝试了几种解决方案,但还没有一种解决方案。
另一个标记为重复的问题是手动而不是自动执行此操作。
答案 0 :(得分:7)
我使用以下代码在布局背景中显示实时相机输入,该按钮将图像保存为jpeg。根据需要尝试修改它: 您可以在此处下载整个测试项目,以便快速测试: http://www.4shared.com/rar/v-ZQPybcce/Test.html
--->>此代码与使用意图的其他代码的不同之处在于,无需打开相机应用程序即可自动拍照,从而使应用看起来更好:)< ----
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;
}
}
这是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" />
将此添加到您的清单:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
同样在清单中,将以下内容添加到“CameraActivity”活动标签中,以确保您的活动始终处于横向,因为除非您更改代码,否则将手机保持在protrait(直立),这将反转图像的方面比例并严重扭曲它。
<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>
并将其保存为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>
在我的应用程序中,我希望图像捕获布局的每个视图,而不仅仅是像这样的相机Feed:
我在此处发布的测试代码隐藏了捕获按钮,因此它不会出现在您的照片中。如果你的应用程序中有更多的视图,并且它们不会在照片中显示,则在捕获时隐藏它们(请参阅代码以了解隐藏的位置)或编辑代码。
------&gt;总结我的帖子这段代码可以做基本的捕捉和保存jpeg,但如果你想要专业的图像,你需要稍微编辑一下。祝你好运:)&lt; ------
答案 1 :(得分:1)
我不知道这个解决方案是否符合您的要求。然而,将图片作为位图拍摄的基础应该是这样的:
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
}
}
不要忘记在Manifest中设置相机权限:
<uses-feature android:name="android.hardware.camera" />
答案 2 :(得分:-1)
您应首先使用IMAGE_CAPTURE
Intent
然后,您需要创建一个临时文件来存储照片,这样就不会使用手机上的所有内存。
之后,使用android.provider.MediaStore.Images.Media.getBitmap()
获取位图并选择临时文件。
以下是有关如何执行此操作的完整代码示例: