I'm developing an Android App that has a Camera Preview Activity. It calls takePicture() every 2 second using a timer and does some processing on the captured image in PictureCallback. From the Android documentation, I learnt that PictureCallback happens in the same thread as Camera.open().
Also, it's recommended to call takePicture() in a separate thread. What's the best way to call StartPreview() after an image is captured?
I would want the processing on each capture to happen on separate threads and the camera preview should continue in the main UI thread. What's the best way to implement this using AsyncTask()?
public class CameraActivity extends AppCompatActivity{
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
public static String TAG = "Exception";
int viewWidth = 0;
int viewHeight = 0;
private Camera mCamera;
private CameraPreview mPreview;
private ImageView iv;
private RelativeLayout rl;
private Camera.PictureCallback mPicture;
private MRZ_OCR mrz = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
rl = (RelativeLayout) findViewById(R.id.rel_camera);
iv = (ImageView) findViewById(R.id.black_above);
viewWidth = iv.getWidth();
viewHeight = rl.getHeight() - 2 * iv.getHeight();
// Create an instance of Camera
mCamera = getCameraInstance();
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
new Timer().schedule(new TimerTask() {
#Override
public void run() {
mCamera.startPreview();
mrz = new MRZ_OCR();
mrz.execute();
}
}, 4000, 4000);
mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// Crop to get only MRZ
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
bm = Bitmap.createBitmap(bm, 0, pxFromDp(CameraActivity.this, 120), viewWidth, viewHeight);
//Verify if it has MRZ
bm = MRZ.getMRZ(bm);
if (bm != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
createImageFile(byteArray);
Toast.makeText(getApplicationContext(), "Pic Saved", Toast.LENGTH_LONG).show();
}
}
};
}
#Override
protected void onPause() {
super.onPause();
releaseCamera(); // release the camera immediately on pause event
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
private class MRZ_OCR extends AsyncTask<Void, Void, Void>
{
private byte[] data;
#Override
protected Void doInBackground(Void... params) {
mCamera.takePicture(null, null, mPicture);
// Sleep for however long, you could store this in a variable and
// have it updated by a menu item which the user selects.
try {
Thread.sleep(3000); // 3 second preview
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// This returns the preview back to the live camera feed
mCamera.startPreview();
}
}
public static int pxFromDp(final Context context, final float dp) {
return (int) (dp * context.getResources().getDisplayMetrics().density);
}
/**
* A safe way to get an instance of the Camera object.
*/
public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
} catch (Exception e) {
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
private static File getOutputMediaFile(int type)
{
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_" + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
private static void createImageFile(byte[] byteArray) {
//create empty image type file
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null) {
Log.d(TAG, "Error creating media file, check storage permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(byteArray);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
}
I don't know about the api takePicture(),but i think what you need to do is put this code in a separate thread.
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
bm = Bitmap.createBitmap(bm, 0, pxFromDp(CameraActivity.this, 120), viewWidth, viewHeight);
//Verify if it has MRZ
bm = MRZ.getMRZ(bm);
if (bm != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
createImageFile(byteArray);
}
decodeBitmap is a time-consuming process, especially in you app,performed once every 2 seconds. it will blocking the main thread. and why it's recommended to call takePicture() in a separate thread, I think it is the same reason.
You already answered your question. Pass byte[] data to an AsyncTask:
private class PictureConverter extends AsyncTask<Void, Void, Void> {
private byte[] data;
private Camera camera;
public PictureConverter(byte[] _data, Camera _camera) {
data = _data;
camera = _camera;
}
protected Void doInBackground(Void... data) {
Camera.Parameters parameters = camera.getParameters();
ByteArrayOutputStream out = new ByteArrayOutputStream();
YuvImage yuvImage = new YuvImage(data, parameters.getPreviewFormat(), parameters.getPreviewSize().width, parameters.getPreviewSize().height, null);
yuvImage.compressToJpeg(new Rect(0, 0, parameters.getPreviewSize().width, parameters.getPreviewSize().height), 90, out);
byte[] imageBytes = out.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
out.flush();
out.close();
//TODO save the image
return null;
}
protected void onProgressUpdate() {
}
protected void onPostExecute() {
//TODO report that the image got saved
}
}
Related
I am working an android camera app that uses a vertex shader to apply various distortion effects to the camera preview. Although the camera preview shows the desired effect, pictures do not. How do I get the picture/image to show the same effect as the camera preview? I hope my question is clear. Many thanks in anticipation.
Code extract is as follows:
Camera Activity:
public class CameraActivity extends Activity implements SurfaceTexture.OnFrameAvailableListener{
#SuppressWarnings("deprecation")
private Camera mCamera;
private PreviewCallback mPreviewCallback;
private MyGLSurfaceView glSurfaceView;
private SurfaceTexture surface;
MyGL20Renderer renderer;
public boolean mFrameAvailable = false;
public static final int MEDIA_TYPE_IMAGE = 1;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.screen);
FrameLayout surface = (FrameLayout)findViewById(R.id.camera_preview);
glSurfaceView = new MyGLSurfaceView(this);
renderer = glSurfaceView.getRenderer();
// setContentView(glSurfaceView);
surface.addView(glSurfaceView);
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
#SuppressWarnings("deprecation")
#Override
public void onClick(View v) {
// get an image from the camera
// mCamera.takePicture(null, null, mPicture);
// mCamera.setOneShotPreviewCallback(mPreviewCallback);
takeSnapPhoto();
}
}
);
}
#SuppressWarnings("deprecation")
public void startCamera(int texture)
{
surface = new SurfaceTexture(texture);
surface.setOnFrameAvailableListener(this);
renderer.setSurface(surface);
mCamera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
try
{
mCamera.setPreviewTexture(surface);
mCamera.startPreview();
}
catch (IOException ioe)
{
Log.w("MainActivity","CAM LAUNCH FAILED");
}
Camera.Parameters param = mCamera.getParameters();
param.setPictureSize(640, 480);
// param.setColorEffect(Camera.Parameters.EFFECT_SEPIA);
mCamera.setParameters(param);
}
public void onFrameAvailable(SurfaceTexture surfaceTexture)
{
mFrameAvailable = true;
glSurfaceView.requestRender();
}
#SuppressWarnings("deprecation")
#Override
public void onPause()
{
mFrameAvailable = false;
mCamera.stopPreview();
mCamera.release();
System.exit(0);
}
#SuppressWarnings("deprecation")
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data .length);
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d("CrazyMirror", "Error creating media file, check storage permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
// bitmap.compress(Bitmap.CompressFormat.PNG,100, fos);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d("CrazyMirror", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("CrazyMirror", "Error accessing file: " + e.getMessage());
}
refreshPreview();
}
};
/** Create a File for saving an image or video */
#SuppressLint("SimpleDateFormat")
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "CrazyMirror");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("CrazyMirror", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
}
else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
}
else {
return null;
}
return mediaFile;
}
#SuppressWarnings("deprecation")
public void refreshPreview() {
try {
mCamera.stopPreview();
} catch (Exception e) {}
try {
mCamera.startPreview();
} catch (Exception e) {}
}
public void takeSnapPhoto() {
mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
int format = parameters.getPreviewFormat();
//YUV formats require more conversion
if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
int w = parameters.getPreviewSize().width;
int h = parameters.getPreviewSize().height;
// Get the YuV image
YuvImage yuv_image = new YuvImage(data, format, w, h, null);
// Convert YuV to Jpeg
Rect rect = new Rect(0, 0, w, h);
ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
yuv_image.compressToJpeg(rect, 100, output_stream);
byte[] byt = output_stream.toByteArray();
FileOutputStream outStream = null;
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "CrazyMirror");
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
try {
// Write to SD Card
// File file = createFileInSDCard(FOLDER_PATH, "Image_"+System.currentTimeMillis()+".jpg");
//Uri uriSavedImage = Uri.fromFile(file);
outStream = new FileOutputStream(mediaFile);
outStream.write(byt);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
});}
}
i'm working on a android application and I have to take a picture and save it. It's working and my picture is saved in a directory of the phone. Especially, in Picture directory.
So, here its my class parameter with the button to launch the camera ( new activity) and take the picture :
public class Parametre extends Activity {
private EditText ETpseudo= null;
private Button buttonPhoto = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.parametres);
ETpseudo =(EditText) findViewById(R.id.editPseudo);
buttonPhoto = (Button) findViewById(R.id.buttonPhoto);
//ivPhoto.setImageBitmap();
buttonPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Parametre.this, CameraActivity.class));
}
});
}
}
CameraActivity :
public class CameraActivity extends Activity {
private Camera mCamera;
private CameraPreview mCameraPreview;
private ImageView cadrePhoto = null;
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
Log.d("DEBUG", String.valueOf(grantResults[0]));
startCamera();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
Button captureButton = (Button) findViewById(R.id.button_capture);
startCamera();
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPicture);
}
});
}
private void startCamera(){
mCamera = getCameraInstance();
mCamera.startPreview();
mCameraPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mCameraPreview);
setCameraDisplayOrientation(this, 1, mCamera);
}
/**
* Helper method to access the camera returns null if it cannot get the
* camera or does not exist
*
* #return
*/
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
private Camera getCameraInstance() {
Camera camera = null;
try {
camera = Camera.open(1);
} catch (Exception e) {
e.printStackTrace();
}
return camera;
}
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
public void setCameraDisplayOrientation(Activity activity, int cameraId,android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
Log.d("Error", "Error creating media file, check storage permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d("DBG", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("Error", "Error accessing file: " + e.getMessage());
}
}
};
private static File getOutputMediaFile() {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
}
So, after taking the photo, I want to display the image on an ImageView in the parameter view. But I dont know how to do this. How to get back the photo and display him on the parameter View ?
Thanks.
Sorry for my english :/
you can do this in as easy way just create an static bitmap when picture taken in picturecallback method
Bitmap bmap=BitmapFactory.decodeByteArray(data, 0, data.length,sizeOptions);
Log.e("clickedbitmaaapp", String.valueOf(bmap));
static Bitmap mBitmap=bmap;
create this bitmap in other class which where you can access this easily.
Thanks you.
I can't test my code now. But do you think that should work here ? :
(cameraActivity)
public class CameraActivity extends Activity {
static Bitmap mBitmap;
...
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
Log.d("Error", "Error creating media file, check storage permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bmap= BitmapFactory.decodeByteArray(data, 0, data.length, options);
mBitmap = bmap;
} catch (FileNotFoundException e) {
Log.d("DBG", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("Error", "Error accessing file: " + e.getMessage());
}
}
};
and then in my parameter class :
public class Parametre extends Activity {
private EditText ETpseudo= null;
private Button buttonPhoto = null;
private ImageView iv = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.parametres);
ETpseudo =(EditText) findViewById(R.id.editPseudo);
buttonPhoto = (Button) findViewById(R.id.buttonPhoto);
//ivPhoto.setImageBitmap();
buttonPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Parametre.this, CameraActivity.class));
}
});
ImageView imageView=(ImageView)findViewById(R.id.cadreImage);
imageView.setImageBitmap(CameraActivity.mBitmap);
}
}
I have an app that I want to be able to capture a screenshot
Here is my code :
public class Screenshot {
private final View view;
/** Create snapshots based on the view and its children. */
public Screenshot(View root) {
this.view = root;
}
/** Create snapshot handler that captures the root of the whole activity. */
public Screenshot(Activity activity) {
final View contentView = activity.findViewById(android.R.id.content);
this.view = contentView.getRootView();
}
/** Take a snapshot of the view. */
public Bitmap snap() {
Bitmap bitmap = Bitmap.createBitmap(this.view.getWidth(), this.view.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
}
but the contents of the surfaceView is saved as black.!!!
Please help me, Thanks...
I hope you have used this solution which was posted here Get screenshot of surfaceView in Android
this thing is explained here Take Screenshot of SurfaceView
The SurfaceView's surface is independent of the surface on which View elements are drawn. So capturing the View contents won't include the SurfaceView.........
I hope this Taking screenshot programmatically doesnt capture the contents of surfaceVIew code can help you out more
public class Cam_View extends Activity implements SurfaceHolder.Callback {
protected static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 0;
private SurfaceView SurView;
private SurfaceHolder camHolder;
private boolean previewRunning;
final Context context = this;
public static Camera camera = null;
private RelativeLayout CamView;
private Bitmap inputBMP = null, bmp, bmp1;
private ImageView mImage;
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
CamView = (RelativeLayout) findViewById(R.id.camview);//RELATIVELAYOUT OR
//ANY LAYOUT OF YOUR XML
SurView = (SurfaceView)findViewById(R.id.sview);//SURFACEVIEW FOR THE PREVIEW
//OF THE CAMERA FEED
camHolder = SurView.getHolder(); //NEEDED FOR THE PREVIEW
camHolder.addCallback(this); //NEEDED FOR THE PREVIEW
camHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//NEEDED FOR THE PREVIEW
camera_image = (ImageView) findViewById(R.id.camera_image);//NEEDED FOR THE PREVIEW
Button btn = (Button) findViewById(R.id.button1); //THE BUTTON FOR TAKING PICTURE
btn.setOnClickListener(new OnClickListener() { //THE BUTTON CODE
public void onClick(View v) {
camera.takePicture(null, null, mPicture);//TAKING THE PICTURE
//THE mPicture IS CALLED
//WHICH IS THE LAST METHOD(SEE BELOW)
}
});
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,//NEEDED FOR THE PREVIEW
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) { //NEEDED FOR THE PREVIEW
try {
camera=Camera.open();
} catch(Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
finish();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) { //NEEDED FOR THE PREVIEW
camera.stopPreview();
camera.release();
camera=null;
}
public void TakeScreenshot(){ //THIS METHOD TAKES A SCREENSHOT AND SAVES IT AS .jpg
Random num = new Random();
int nu=num.nextInt(1000); //PRODUCING A RANDOM NUMBER FOR FILE NAME
CamView.setDrawingCacheEnabled(true); //CamView OR THE NAME OF YOUR LAYOUR
CamView.buildDrawingCache(true);
Bitmap bmp = Bitmap.createBitmap(CamView.getDrawingCache());
CamView.setDrawingCacheEnabled(false); // clear drawing cache
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(CompressFormat.JPEG, 100, bos);
byte[] bitmapdata = bos.toByteArray();
ByteArrayInputStream fis = new ByteArrayInputStream(bitmapdata);
String picId=String.valueOf(nu);
String myfile="Ghost"+picId+".jpeg";
File dir_image = new File(Environment.getExternalStorageDirectory()+//<---
File.separator+"Ultimate Entity Detector"); //<---
dir_image.mkdirs(); //<---
//^IN THESE 3 LINES YOU SET THE FOLDER PATH/NAME . HERE I CHOOSE TO SAVE
//THE FILE IN THE SD CARD IN THE FOLDER "Ultimate Entity Detector"
try {
File tmpFile = new File(dir_image,myfile);
FileOutputStream fos = new FileOutputStream(tmpFile);
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) > 0) {
fos.write(buf, 0, len);
}
fis.close();
fos.close();
Toast.makeText(getApplicationContext(),
"The file is saved at :SD/Ultimate Entity Detector",Toast.LENGTH_LONG).show();
bmp1 = null;
camera_image.setImageBitmap(bmp1); //RESETING THE PREVIEW
camera.startPreview(); //RESETING THE PREVIEW
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private PictureCallback mPicture = new PictureCallback() { //THIS METHOD AND THE METHOD BELOW
//CONVERT THE CAPTURED IMAGE IN A JPG FILE AND SAVE IT
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File dir_image2 = new File(Environment.getExternalStorageDirectory()+
File.separator+"Ultimate Entity Detector");
dir_image2.mkdirs(); //AGAIN CHOOSING FOLDER FOR THE PICTURE(WHICH IS LIKE A SURFACEVIEW
//SCREENSHOT)
File tmpFile = new File(dir_image2,"TempGhost.jpg"); //MAKING A FILE IN THE PATH
//dir_image2(SEE RIGHT ABOVE) AND NAMING IT "TempGhost.jpg" OR ANYTHING ELSE
try { //SAVING
FileOutputStream fos = new FileOutputStream(tmpFile);
fos.write(data);
fos.close();
//grabImage();
} catch (FileNotFoundException e) {
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(getApplicationContext(),"Error",Toast.LENGTH_LONG).show();
}
String path = (Environment.getExternalStorageDirectory()+
File.separator+"Ultimate EntityDetector"+
File.separator+"TempGhost.jpg");//<---
BitmapFactory.Options options = new BitmapFactory.Options();//<---
options.inPreferredConfig = Bitmap.Config.ARGB_8888;//<---
bmp1 = BitmapFactory.decodeFile(path, options);//<--- *********(SEE BELOW)
//THE LINES ABOVE READ THE FILE WE SAVED BEFORE AND CONVERT IT INTO A BitMap
camera_image.setImageBitmap(bmp1); //SETTING THE BitMap AS IMAGE IN AN IMAGEVIEW(SOMETHING
//LIKE A BACKGROUNG FOR THE LAYOUT)
tmpFile.delete();
TakeScreenshot();//CALLING THIS METHOD TO TAKE A SCREENSHOT
//********* THAT LINE MIGHT CAUSE A CRASH ON SOME PHONES (LIKE XPERIA T)<----(SEE HERE)
//IF THAT HAPPENDS USE THE LINE "bmp1 =decodeFile(tmpFile);" WITH THE METHOD BELOW
}
};
public Bitmap decodeFile(File f) { //FUNCTION BY Arshad Parwez
Bitmap b = null;
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream 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
BitmapFactory.Options 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;
}
}
try out this also
public static Bitmap overlay(Bitmap bmp1,Bitmap bmp2) {
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, 0,0, null);
canvas.drawBitmap(bmp2, 0, 0, null);
Log.i("bmOverlay.......",""+bmOverlay);
bmp3=bmOverlay;
return bmOverlay;
}
private void getScreen() {
Toast.makeText(BookType1.this, "saved", Toast.LENGTH_SHORT).show();
File myDir=new File("/sdcard/saved_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-"+ n +".png";
File file = new File (myDir, fname);
try
{
FileOutputStream ostream = new FileOutputStream(file);
bmp3.compress(CompressFormat.PNG, 100, ostream);
ostream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
and you can also go through these references which gives you more idea
How to capture screenshot of surfaceview with background
Taking screen shot of a SurfaceView in android
How to take a screenshot of Android's Surface View?
How to programmatically take a screenshot in Android?
I'm developing an application for Android that captures max fps and saves to the SD card.
The problem is that the saved photo is a black screen, and I can't understand why.
Can anyone tell me where is the problem?
The code where I do this:
public class PhotoFragment extends Fragment {
private Camera cam;
private CameraPreview camPreview;
private boolean recording = false;
private ArrayList<byte[]> fotos;
private ArrayList<String> tempos;
private Thread thread;
public PhotoFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_photofinish, container, false);
cam = getCameraInstance();
if(cam != null) {
cam.setDisplayOrientation(90);
// set Camera parameters
Camera.Parameters cameraParameters = cam.getParameters();
//set color efects to none
cameraParameters.setColorEffect(Camera.Parameters.EFFECT_NONE);
//set antibanding to none
if (cameraParameters.getAntibanding() != null) {
cameraParameters.setAntibanding(Camera.Parameters.ANTIBANDING_OFF);
}
// set white ballance
if (cameraParameters.getWhiteBalance() != null) {
cameraParameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT);
}
//set flash
if (cameraParameters.getFlashMode() != null) {
cameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
//set zoom
if (cameraParameters.isZoomSupported()) {
cameraParameters.setZoom(0);
}
//set focus mode
cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
List<Size> sizes = cameraParameters.getSupportedPictureSizes();
Camera.Size size = sizes.get(0);
cameraParameters.setPictureSize(size.width, size.height);
cam.setParameters(cameraParameters);
fotos = new ArrayList<byte[]>();
tempos = new ArrayList<String>();
camPreview = new CameraPreview(this.getActivity(), cam);
FrameLayout preview = (FrameLayout) rootView.findViewById(R.id.camera_preview);
preview.addView(camPreview);
TextView startRecording = (TextView) rootView.findViewById(R.id.start_record_button);
startRecording.setOnClickListener( new View.OnClickListener() {
public void onClick(View v) {
if(!recording)
{
recording = true;
Size previewSize = cam.getParameters().getPreviewSize();
int dataBufferSize=(int)(previewSize.height*previewSize.width*(ImageFormat.getBitsPerPixel(cam.getParameters().getPreviewFormat())/8.0));
thread.start();
cam.addCallbackBuffer(new byte[dataBufferSize]);
cam.addCallbackBuffer(new byte[dataBufferSize]);
cam.addCallbackBuffer(new byte[dataBufferSize]);
cam.setPreviewCallbackWithBuffer(new PreviewCallback() {
public void onPreviewFrame(byte[] imageData, Camera arg1) {
try {
fotos.add(imageData);
tempos.add(new SimpleDateFormat("HH_mm_ss_SSS", Locale.getDefault()).format(new Date()));
} catch(Exception e) {
System.out.println("ERRO: " + e);
}
}
});
}
else
{
recording = false;
try {
thread.join();
} catch (Exception e) {
}
}
}
});
thread = new Thread(new Runnable() {
public void run() {
while(recording) {
if(fotos.size()>0 && tempos.size()>0)
{
File pictureFile = getOutputMediaFile(1, tempos.get(0));
if (pictureFile == null){
System.out.println("Error creating media file, check storage permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(fotos.get(0));
fos.close();
pictureFile = null;
cam.addCallbackBuffer(fotos.get(0));
fotos.remove(0);
tempos.remove(0);
} catch (FileNotFoundException e) {
System.out.println("ERRO FILE NOT FOUND! : " + e);
} catch (IOException e) {
System.out.println("ERRO IOException!");
}
}
}
}
});
}
else
{
Toast.makeText(getActivity(), "Camera not available", Toast.LENGTH_LONG).show();
}
return rootView;
}
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open();
}
catch (Exception e){
}
return c;
}
#Override
public void onDestroyView() {
super.onDestroyView();
cam.release();
}
private static File getOutputMediaFile(int type, String timeStamp){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "L_P");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
System.out.println("L_P failed to create directory");
return null;
}
}
String timeStampDay = new SimpleDateFormat("ddMMyyyy", Locale.getDefault()).format(new Date());
new File(mediaStorageDir.getPath() + File.separator + timeStampDay).mkdirs();
File mediaFile;
if (type == 1){
mediaFile = new File(mediaStorageDir.getPath() + File.separator + timeStampDay + File.separator + "IMG_"+ timeStamp + ".jpg");
} else if(type == 2) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
}
You are claiming that the file is a JPEG. However, you have done nothing to convert the image to be a JPEG. Preview frames, by default, are not JPEG, but are in NV21 format. Use getSupportedPreviewFormats() to see if JPEG previews are possible, then use setPreviewFormat() to request JPEG previews.
And, as I noted in your previous question, do NOT have two threads working with an ArrayList. Also, do not have your background thread busy-wait looking constantly for an image to show up on an ArrayList. Use a LinkedBlockingQueue or something else that is thread-safe and allows the background thread to block while waiting for an image.
I am working on an app that needs to access an array of pixels from a picture after it is taken. The main Activity is below. I have a good amount of java experience but extremely limited experience with images past displaying them on the screen. I see the byte array being passed to the picture callback method but I do not know how it is formatted. How can I get a pixel array that includes the RGB components from the captured image? I tried to find this through the stack overflow forums however I got a few hundred pages of results and only searched through the first 10 or so, so I am sorry if that has already been asked and I just did not see it.
public class ConverterActivity extends Activity
{
private Camera mCamera;
private CameraPreview mPreview;
private PictureCallback mPicture = new PictureCallback() {
private String TAG;
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
// Log.d(TAG, "Error creating media file, check storage permissions: " +
// e.getMessage());
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
// Create an instance of Camera
mCamera = Camera.open(this.getBackCamera());
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
#Override
protected void onPause()
{
super.onPause();
releaseCamera(); // release the camera immediately on pause event
}
private void releaseCamera(){
if (mCamera != null){
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
public int getBackCamera()
{
int numCameras = Camera.getNumberOfCameras();
CameraInfo cInfo = new CameraInfo();
for (int i = 0; i < numCameras; i++)
{
Camera.getCameraInfo(i, cInfo);
if (cInfo.facing == CameraInfo.CAMERA_FACING_BACK)
{
return i;
}
}
return -1;
}
}
If you take the picture using code like this:
imgFile = new File(Environment.getExternalStorageDirectory () + "/somefolder/" + name + ".jpg");
String fileName = imgFile.getAbsolutePath();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(fileName)));
startActivityForResult(intent, REQUEST_FROM_CAMERA);
Then you should be able to, when you get the result back from this intent, using code like this to access the bitmap
if (imgFile.exists()) {
String fileName = file.getAbsolutePath();
BitmapFactory.Options opts = new BitmapFactory.Options();
Bitmap bm;
opts.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(fileName, opts);
return bm;
}
else return null;
Then you can use bitmapfactory tools, such as compress to stream and then
convert to byte[]
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, stream); // 100 = max quality
byte[] byteArray = stream.toByteArray();