我正在尝试使用相机的连拍模式构建一个小型照片应用。主要思想是每0.3秒拍摄一张图片,并将图片存储在一个数组中,直到拍完最后一张照片。应指定要拍摄的照片数量。
我每2秒只能拍一张照片。最短的间隔。然后,当应该将图片写入存储时,应用程序会崩溃。
有人知道如何实现这个吗?这是我的代码:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
public class CamaeaView extends Activity implements SurfaceHolder.Callback, OnClickListener {
static final int FOTO_MODE = 1;
private static final String TAG = "Test";
Camera mCamera;
boolean mPreviewRunning = false;
private Context mContext = this;
ArrayList<Object> listImage = null;
public static ArrayList<Object> List1[];
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Log.e(TAG, "onCreate");
@SuppressWarnings("unused")
Bundle extras = getIntent().getExtras();
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
mSurfaceView.setOnClickListener(this);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {
Log.d("Start: ","Imagelist");
Intent mIntent = new Intent();
listImage.add(StoreByteImage(imageData));
SaveImage(listImage);
mCamera.startPreview();
setResult(FOTO_MODE, mIntent);
finish();
}
};
protected void onResume() {
Log.d(TAG, "onResume");
super.onResume();
}
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
protected void onStop() {
Log.e(TAG, "onStop");
super.onStop();
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surfaceCreated");
mCamera = Camera.open();
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.d(TAG, "surfaceChanged");
// XXX stopPreview() will crash if preview is not running
if (mPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters p = mCamera.getParameters();
p.setPreviewSize(w, h);
p.setPictureSize(1024, 768);
p.getSupportedPictureFormats();
p.setPictureFormat(PixelFormat.JPEG);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e(TAG, "surfaceDestroyed");
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
public void onClick(View arg0) {
int i = 0;
while (i < 4) {
mCamera.takePicture(null, mPictureCallback, mPictureCallback);
i = i + 1;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static Object StoreByteImage(byte[] imageData) {
Object obj = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream(imageData);
ObjectInputStream objImageData = new ObjectInputStream(bis);
obj = objImageData.readObject();
} catch (IOException ex) {
// TODO: Handle the exception
} catch (ClassNotFoundException ex) {
// TODO: Handle the exception
}
return obj;
}
public static Object createImagesArray(byte[] imageData) {
Object obj = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream(imageData);
ObjectInputStream objImageData = new ObjectInputStream(bis);
obj = objImageData.readObject();
} catch (IOException ex) {
// TODO: Handle the exception
} catch (ClassNotFoundException ex) {
// TODO: Handle the exception
}
return obj;
}
public static boolean SaveImage(List<Object> listImage) {
FileOutputStream outStream = null;
Log.d("ListSize: ", Integer.toString(listImage.size()));
Iterator<Object> itList = listImage.iterator();
byte[] imageBytes = null;
while (itList.hasNext()) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(listImage);
oos.flush();
oos.close();
bos.close();
imageBytes = bos.toByteArray();
} catch (IOException ex) {
// TODO: Handle the exception
}
try {
// Write to SD Card
outStream = new FileOutputStream(String.format(
"/sdcard/DCIM/%d.jpg", System.currentTimeMillis())); // <9>
outStream.write(imageBytes);
outStream.close();
} catch (FileNotFoundException e) { // <10>
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
Log.d(TAG, "onPictureTaken - jpeg");
return true;
}
}
评论错误:
ERROR/MemoryHeapBase(1382): error opening /dev/pmem_camera: No such file or directory
ERROR/QualcommCameraHardware(1382): failed to construct master heap for pmem pool /dev/pmem_camera
ERROR/QualcommCameraHardware(1382): initRaw X failed with pmem_camera, trying with pmem_adsp
答案 0 :(得分:16)
AFAIK,在完成第一张照片之前,你不能拍另一张照片。消除for
循环和Thread.sleep()
。拍下mPictureCallback
中的下一张照片。
主要思想是每0.3秒拍摄一张照片并将照片存储在一个数组中,直到拍完最后一张照片。
“0,3sec”目标比大多数设备处理图像的速度快,并且您的图像阵列可能没有足够的堆空间。我怀疑你必须通过AsyncTask
将每个图像写入磁盘,这样你就可以释放堆空间,同时也不会占用主应用程序线程。
答案 1 :(得分:1)
您可以尝试在预分配的字节数组中捕获后续预览帧。 请参阅以下方法:
http://developer.android.com/reference/android/hardware/Camera.html#addCallbackBuffer(字节[]) http://developer.android.com/reference/android/hardware/Camera.html#setPreviewCallbackWithBuffer(android.hardware.Camera.PreviewCallback)
...或http://developer.android.com/reference/android/hardware/Camera.html#setOneShotPreviewCallback(android.hardware.Camera.PreviewCallback)可以更好地控制时间安排。