Preview camera frame not capturing Android - android

I have the code setup (obviously not correctly but it seems ok)
My test code for capturing frame is like this:
frameCallback = new Camera.PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
System.out.println("preview frame captured");
But this onPreviewFrame is never ran, as the print statement tests.
The weird thing is, the preview is showing up perfectly on my surface. i.e- I can see it on my screen and there is no errors. Why isn't onPreviewFrame being called then?
Here is all my code for reference:
public class HuntActivity extends AppCompatActivity implements SurfaceHolder.Callback{
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
Camera.PreviewCallback frameCallback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hunt);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
frameCallback = new Camera.PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
System.out.println("preview frame captured");
}
};
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {camera = Camera.open();
} catch (RuntimeException e) {
System.err.println(e);
return;
}
camera.setPreviewCallback(frameCallback);
Camera.Parameters param;
param = camera.getParameters();
param.setPreviewSize(800, 480);
camera.setDisplayOrientation(90);
camera.setParameters(param);
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
System.err.println(e);
return;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
refreshCamera();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
public void refreshCamera() {
if (surfaceHolder.getSurface() == null) {return;}
try {camera.stopPreview();
} catch (Exception e){}
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {}
}

refreshCamera();
Do not call that function there. It will stop the preview functionality before you can use it.
Move following code to onSurfaceChanged() and use the width and heigth parameters
Camera.Parameters param;
param = camera.getParameters();
//param.setPreviewSize(800, 480);
param.setPreviewSize(width, height);
... and the rest of those lines...
Never hardcode resolutions like 800x480

try to unlock
camera.unlock();
camera.reconnect();
frameCallback.setPreviewCallback(mCallback);

Related

using camera.hardware reduces image quality

I have been following two links to create custom camera for my application. I have been successful in opening the camera. The problem is that it reduces that image quality. The links I have been following are these:
http://www.coderzheaven.com/2011/12/28/how-to-create-a-custom-layout-for-your-camera-in-android/
http://blog.rhesoft.com/2015/04/02/tutorial-how-to-use-camera-with-android-and-android-studio/
and my code is:
Camera Activity:
public class CameraSetter extends Activity {
public Context context;
public int CAMERA;
// ImageView photo_setter;
private Camera mCamera = null;
private CameraView mCameraView = null;
public CameraSetter() {
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TypefaceProvider.registerDefaultIconSets();
setContentView(R.layout.camera_preview);
Initialize();
}
private void Initialize() {
//photo_setter = (ImageView)findViewById(R.id.imview_camera_setter);
try {
mCamera = Camera.open();//you can use open(int) to use different cameras
} catch (Exception e) {
Log.d("ERROR", "Failed to get camera: " + e.getMessage());
}
if (mCamera != null) {
mCameraView = new CameraView(this, mCamera);//create a SurfaceView to show camera data
FrameLayout camera_view = (FrameLayout) findViewById(R.id.camera_view);
camera_view.addView(mCameraView);//add the SurfaceView to the layout
}
//btn to close the application
ImageButton imgClose = (ImageButton) findViewById(R.id.imgClose);
imgClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
System.exit(0);
}
});
}
}
and my cameraview class is:
public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraView(Context context, Camera camera) {
super(context);
mCamera = camera;
mCamera.setDisplayOrientation(90);
//get the holder and set this class as the callback, so we can get camera data here
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
//when the surface is created, we can set the camera to draw images in this surfaceholder
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("ERROR", "Camera error on surfaceCreated " + e.getMessage());
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
if (mHolder.getSurface() == null)//check if the surface is ready to receive camera data
return;
try {
mCamera.stopPreview();
} catch (Exception e) {
//this will happen when you are trying the camera if it's not running
}
//now, recreate the camera preview
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("ERROR", "Camera error on surfaceChanged " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
//our app has only one screen, so we'll destroy the camera in the surface
//if you are unsing with more screens, please move this code your activity
mCamera.stopPreview();
mCamera.release();
}
}
Can I increase the image quality using the same code or I have to do something else?
problem is solved by adding in surfacechanged:
Camera.Parameters parameters = mCamera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
parameters.setJpegQuality(100);
parameters.setRotation(90);
List<Camera.Size> sizes = parameters.getSupportedPictureSizes();
Camera.Size size = sizes.get(0);
for(int j=0;j<sizes.size();j++)
{
if(sizes.get(j).width > size.width)
size = sizes.get(j);
}
parameters.setPictureSize(size.width, size.height);
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
mCamera.setDisplayOrientation(90);
} else if (display.getRotation() == Surface.ROTATION_270) {
mCamera.setDisplayOrientation(180);
}
mCamera.setParameters(parameters);

Camera flash not working

My application turn on/off flash on a lot of devices. But it's not working on LG-F500S Android verion 6.0 (Samsung S7 android 6.0 work fine). Who help me to find reason and solution, please?
I have to find reason.
+ targetSdkVersion < 23
+ Surface Holder:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
try {
mCamera.stopPreview();
} catch (Exception e){
e.printStackTrace();
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
}
+ MainActivity:
public 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
}
#Override
protected void onResume() {
super.onResume();
cam = getCameraInstance();
mPreview = new CameraPreview(this, cam);
FrameLayout preview = (FrameLayout) findViewById(R.id.surfaceContain);
preview.addView(mPreview);
}
public void toggleLight(View v){
if (isFlash){
isFlash = false;
params = cam.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
cam.setParameters(params);
cam.startPreview();
}else{
isFlash = true;
params = cam.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cam.setParameters(params);
cam.startPreview();
}
}
View details here:
https://developer.android.com/guide/topics/media/camera.html

Capturing Photo from SurfaceView

I'm trying to capture an image from a SurfaceView custom camera. I have set up the initial code but I don't know how to call the 'take photo' method so that I can see the preview on the surface.
Currently this code displays the preview in realtime. I need to take the picture and access the byte[] array
Please help me complete the code:
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
captureImage = (ImageButton) findViewById(R.id.captureImage);
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
captureImage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//this button press should take the picture
}
});
mSurfaceView.getHolder().addCallback(this);
mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mCamera = Camera.open();
}
#Override
public void onPause() {
super.onPause();
mCamera.stopPreview();
}
#Override
public void onDestroy() {
super.onDestroy();
mCamera.release();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(mSurfaceView.getHolder());
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
Camera.Size selected = sizes.get(0);
params.setPreviewSize(selected.width,selected.height);
mCamera.setParameters(params);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
I need to get the bytes [] data so that I can convert the image to a base64 string. How do I call the necessary methods to take the picture using the code above?
Check "jpegCallback" in my example:
public class CameraActivity extends ActionBarActivity implements SurfaceHolder.Callback {
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
PictureCallback jpegCallback;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceHolder = surfaceView.getHolder();
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
surfaceHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.d("Log", "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Toast.makeText(getApplicationContext(), "Picture Saved", 2000).show();
refreshCamera();
}
};
}
public void captureImage(View v) throws IOException {
//take the picture
camera.takePicture(null, null, jpegCallback);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
// open the camera
camera = Camera.open();
} catch (RuntimeException e) {
// check for exceptions
System.err.println(e);
return;
}
Camera.Parameters param;
param = camera.getParameters();
// modify parameter
List<Camera.Size> sizes = param.getSupportedPreviewSizes();
Camera.Size selected = sizes.get(0);
param.setPreviewSize(selected.width,selected.height);
camera.setParameters(param);
try {
// The Surface has been created, now tell the camera where to draw
// the preview.
camera.setDisplayOrientation(90);
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
// check for exceptions
System.err.println(e);
return;
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
refreshCamera();
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
// stop preview and release camera
camera.stopPreview();
camera.release();
camera = null;
}
public void refreshCamera() {
if (surfaceHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
camera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
}
}
}

My custom camera happen to crash after taken a few photo why is that?

After taken a few photo, my camera just went black. Any suggestion of this?
SurfaceView cameraView;
SurfaceHolder surfaceHolder;
Camera camera;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
cameraView = (SurfaceView)this.findViewById(R.id.CameraView);
surfaceHolder = cameraView.getHolder();
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(this);
cameraView.setFocusable(true);
cameraView.setFocusableInTouchMode(true);
cameraView.setClickable(true);
cameraView.setOnClickListener(this);
}
public void onClick(View v){
camera.takePicture(null, null, this);
}
#Override
public void onPictureTaken(byte[] data, Camera camera) {
try{
OutputStream imageFileOS = new FileOutputStream(String.format("/sdcard/Galmix/%d.jpg",System.currentTimeMillis()));
imageFileOS.write(data);
imageFileOS.flush();
imageFileOS.close();
} catch(FileNotFoundException e){
Toast t = Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT);
t.show();
} catch (IOException e) {
Toast t = Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT);
t.show();
}
camera.startPreview();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
camera.startPreview();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
try{
camera.setPreviewDisplay(holder);
Camera.Parameters parameters = camera.getParameters();
parameters.setPictureSize(640, 480);
if(this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE){
parameters.set("orientation", "portrait");
camera.setDisplayOrientation(90);
}
camera.setParameters(parameters);
} catch(IOException e){
camera.release();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
}
Check to make sure the images you're saving are being saved properly. I had a similar issue where due to a bug in my saving code I was getting a NullPointerException and killing my camera activity. For more specifics you'll have to post code though.

Set size of the photo taken by camera

Are there any way to constantly set the resolution of the photo (like 256x256) that were taken by my own camera application. Here is bits of code, Thanks.
SurfaceView cameraView;
SurfaceHolder surfaceHolder;
Camera camera;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
File mFile=new File("/sdcard/Galmix");
mFile.mkdir();
cameraView = (SurfaceView)this.findViewById(R.id.CameraView);
surfaceHolder = cameraView.getHolder();
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(this);
cameraView.setFocusable(true);
cameraView.setFocusableInTouchMode(true);
cameraView.setClickable(true);
cameraView.setOnClickListener(this);
}
public void onClick(View v){
camera.takePicture(null, null, this);
}
#Override
public void onPictureTaken(byte[] data, Camera camera) {
try{
OutputStream imageFileOS = new FileOutputStream(String.format("/sdcard/Galmix/%d.jpg",System.currentTimeMillis()));
imageFileOS.write(data);
imageFileOS.flush();
imageFileOS.close();
} catch(FileNotFoundException e){
Toast t = Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT);
t.show();
} catch (IOException e) {
Toast t = Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT);
t.show();
}
camera.startPreview();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
camera.startPreview();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
try{
camera.setPreviewDisplay(holder);
Camera.Parameters parameters = camera.getParameters();
if(this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE){
parameters.set("orientation", "portrait");
camera.setDisplayOrientation(90);
}
List<String> colorEffects = parameters.getSupportedColorEffects();
Iterator<String> cei = colorEffects.iterator();
while(cei.hasNext()){
String currentEffect = cei.next();
if(currentEffect.equals(Camera.Parameters.EFFECT_SOLARIZE)){
parameters.setColorEffect(Camera.Parameters.EFFECT_SOLARIZE); break;
}
}
camera.setParameters(parameters);
} catch(IOException e){
camera.release();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
}
See Camera Parameters for information.
to resolve your problem, you have to check your camera supported sizes by using this code:
Camera camera = Camera.open();
Parameters params = camera.getParameters();
List<Camera.Size> sizes = params.getSupportedPictureSizes();
Once you will se the supported Sizes, you can define them with the method :
setPictureSize(int width, int height);

Categories

Resources