Currently I am using the Git-hub library for making a demo-App for AR-Location based project. I am using AR-Location Based Android. The library is working fine in portrait mode but in landscape mode the Ar-points are coming from bottom of screen(like bubbles comes out from bottom) and hide to top of screen, while rotating camera.I raised issues in Git also, but the owner is not responding. I tried to fix it, but unable to do it. Can anyone guide me to solve the problem. Or where to change.
I think this classes are responsible for plotting in portrait and Landscape mode. If not please tell me where to change.
#SuppressLint("ViewConstructor")
#SuppressWarnings("deprecation")
#TargetApi(Build.VERSION_CODES.KITKAT)
public class ARCamera extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "ARCamera";
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
Camera.Size previewSize;
List<Camera.Size> supportedPreviewSizes;
Camera camera;
Camera.Parameters parameters;
Activity activity;
float[] projectionMatrix = new float[16];
int cameraWidth;
int cameraHeight;
private final static float Z_NEAR = 0.5f; //Increase or decrease distance, between poines
private final static float Z_FAR = 2000;
public ARCamera(Context context, SurfaceView surfaceView) {
super(context);
this.surfaceView = surfaceView;
this.activity = (Activity) context;
surfaceHolder = this.surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
this.camera = camera;
if (this.camera != null) {
supportedPreviewSizes = this.camera.getParameters().getSupportedPreviewSizes();
requestLayout();
Camera.Parameters params = this.camera.getParameters();
List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
this.camera.setParameters(params);
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (supportedPreviewSizes != null) {
previewSize = getOptimalPreviewSize(supportedPreviewSizes, width, height);
}
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = right - left;
final int height = bottom - top;
int previewWidth = width;
int previewHeight = height;
if (previewSize != null) {
previewWidth = previewSize.width;
previewHeight = previewSize.height;
}
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2,
width, (height + scaledChildHeight) / 2);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
try {
if (camera != null) {
parameters = camera.getParameters();
int orientation = getCameraOrientation();
camera.setDisplayOrientation(orientation);
camera.getParameters().setRotation(orientation);
camera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
private int getCameraOrientation() {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
Toast.makeText(activity, "Rotation = " + rotation, Toast.LENGTH_SHORT).show();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
Toast.makeText(activity, "Degrees = " + degrees, Toast.LENGTH_SHORT).show();
break;
case Surface.ROTATION_90:
degrees = 90;
Toast.makeText(activity, "Degrees = " + degrees, Toast.LENGTH_SHORT).show();
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int orientation;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
orientation = (info.orientation + degrees) % 360;
orientation = (360 - orientation) % 360;
} else {
orientation = (info.orientation - degrees + 360) % 360;
}
return orientation;
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
camera.release();
camera = null;
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) width / height;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = height;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
continue;
}
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
if (optimalSize == null) {
optimalSize = sizes.get(0);
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (camera != null) {
this.cameraWidth = width;
this.cameraHeight = height;
Camera.Parameters params = camera.getParameters();
params.setPreviewSize(previewSize.width, previewSize.height);
requestLayout();
try {
camera.setParameters(params);
camera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
generateProjectionMatrix();
}
}
private void generateProjectionMatrix() {
float ratio = (float) this.cameraWidth / this.cameraHeight;
final int OFFSET = 0;
final float LEFT = -ratio;
final float RIGHT = ratio;
final float BOTTOM = -1; //increases the speed of points going
final float TOP = 1; //increases the speed of points coming
Matrix.frustumM(projectionMatrix, OFFSET, LEFT, RIGHT, BOTTOM, TOP, Z_NEAR, Z_FAR);
}
public float[] getProjectionMatrix() {
return projectionMatrix;
}
}
Activity Class
public class ARActivity extends AppCompatActivity implements SensorEventListener, LocationListener {
final static String TAG = "ARActivity";
private SurfaceView surfaceView;
private FrameLayout cameraContainerLayout;
private AROverlayView arOverlayView;
private Camera camera;
private ARCamera arCamera;
private TextView tvCurrentLocation;
private SensorManager sensorManager;
private final static int REQUEST_CAMERA_PERMISSIONS_CODE = 11;
public static final int REQUEST_LOCATION_PERMISSIONS_CODE = 0;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 10 meters
private static final long MIN_TIME_BW_UPDATES = 0;//1000 * 60 * 1; // 1 minute
private LocationManager locationManager;
public Location location;
boolean isGPSEnabled;
boolean isNetworkEnabled;
boolean locationServiceAvailable;
private DisplayMetrics metrics;
private RelativeLayout infoLayout;
private ImageView appLogo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ar);
Utility.getFullScreenView(this);
sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
cameraContainerLayout = (FrameLayout) findViewById(R.id.camera_container_layout);
surfaceView = (SurfaceView) findViewById(R.id.surface_view);
tvCurrentLocation = (TextView) findViewById(R.id.tv_current_location);
infoLayout = (RelativeLayout) findViewById(R.id.info_layout);
appLogo = (ImageView) findViewById(R.id.logoApp);
arOverlayView = new AROverlayView(this);
metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
infoLayout.getLayoutParams().width = metrics.widthPixels/4;
appLogo.getLayoutParams().width = metrics.widthPixels/5;
appLogo.getLayoutParams().height = metrics.heightPixels/4;
}
#Override
public void onResume() {
super.onResume();
requestLocationPermission();
requestCameraPermission();
registerSensors();
initAROverlayView();
}
#Override
public void onPause() {
releaseCamera();
super.onPause();
}
public void requestCameraPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
this.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSIONS_CODE);
} else {
initARCameraView();
}
}
public void requestLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSIONS_CODE);
} else {
initLocationService();
}
}
public void initAROverlayView() {
if (arOverlayView.getParent() != null) {
((ViewGroup) arOverlayView.getParent()).removeView(arOverlayView);
}
cameraContainerLayout.addView(arOverlayView);
}
public void initARCameraView() {
reloadSurfaceView();
if (arCamera == null) {
arCamera = new ARCamera(this, surfaceView);
}
if (arCamera.getParent() != null) {
((ViewGroup) arCamera.getParent()).removeView(arCamera);
}
cameraContainerLayout.addView(arCamera);
arCamera.setKeepScreenOn(true);
initCamera();
}
private void initCamera() {
int numCams = Camera.getNumberOfCameras();
if(numCams > 0){
try{
camera = Camera.open();
camera.startPreview();
arCamera.setCamera(camera);
} catch (RuntimeException ex){
Toast.makeText(this, "Camera not found", Toast.LENGTH_LONG).show();
}
}
}
private void reloadSurfaceView() {
if (surfaceView.getParent() != null) {
((ViewGroup) surfaceView.getParent()).removeView(surfaceView);
}
cameraContainerLayout.addView(surfaceView);
}
private void releaseCamera() {
if(camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
arCamera.setCamera(null);
camera.release();
camera = null;
}
}
private void registerSensors() {
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_FASTEST);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
float[] rotationMatrixFromVector = new float[16];
float[] projectionMatrix = new float[16];
float[] rotatedProjectionMatrix = new float[16];
SensorManager.getRotationMatrixFromVector(rotationMatrixFromVector, sensorEvent.values);
if (arCamera != null) {
projectionMatrix = arCamera.getProjectionMatrix();
}
Matrix.multiplyMM(rotatedProjectionMatrix, 0, projectionMatrix, 0, rotationMatrixFromVector, 0);
this.arOverlayView.updateRotatedProjectionMatrix(rotatedProjectionMatrix);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
//do nothing
}
private void initLocationService() {
if ( Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED) {
return ;
}
try {
this.locationManager = (LocationManager) this.getSystemService(this.LOCATION_SERVICE);
// Get GPS and network status
this.isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
this.isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isNetworkEnabled && !isGPSEnabled) {
// cannot get location
this.locationServiceAvailable = false;
}
this.locationServiceAvailable = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
updateLatestLocation();
}
}
if (isGPSEnabled) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
updateLatestLocation();
}
}
} catch (Exception ex) {
Log.e(TAG, ex.getMessage());
}
}
private void updateLatestLocation() {
if (arOverlayView !=null && location != null) {
arOverlayView.updateCurrentLocation(location);
tvCurrentLocation.setText(String.format("lat: %s \nlon: %s \naltitude: %s \n",
location.getLatitude(), location.getLongitude(), location.getAltitude()));
}
}
#Override
public void onLocationChanged(Location location) {
updateLatestLocation();
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
public void showHideInfo(View view) {
infoLayout.setVisibility(View.VISIBLE);
infoLayout.startAnimation(AnimationUtils.loadAnimation(this,R.anim.slide_in));
}
public void closeInfo(View view) {
infoLayout.setVisibility(View.GONE);
infoLayout.startAnimation(AnimationUtils.loadAnimation(this,android.R.anim.slide_out_right));
}
}
LocationHelper Class
public class LocationHelper {
private final static double WGS84_A = 6378137.0; // WGS 84 semi-major axis constant in meters
private final static double WGS84_E2 = 0.00669437999014; // square of WGS 84 eccentricity
public static float[] WSG84toECEF(Location location) {
double radLat = Math.toRadians(location.getLatitude());
double radLon = Math.toRadians(location.getLongitude());
float clat = (float) Math.cos(radLat);
float slat = (float) Math.sin(radLat);
float clon = (float) Math.cos(radLon);
float slon = (float) Math.sin(radLon);
float N = (float) (WGS84_A / Math.sqrt(1.0 - WGS84_E2 * slat * slat));
float x = (float) ((N + location.getAltitude()) * clat * clon);
float y = (float) ((N + location.getAltitude()) * clat * slon);
float z = (float) ((N * (1.0 - WGS84_E2) + location.getAltitude()) * slat);
return new float[] {x , y, z};
}
public static float[] ECEFtoENU(Location currentLocation, float[] ecefCurrentLocation, float[] ecefPOI) {
double radLat = Math.toRadians(currentLocation.getLatitude());
double radLon = Math.toRadians(currentLocation.getLongitude());
float clat = (float)Math.cos(radLat);
float slat = (float)Math.sin(radLat);
float clon = (float)Math.cos(radLon);
float slon = (float)Math.sin(radLon);
float dx = ecefCurrentLocation[0] - ecefPOI[0];
float dy = ecefCurrentLocation[1] - ecefPOI[1];
float dz = ecefCurrentLocation[2] - ecefPOI[2];
float east = -slon*dx + clon*dy;
float north = -slat*clon*dx - slat*slon*dy + clat*dz;
float up = clat*clon*dx + clat*slon*dy + slat*dz;
return new float[] {east , north, up, 1};
}
}
I think first two classes are responsible for it. But I am not able to do so. Please guide me.
Related
I am developing an application where i do some real time image processing. In my camera view I do the image processing inside the onPreviewFrame where i loop through each pixel and then find the sum Y value of each frame. I then save this into a csv file and everything works perfect. Except, i also want to store the time elapsed between each frame in the csv along with each y-sum.
ImageProcessing
public abstract class ImageProcessing {
public static int YUV420SPtoYSum(byte[] yuv420sp, int width, int height){
if(yuv420sp == null)
return 0;
int sum = 0;
final int ii = 0;
final int ij = 0;
final int di = +1;
final int dj = +1;
int y = 0;
for (int i = 0, ci = ii; i < height; ++i, ci += di) {
for (int j = 0, cj = ij; j < width; ++j, cj += dj) {
y = (0xff & ((int) yuv420sp[ci * width + cj]));
//y = y < 16 ? 16 : y;
sum += y;
}
}
return sum;
}
}
CameraView Class
public class CameraView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback {
private static final String TAG = "CameraView";
Camera.Size mPreviewSize;
List<Camera.Size> mSupportedPreviewSizes;
private SurfaceHolder mHolder;
private Camera mCamera;
int img_Y_Avg, img_U_Avg, img_V_Avg;
public interface PreviewReadyCallback {
void onPreviewFrame(int yAverage, int uAverage, int vAverage); // Any value you want to get
}
PreviewReadyCallback mPreviewReadyCallback = null;
public void setOnPreviewReady(PreviewReadyCallback cb) {
mPreviewReadyCallback = cb;
}
public CameraView(Context context, Camera camera){
super(context);
mCamera = camera;
//mCamera.setDisplayOrientation(90);
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
for(Camera.Size str: mSupportedPreviewSizes)
Log.e(TAG, str.width + "/" + str.height);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder){
try{
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
}catch(Exception 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)
return;
try{
mCamera.stopPreview();
}catch(Exception e) {
Log.d("ERROR","Camera error on SurfaceChanged" + e.getMessage());
}
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(176, 144);
mCamera.cancelAutoFocus();
//parameters.setAutoExposureLock(false);
mCamera.setDisplayOrientation(90);
//set fps
parameters.setPreviewFpsRange(16000, 16000);
//on flash
parameters.setFlashMode(parameters.FLASH_MODE_AUTO);
//parameters.setAutoWhiteBalanceLock(true);
parameters.setPreviewFormat(ImageFormat.NV21);
/*if (parameters.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported
List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
Rect areaRect1 = new Rect(-50, -50, 50, 50); // specify an area in center of image
meteringAreas.add(new Camera.Area(areaRect1, 1000)); // set weight to 60%
parameters.setMeteringAreas(meteringAreas);
}*/
//mCamera.setDisplayOrientation(90);
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewCallback(this);
mCamera.startPreview();
} catch (IOException e) {
Log.d("ERROR","Camera error on SurfaceChanged" + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
if (mCamera != null){
//mCamera.stopPreview();
//mCamera.release();
}
}
#Override
public void onPreviewFrame(byte[] data, Camera camera){
//check if data is null
if (data == null)
throw new NullPointerException();
Camera.Size size = camera.getParameters().getPreviewSize();
//check if size is null
if(size == null)
throw new NullPointerException();
//set resolution of camera view to optimal setting
int width = size.width;
int height = size.height;
Log.d("Resolution ", " "+String.valueOf(width)+" "+String.valueOf(height));
//call ImageProcess on the data to decode YUV420SP to RGB
img_Y_Avg = ImageProcessing.YUV420SPtoYSum(data, width, height);
img_U_Avg = ImageProcessing.YUV420SPtoUSum(data, width, height);
img_V_Avg = ImageProcessing.YUV420SPtoVSum(data, width, height);
mPreviewReadyCallback.onPreviewFrame(img_Y_Avg, img_U_Avg, img_V_Avg);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
final int width = resolveSize(getSuggestedMinimumWidth(),widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if(mSupportedPreviewSizes != null){
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
Log.d("Resolution ", " "+mPreviewSize);
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h){
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes){
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff){
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null){
minDiff = Double.MIN_VALUE;
for (Camera.Size size : sizes){
if (Math.abs(size.height - targetHeight) < minDiff){
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
}
MainActivity
public class MainActivity extends AppCompatActivity implements CameraView.PreviewReadyCallback {
private static Camera camera = null;
private CameraView image = null;
private LineChart bp_graph;
private static int img_Y_Avg = 0, img_U_Avg = 0, img_V_Avg = 0;
double valueY, valueU, valueV;
Handler handler;
private int readingRemaining = 600;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
bp_graph = (LineChart)findViewById(R.id.graph);
graph_features();
//open camera
try {
camera = Camera.open();
handler = new Handler();
final Runnable runnable = new Runnable() {
#Override
public void run() {
camera.stopPreview();
camera.release();
}
};
handler.postDelayed(runnable, 30000);
} catch (Exception e) {
Log.d("ERROR", "Failed to get camera: " + e.getMessage());
}
if (camera != null) {
image = new CameraView(this, camera);
FrameLayout camera_view = (FrameLayout) findViewById(R.id.camera_view);
camera_view.addView(image);
image.setOnPreviewReady(this);
}
//close camera button
ImageButton imgClose = (ImageButton) findViewById(R.id.imgClose);
imgClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
System.exit(0);
}
});
}
#Override
protected void onResume(){
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
private void graph_features(){
bp_graph.getDescription().setEnabled(false);
//enable touch gesture
bp_graph.setTouchEnabled(true);
//enable scaling
bp_graph.setDragEnabled(true);
//scale and drag
bp_graph.setScaleEnabled(true);
bp_graph.setDrawGridBackground(false);
//enable pinch zoom in
bp_graph.setPinchZoom(true);
//alternative background color
bp_graph.setBackgroundColor(Color.LTGRAY);
//work on data
LineData lineData = new LineData();
lineData.setValueTextColor(Color.WHITE);
//add data to line chart
bp_graph.setData(lineData);
//animate
bp_graph.animateX(600);
Legend legend = bp_graph.getLegend();
//custom legend
legend.setForm(Legend.LegendForm.LINE);
legend.setTextColor(Color.WHITE);
XAxis x1 = bp_graph.getXAxis();
x1.setTextColor(Color.WHITE);
x1.setDrawGridLines(false);
x1.setAvoidFirstLastClipping(true);
x1.setPosition(XAxis.XAxisPosition.BOTTOM);
YAxis y1 = bp_graph.getAxisLeft();
y1.setTextColor(Color.WHITE);
y1.setAxisMaximum(5000000);
y1.setAxisMinimum(100000);
y1.setDrawGridLines(true);
//y1.setInverted(true);
YAxis y2 = bp_graph.getAxisRight();
y2.setEnabled(false);
}
//method to create set
private ILineDataSet createSet() {
LineDataSet set = new LineDataSet(null, "PPG");
set.setLineWidth(1.0f);
set.setCircleRadius(1.0f);
set.setColor(Color.rgb(240, 99, 99));
set.setCircleColor(Color.rgb(240, 99, 99));
set.setHighLightColor(Color.rgb(190, 190, 190));
set.setAxisDependency(YAxis.AxisDependency.LEFT);
set.setValueTextSize(1.0f);
return set;
}
#Override
public void onPreviewFrame(int ySum, int uSum, int vSum) {
img_Y_Avg = ySum;
img_U_Avg = uSum;
img_V_Avg = vSum;
//set value of Y on the text view
TextView valueOfY = (TextView)findViewById(R.id.valueY);
valueY = img_Y_Avg;
valueOfY.setText(Double.toString(img_Y_Avg));
//set value of U on the text view
TextView valueOfU = (TextView)findViewById(R.id.valueU);
valueU = img_U_Avg;
valueOfU.setText(Double.toString(img_U_Avg));
//set value of V on the text view
TextView valueOfV = (TextView)findViewById(R.id.valueV);
valueV = img_V_Avg;
valueOfV.setText(Double.toString(img_V_Avg));
//store value to array list
ArrayList<Integer> yAverage = new ArrayList<Integer>();
yAverage.add(img_Y_Avg);
//Log.d("MyEntryData", String.valueOf(yAverage));
//store u values to array
ArrayList<Integer> uAverage = new ArrayList<Integer>();
uAverage.add(img_U_Avg);
//Log.d("MyEntryData", String.valueOf(uAverage));
//store u values to array
ArrayList<Integer> vAverage = new ArrayList<Integer>();
vAverage.add(img_V_Avg);
//Log.d("MyEntryData", String.valueOf(vAverage));
float start = System.nanoTime();
int diff = (int) ((System.currentTimeMillis()/1000) - start);
ArrayList<Integer> difference = new ArrayList<Integer>();
difference.add(diff);
Log.d("time", String.valueOf(start));
ArrayList<Integer> getValues = new ArrayList<Integer>();
for(int i = 0; i < uAverage.size(); i++) {
//getValues.add(difference.get(i));
getValues.add(yAverage.get(i));
getValues.add(uAverage.get(i));
getValues.add(vAverage.get(i));
}
String filename = new SimpleDateFormat("yyyyMMddHHmm'.csv'").format(new Date());
File directoryDownload = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File logDir = new File (directoryDownload, "bpReader"); //Creates a new folder in DOWNLOAD directory
logDir.mkdirs();
File file = new File(logDir, filename);
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file, true);
//outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
for (int i = 0; i < uAverage.size(); i += 3) {
//outputStream.write((getValues.get(i) + ",").getBytes());
outputStream.write((getValues.get(i) + ",").getBytes());
outputStream.write((getValues.get(i + 1) + ",").getBytes());
outputStream.write((getValues.get(i + 2) + "\n").getBytes());
}
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
Log.d("MyEntryData", String.valueOf(getValues));
handler = new Handler();
final Runnable runnable = new Runnable() {
#Override
public void run() {
readingRemaining = readingRemaining -1;
if (readingRemaining > 0){
plotGraph(img_Y_Avg);
//plotGraph(img_U_Avg);
//plotGraph(img_V_Avg);
}
}
};
handler.postDelayed(runnable, 100);
//Log.d("MyEntryData", String.valueOf(img_Y_Avg +" "+ img_U_Avg+" "+img_V_Avg));
}
private void plotGraph(double graph_data){
LineData data = bp_graph.getData();
if (data != null){
ILineDataSet set = data.getDataSetByIndex(0);
if (set == null){
set = createSet();
data.addDataSet(set);
}
//add a new value
int randomDataSetIndex = (int) (Math.random() * data.getDataSetCount());
float yValue = (float) graph_data;
data.addEntry(new Entry(data.getDataSetByIndex(randomDataSetIndex).getEntryCount(), yValue), randomDataSetIndex);
//notify chart data have changed
bp_graph.notifyDataSetChanged();
bp_graph.setVisibleXRangeMaximum(100);
//scroll to last entry
bp_graph.moveViewTo(data.getEntryCount() - 7, 50f, YAxis.AxisDependency.RIGHT);
}
}}
I am doing the image processing inside the CameraView class and then with the help of an interface sending the values to MainActivity, where I generate the .csv file and the graph.
How do i get the time difference between each frame(or 2 consecutive y-sum) that is being generated?
Like this:
long startTime = System.currentTimeMillis();
img_Y_Avg = ImageProcessing.YUV420SPtoYSum(data, width, height);
img_U_Avg = ImageProcessing.YUV420SPtoUSum(data, width, height);
img_V_Avg = ImageProcessing.YUV420SPtoVSum(data, width, height);
long finishTime = System.currentTimeMillis();
mPreviewReadyCallback.onPreviewFrame(img_Y_Avg, img_U_Avg, img_V_Avg,finishTime-startTime);
And add this parameter to interface:
public interface PreviewReadyCallback {
void onPreviewFrame(int yAverage, int uAverage, int vAverage, long time);
}
Then save it to CSV like other values...
Update:
That was your calculation time. If you want time between frames:
In class:
long oldTime=System.currentTimeMillis();
and then
img_Y_Avg = ImageProcessing.YUV420SPtoYSum(data, width, height);
img_U_Avg = ImageProcessing.YUV420SPtoUSum(data, width, height);
img_V_Avg = ImageProcessing.YUV420SPtoVSum(data, width, height);
long newTime = System.currentTimeMillis();
mPreviewReadyCallback.onPreviewFrame(img_Y_Avg, img_U_Avg, img_V_Avg,newTime-oldTime);
oldTime=newTime;
I have implemented my custom CamerView with TextureView which works perfectly fine. Though in some devices such as Motorolla G4 - MarshMallow, Lenovo KNote - Lollipop Camera Preview flickers with Green Square View appears on the screen.
Here's my CameraTextureView
public class CameraTextureView extends TextureView implements TextureView.SurfaceTextureListener {
private static final String TAG = CameraTextureView.class.getSimpleName();
private Camera mCamera;
private List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;
private SurfaceTexture mSurfaceTexture;
private Handler mHandler;
private Context mContext;
public void setCamera(Camera mCamera) {
try {
this.mCamera = mCamera;
if (mCamera == null) {
return;
}
startCameraPreview();
} catch (Exception e) {
FileLog.e(TAG, e);
}
}
public Camera getCamera() {
return mCamera;
}
public CameraTextureView(Context context, Camera mCamera) {
super(context);
try {
this.setSurfaceTextureListener(this);
this.mCamera = mCamera;
this.mSurfaceTexture = getSurfaceTexture();
this.mHandler = new Handler();
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
this.mContext = context;
} catch (Exception e) {
FileLog.e(TAG, e);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
try {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
float ratio;
if (mPreviewSize.height >= mPreviewSize.width)
ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
else
ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;
setMeasuredDimension(width, ApplicationLoader.getPreferences().isToShowTeamList() == true ? (int) (width * ratio) : height);
} catch (Exception e) {
FileLog.e(TAG, e);
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
try {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
} catch (Exception e) {
FileLog.e(TAG, e);
}
return null;
}
public void startCameraPreview() {
try {
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
mCamera.setPreviewTexture(getSurfaceTexture());
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
parameters.setRotation(90);
mCamera.setDisplayOrientation(90);
mCamera.setParameters(parameters);
mCamera.startPreview();
} catch (Exception e) {
FileLog.e(TAG, e);
}
}
};
Thread thread = new Thread(runnable);
thread.start();
} catch (Exception e) {
FileLog.e(TAG, e);
}
}
private void setCameraDisplayOrientation(Context mContext, android.hardware.Camera camera) {
try{
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
/*int rotation = mContext.getWindowManager().getDefaultDisplay().getRotation();*/
Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int rotation = display.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);
}catch(Exception e){
FileLog.e(TAG, e.toString());
}
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
startCameraPreview();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
}
Though while taking screenshot it appears normal on screenshot.
In some device the the image become stretched, I'm using surfaceView in may camera preview.
public class vp02ImageCapture extends SuperVP {
private static final String TAG = "vp02ImageCapture";
private Camera camera;
#Bind(R.id.TransparentView) SurfaceView transparentView;
#Bind(R.id.sv_camera) SurfaceView sv;
#Bind(R.id.relative) RelativeLayout rl;
#Bind(R.id.mask) FrameLayout mask;
private ProgressDialog dp;
private boolean front = true;
private SurfaceHolder sh,holderTransparent;
int orient = 1;
private Handler h = new Handler();
View v;
//private UserInfo info;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
v = inflater.inflate(R.layout.vp02imagecapture, null);
ButterKnife.bind(this, v);
sh = sv.getHolder();
holderTransparent = transparentView.getHolder();
holderTransparent.setFormat(PixelFormat.TRANSPARENT);
transparentView.setZOrderMediaOverlay(true);
return v;
}
public int getscrOrientation()
{
Display getOrient = getActivity().getWindowManager().getDefaultDisplay();
int orientation = getOrient.getOrientation();
// Sometimes you may get undefined orientation Value is 0
// simple logic solves the problem compare the screen
// X,Y Co-ordinates and determine the Orientation in such cases
if(orientation==Configuration.ORIENTATION_UNDEFINED){
Configuration config = getResources().getConfiguration();
orientation = config.orientation;
if(orientation== Configuration.ORIENTATION_UNDEFINED){
//if height and widht of screen are equal then
// it is square orientation
if(getOrient.getWidth()==getOrient.getHeight()){
orientation = Configuration.ORIENTATION_SQUARE;
}else{ //if widht is less than height than it is portrait
if(getOrient.getWidth() < getOrient.getHeight()){
orientation = Configuration.ORIENTATION_PORTRAIT;
}else{ // if it is not any of the above it will defineitly be landscape
orientation = Configuration.ORIENTATION_LANDSCAPE;
}
}
}
}
return orientation; // return value 1 is portrait and 2 is Landscape Mode
}
openCamera() method
private void openCamera() {
int cameraId;
if (front) {
cameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
} else{
cameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
}
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = getActivity().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);
final Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
Camera.Size optimalSize = getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
transparentView.requestLayout();
sv.requestLayout();
h.postDelayed(new Runnable() {
#Override
public void run() {
try {
Draw();
// camera.setParameters(parameters);
camera.setPreviewDisplay(sh);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
}, 200);
}
#Override
public void releaseUI() {
rl.setVisibility(View.GONE);
// hideProgressDialog();
camera.release();
}
#Override
public void updateUI() {
super.updateUI();
Log.e("sample","asd " + TAG);
if (TAG.equals("vp02ImageCapture")){
parent.btnNext.setVisibility(View.GONE);
parent.btnBack.setVisibility(View.GONE);
}else{
parent.btnNext.setVisibility(View.VISIBLE);
parent.btnBack.setVisibility(View.VISIBLE);
}
getActivity().setTitle("Image Capture");
rl.setVisibility(View.VISIBLE);
openCamera();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("isfront", front);
}
#OnClick(R.id.btnSwitch)void switchCamera(){
camera.stopPreview();
camera.release();
front = front ? false : true;
openCamera();
}
#OnClick(R.id.btnCapture) void capture(){
// showProgressDialog("Loading...");
camera.takePicture(new Camera.ShutterCallback() {
#Override
public void onShutter() {
}
}, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
}
}, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// rotate capture image
Display display = getActivity().getWindowManager().getDefaultDisplay();
int rotation = 0;
switch (display.getRotation()) {
case Surface.ROTATION_0: // This is display orientation
rotation = 90;
break;
case Surface.ROTATION_90:
rotation = 0;
break;
case Surface.ROTATION_180:
rotation = 270;
break;
case Surface.ROTATION_270:
rotation = 180;
break;
}
//Crop image size
Bitmap bitmap = ImageFactory.byteArrayToBitmap(data);
if (front) {
bitmap = rotate(bitmap, rotation);
}
int l = sv.getWidth() / 8;
int t = (sv.getHeight() / 2) - (l*4);
// 2.3 Size of rotated bitmap
int bitWidth = bitmap.getWidth();
int bitHeight = bitmap.getHeight();
Log.e("SIZES", "" + sv.getHeight() + "----" + bitHeight + "-----");
// 3. Size of camera preview on screen
int preWidth = sv.getWidth();
int preHeight = sv.getHeight();
// 4. Scale it.
// Assume you draw Rect as "canvas.drawRect(60, 50, 210, 297, paint);" command
// canvas.drawRect(l,t,l*7,t + l*8,paint1);
// int startx = (l * bitWidth / preWidth);
// int starty = (t * bitHeight / preHeight);
// int endx = ((l * 6) * bitWidth / preWidth);
// int endy = (((t * 4) * bitHeight / preHeight));
int startx = (l * bitWidth / preWidth);
int starty = (t * bitHeight / preHeight);
int endx = ((l * 6) * bitWidth / preWidth);
int endy = (((t + (l*7)) * bitHeight / preHeight));
Log.e("ELIBOY!", "" + l + "----" + t + "------" + l * 7 + "----" + t * 5);
Log.e("ELI!!!!", "" + startx + "----" + starty + "------" + endx + "----" + endy);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
setImageByteArray(byteArray);
setStartX(startx);
setStartY(starty);
setEndX(endx);
setEndY(endy);
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1); //set next page to display ; current page + 1
/*Fragment f = new vp03ImagePreview();
f.setArguments(b);
getParentFragment().getChildFragmentManager().beginTransaction().replace(R.id.imagefrag_container,f).commit();*/
//ScreenManager.getInstance().replaceScreen(Screens.Enroll02b,b);
}
});
}
boolean fromPause = false;
#Override
public void onResume() {
super.onResume();
if(fromPause)
if(((ScreenTransaction)getParentFragment()).viewPager.getCurrentItem()==1)
openCamera();
fromPause = false;
}
#Override
public void onPause() {
super.onPause();
try{
camera.release();
}catch (NullPointerException e){
}
h.removeCallbacksAndMessages(null);
fromPause = true;
//viewPager.removeOnPageChangeListener(viewpagerChangeListener);
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.5;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
#OnClick(R.id.mask)void autofocus(){
camera.autoFocus(new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
}
});
}
public void showProgressDialog(String message){
dp = new ProgressDialog(getActivity());
dp.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dp.setCancelable(false);
dp.setMessage(message);
dp.show();
}
public void hideProgressDialog(){
dp.hide();
}
}
I want to support all screen .
How can I solve this?
in some screen its working but in some specially when its default camera is not in full screen.
I have made this code and its working very well.
public class CameraActivity extends Activity implements Constants.Parameters {
FrameLayout previewFrameLayout;
ImageButton captureButton, switchCamera, flashImageButton, backImageButton;
boolean isFlashEnabled = false, isFlashAvailable = false, isFrontCamera = false;
Handler handler;
private int mCameraId;
private Camera mCamera;
private CameraPreview mCameraPreview;
public final int BACK_CAMERA = 0;
public final int FRONT_CAMERA = 1;
String className = "";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
handler = new Handler();
isFlashAvailable = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
isFrontCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
previewFrameLayout = (FrameLayout) findViewById(R.id.camera_preview);
captureButton = (ImageButton) findViewById(R.id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPicture);
}
});
switchCamera = (ImageButton) findViewById(R.id.switchCamera);
switchCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Utils.scaleView(switchCamera);
handler.postDelayed(new Runnable() {
#Override
public void run() {
previewFrameLayout.removeAllViews();
if (mCameraId == BACK_CAMERA) {
flashImageButton.setVisibility(View.INVISIBLE);
mCameraId = FRONT_CAMERA;
mCameraPreview = new CameraPreview(CameraNewActivity.this, FRONT_CAMERA);
previewFrameLayout.addView(mCameraPreview);
} else {
flashImageButton.setVisibility(View.VISIBLE);
mCameraId = BACK_CAMERA;
mCameraPreview = new CameraPreview(CameraNewActivity.this, BACK_CAMERA);
previewFrameLayout.addView(mCameraPreview);
}
}
}, 250);
}
});
flashImageButton = (ImageButton) findViewById(R.id.flash);
flashImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Utils.scaleView(flashImageButton);
try {
Camera.Parameters parameters = mCamera.getParameters();
if (!isFlashEnabled) {
isFlashEnabled = true;
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
flashImageButton.setSelected(true);
} else {
isFlashEnabled = false;
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
flashImageButton.setSelected(false);
}
mCamera.setParameters(parameters);
} catch (Exception e) {
e.printStackTrace();
}
}
});
if (!isFlashAvailable) {
flashImageButton.setVisibility(View.GONE);
}
if (!isFrontCamera) {
switchCamera.setVisibility(View.GONE);
}
backImageButton = (ImageButton) findViewById(R.id.back);
backImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
private void hideIcons() {
switchCamera.setVisibility(View.GONE);
captureButton.setVisibility(View.GONE);
flashImageButton.setVisibility(View.GONE);
backImageButton.setVisibility(View.GONE);
}
private void showIcons() {
switchCamera.setVisibility(View.VISIBLE);
captureButton.setVisibility(View.VISIBLE);
flashImageButton.setVisibility(View.VISIBLE);
backImageButton.setVisibility(View.VISIBLE);
}
#Override
protected void onResume() {
super.onResume();
mCameraPreview = new CameraPreview(this, mCameraId);
previewFrameLayout.addView(mCameraPreview);
}
#Override
protected void onPause() {
super.onPause();
mCameraPreview.stop();
previewFrameLayout.removeView(mCameraPreview); // This is necessary.
mCameraPreview = null;
}
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
final File pictureFile = new File(Utils.profilePicPath + String.valueOf(System.currentTimeMillis()) + ".jpg");
pictureFile.getParentFile().mkdirs();
Utils.deleteCapture();
if (pictureFile == null) {
return;
}
Thread thread = new Thread() {
#Override
public void run() {
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pictureFile.getPath(), bmOptions);
final int height = bmOptions.outHeight;
final int width = bmOptions.outWidth;
if (height > width) {
if (height / width < 1.5) {
Bitmap bitmap = Picasso.with(CameraNewActivity.this)
.load(pictureFile).resize((int) (height / 1.65), height).centerCrop().get();
if (mCameraId == FRONT_CAMERA) {
bitmap = flip(bitmap);
}
FileOutputStream out = new FileOutputStream(pictureFile.getPath());
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
thread.start();
}
};
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
protected List<Camera.Size> mPreviewSizeList;
protected List<Camera.Size> mPictureSizeList;
protected Camera.Size mPreviewSize;
protected Camera.Size mPictureSize;
private int mSurfaceChangedCallDepth = 0;
private int mCenterPosX = -1;
private int mCenterPosY = 0;
protected boolean mSurfaceChanged = false;
public CameraPreview(Activity activity, int cameraId) {
super(activity);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
if (Camera.getNumberOfCameras() > cameraId) {
mCameraId = cameraId;
} else {
mCameraId = 0;
}
mCamera = Camera.open(mCameraId);
Camera.Parameters cameraParams = mCamera.getParameters();
mPreviewSizeList = cameraParams.getSupportedPreviewSizes();
mPictureSizeList = cameraParams.getSupportedPictureSizes();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mSurfaceChangedCallDepth++;
mCamera.stopPreview();
Camera.Parameters cameraParams = mCamera.getParameters();
if (!mSurfaceChanged) {
Camera.Size previewSize = determinePreviewSize(width, height);
Camera.Size pictureSize = determinePictureSize(previewSize);
mPreviewSize = previewSize;
mPictureSize = pictureSize;
mSurfaceChanged = adjustSurfaceLayoutSize(previewSize, width, height);
if (mSurfaceChanged && (mSurfaceChangedCallDepth <= 1)) {
return;
}
}
if (mCameraId == BACK_CAMERA) {
cameraParams.setRotation(90);
} else {
cameraParams.setRotation(270);
}
mCamera.setDisplayOrientation(90);
cameraParams.set("orientation", "portrait");
cameraParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
cameraParams.setPictureSize(mPictureSize.width, mPictureSize.height);
mCamera.setParameters(cameraParams);
mSurfaceChanged = false;
try {
mCamera.startPreview();
} catch (Exception e) {
// Remove failed size
mPreviewSizeList.remove(mPreviewSize);
mPreviewSize = null;
// Reconfigure
if (mPreviewSizeList.size() > 0) { // prevent infinite loop
surfaceChanged(null, 0, width, height);
} else {
Utils.showToast(CameraNewActivity.this, "Can't start preview", Toast.LENGTH_LONG);
}
}
mSurfaceChangedCallDepth--;
}
protected Camera.Size determinePreviewSize(int reqWidth, int reqHeight) {
int reqPreviewWidth = reqHeight; // requested width in terms of camera hardware
int reqPreviewHeight = reqWidth; // requested height in terms of camera hardware
// Adjust surface size with the closest aspect-ratio
float reqRatio = ((float) reqPreviewWidth) / reqPreviewHeight;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
Camera.Size retSize = null;
for (Camera.Size size : mPreviewSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return retSize;
}
protected Camera.Size determinePictureSize(Camera.Size previewSize) {
Camera.Size retSize = null;
for (Camera.Size size : mPictureSizeList) {
if (size.equals(previewSize)) {
return size;
}
}
// if the preview size is not supported as a picture size
float reqRatio = ((float) previewSize.width) / previewSize.height;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
for (Camera.Size size : mPictureSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return retSize;
}
protected boolean adjustSurfaceLayoutSize(Camera.Size previewSize,
int availableWidth, int availableHeight) {
float tmpLayoutHeight = previewSize.width;
float tmpLayoutWidth = previewSize.height;
float factH, factW, fact;
factH = availableHeight / tmpLayoutHeight;
factW = availableWidth / tmpLayoutWidth;
if (factH < factW) {
fact = factH;
} else {
fact = factW;
}
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) this.getLayoutParams();
int layoutHeight = (int) (tmpLayoutHeight * fact);
int layoutWidth = (int) (tmpLayoutWidth * fact);
boolean layoutChanged;
if ((layoutWidth != this.getWidth()) || (layoutHeight != this.getHeight())) {
layoutParams.height = layoutHeight;
layoutParams.width = layoutWidth;
if (mCenterPosX >= 0) {
layoutParams.topMargin = mCenterPosY - (layoutHeight / 2);
layoutParams.leftMargin = mCenterPosX - (layoutWidth / 2);
}
this.setLayoutParams(layoutParams); // this will trigger another surfaceChanged invocation.
layoutChanged = true;
} else {
layoutChanged = false;
}
return layoutChanged;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
stop();
}
public void stop() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
}
public Bitmap flip(Bitmap bitmap) {
Matrix mtx = new Matrix();
mtx.preScale(-1, 1);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), mtx, true);
}
}
I am creating a camera application using android camera api by this example: https://examples.javacodegeeks.com/android/core/hardware/camera-hardware/android-camera-example/
I made some changes according to my needs and you can see the code below. The problem is, camera preview for back camera works quite fine on my LG G3 device but on LG G4 it gets too slow. It also works fine with front camera on both devices.
What can cause this problem ?
CameraPreview:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{
private static String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
private List<Size> mSupportedPreviewSizes;
private Size mPreviewSize;
public CameraPreview(Context context, Camera camera){
super(context);
mCamera = camera;
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{
Log.d(TAG, "Surface Created..");
if(mCamera == null){
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
}
} catch (IOException e) {
Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void refreshCamera(Camera camera) {
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.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
setCamera(camera);
try {
Log.d(TAG,"RefreshCamera..");
if(mCamera == null){
Log.d(TAG,"Camera null");
}
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewDisplay(mHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
Log.d(TAG, "Surface Changed..");
refreshCamera(mCamera);
}
public void setCamera(Camera camera) {
//method to set a camera instance
mCamera = camera;
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
mCamera.release();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG,"onMeasure..");
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if(mSupportedPreviewSizes==null){
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
}else{
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
Log.d(TAG, "mPreviewSize set.. Width: " + mPreviewSize.width+" Height: " + mPreviewSize.height);
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
}
I can share the Activity class if its needed..
Thanks..
I had the same problem using surface view .use the below preview class.its working for me for all the device screen.
public class SquareCameraPreview extends SurfaceView {
public static final String TAG = SquareCameraPreview.class.getSimpleName();
private static final int INVALID_POINTER_ID = -1;
private static final int ZOOM_OUT = 0;
private static final int ZOOM_IN = 1;
private static final int ZOOM_DELTA = 1;
private static final int FOCUS_SQR_SIZE = 100;
private static final int FOCUS_MAX_BOUND = 1000;
private static final int FOCUS_MIN_BOUND = -FOCUS_MAX_BOUND;
private static final double ASPECT_RATIO = 3.0 / 4.0;
private Camera mCamera;
private float mLastTouchX;
private float mLastTouchY;
// For scaling
private int mMaxZoom;
private boolean mIsZoomSupported;
private int mActivePointerId = INVALID_POINTER_ID;
private int mScaleFactor = 1;
private ScaleGestureDetector mScaleDetector;
// For focus
private boolean mIsFocus;
private boolean mIsFocusReady;
private Camera.Area mFocusArea;
private ArrayList<Camera.Area> mFocusAreas;
public SquareCameraPreview(Context context) {
super(context);
init(context);
}
public SquareCameraPreview(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SquareCameraPreview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
mFocusArea = new Camera.Area(new Rect(), 1000);
mFocusAreas = new ArrayList<Camera.Area>();
mFocusAreas.add(mFocusArea);
}
/**
* Measure the view and its content to determine the measured width and the
* measured height
*/
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
final boolean isPortrait =
getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
if (isPortrait) {
if (width > height * ASPECT_RATIO) {
width = (int) (height * ASPECT_RATIO + 0.5);
} else {
height = (int) (width / ASPECT_RATIO + 0.5);
}
} else {
if (height > width * ASPECT_RATIO) {
height = (int) (width * ASPECT_RATIO + 0.5);
} else {
width = (int) (height / ASPECT_RATIO + 0.5);
}
}
setMeasuredDimension(width, height);
}
public int getViewWidth() {
return getWidth();
}
public int getViewHeight() {
return getHeight();
}
public void setCamera(Camera camera) {
mCamera = camera;
if (camera != null) {
Camera.Parameters params = camera.getParameters();
mIsZoomSupported = params.isZoomSupported();
if (mIsZoomSupported) {
mMaxZoom = params.getMaxZoom();
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mScaleDetector.onTouchEvent(event);
final int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
mIsFocus = true;
mLastTouchX = event.getX();
mLastTouchY = event.getY();
mActivePointerId = event.getPointerId(0);
break;
}
case MotionEvent.ACTION_UP: {
if (mIsFocus && mIsFocusReady) {
handleFocus(mCamera.getParameters());
}
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_DOWN: {
mCamera.cancelAutoFocus();
mIsFocus = false;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
}
return true;
}
private void handleZoom(Camera.Parameters params) {
int zoom = params.getZoom();
if (mScaleFactor == ZOOM_IN) {
if (zoom < mMaxZoom) zoom += ZOOM_DELTA;
} else if (mScaleFactor == ZOOM_OUT) {
if (zoom > 0) zoom -= ZOOM_DELTA;
}
params.setZoom(zoom);
mCamera.setParameters(params);
}
private void handleFocus(Camera.Parameters params) {
float x = mLastTouchX;
float y = mLastTouchY;
if (!setFocusBound(x, y)) return;
List<String> supportedFocusModes = params.getSupportedFocusModes();
if (supportedFocusModes != null
&& supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
Log.d(TAG, mFocusAreas.size() + "");
params.setFocusAreas(mFocusAreas);
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(params);
mCamera.autoFocus(new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
// Callback when the auto focus completes
}
});
}
}
public void setIsFocusReady(final boolean isFocusReady) {
mIsFocusReady = isFocusReady;
}
private boolean setFocusBound(float x, float y) {
int left = (int) (x - FOCUS_SQR_SIZE / 2);
int right = (int) (x + FOCUS_SQR_SIZE / 2);
int top = (int) (y - FOCUS_SQR_SIZE / 2);
int bottom = (int) (y + FOCUS_SQR_SIZE / 2);
if (FOCUS_MIN_BOUND > left || left > FOCUS_MAX_BOUND) return false;
if (FOCUS_MIN_BOUND > right || right > FOCUS_MAX_BOUND) return false;
if (FOCUS_MIN_BOUND > top || top > FOCUS_MAX_BOUND) return false;
if (FOCUS_MIN_BOUND > bottom || bottom > FOCUS_MAX_BOUND) return false;
mFocusArea.rect.set(left, top, right, bottom);
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor = (int) detector.getScaleFactor();
handleZoom(mCamera.getParameters());
return true;
}
}
}
public class CameraFragment extends Fragment implements SurfaceHolder.Callback, Camera.PictureCallback {
public static int HIGH_RESOLUTION_WIDTH=1000;
public static int HIGH_RESOLUTION_HIGHT=1500;
public static String clorie_count;
private long startTime = 0L;
public static final String TAG = CameraFragment.class.getSimpleName();
public static final String CAMERA_ID_KEY = "camera_id";
public static final String CAMERA_FLASH_KEY = "flash_mode";
public static final String IMAGE_INFO = "image_info";
private static final int PICTURE_SIZE_MAX_WIDTH = 1280;
private static final int PREVIEW_SIZE_MAX_WIDTH = 640;
private int mCameraID;
private String mFlashMode;
private Camera mCamera;
private SquareCameraPreview mPreviewView;
private SurfaceHolder mSurfaceHolder;
private boolean mIsSafeToTakePhoto = false;
private ImageParameters mImageParameters;
private CameraOrientationListener mOrientationListener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
context = activity;
mOrientationListener = new CameraOrientationListener(context);
}
View view;
Dialog listDialog;
#SuppressLint("NewApi")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.camera_fragment, container, false);
if (savedInstanceState == null) {
mCameraID = getBackCameraID();
mFlashMode = CameraSettingPreferences.getCameraFlashMode(getActivity());
mImageParameters = new ImageParameters();
} else {
mCameraID = savedInstanceState.getInt(CAMERA_ID_KEY);
mFlashMode = savedInstanceState.getString(CAMERA_FLASH_KEY);
mImageParameters = savedInstanceState.getParcelable(IMAGE_INFO);
}
mPreviewView = (SquareCameraPreview) view.findViewById(R.id.camerapreview);
mPreviewView.getHolder().addCallback(CameraFragment.this);
mImageParameters.mIsPortrait =getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
capture_icon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
takePicture();
}
});
return view;
}
private void takePicture() {
if (mIsSafeToTakePhoto) {
setSafeToTakePhoto(false);
mOrientationListener.rememberOrientation();
// Shutter callback occurs after the image is captured. This can
// be used to trigger a sound to let the user know that image is taken
Camera.ShutterCallback shutterCallback = null;
// Raw callback occurs when the raw image data is available
Camera.PictureCallback raw = null;
// postView callback occurs when a scaled, fully processed
// postView image is available.
Camera.PictureCallback postView = null;
// jpeg callback occurs when the compressed image is available
mCamera.takePicture(shutterCallback, raw, postView, this);
}
}
private void setSafeToTakePhoto(final boolean isSafeToTakePhoto) {
mIsSafeToTakePhoto = isSafeToTakePhoto;
}
private void setCameraFocusReady(final boolean isFocusReady) {
if (this.mPreviewView != null) {
mPreviewView.setIsFocusReady(isFocusReady);
}
}
/**
* Determine the current display orientation and rotate the camera preview
* accordingly
*/
private void determineDisplayOrientation() {
CameraInfo cameraInfo = new CameraInfo();
Camera.getCameraInfo(mCameraID, cameraInfo);
// Clockwise rotation needed to align the window display to the natural position
int rotation = getActivity().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 displayOrientation;
// CameraInfo.Orientation is the angle relative to the natural position of the device
// in clockwise rotation (angle that is rotated clockwise from the natural position)
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
// Orientation is angle of rotation when facing the camera for
// the camera image to match the natural orientation of the device
displayOrientation = (cameraInfo.orientation + degrees) % 360;
displayOrientation = (360 - displayOrientation) % 360;
} else {
displayOrientation = (cameraInfo.orientation - degrees + 360) % 360;
}
mImageParameters.mDisplayOrientation = displayOrientation;
mImageParameters.mLayoutOrientation = degrees;
mCamera.setDisplayOrientation(mImageParameters.mDisplayOrientation);
}
private void setupCamera() {
// Never keep a global parameters
Camera.Parameters parameters = mCamera.getParameters();
Size bestPreviewSize = determineBestPreviewSize(parameters);
Size bestPictureSize = determineBestPictureSize(parameters);
parameters.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
parameters.setPictureSize(bestPictureSize.width, bestPictureSize.height);
// Set continuous picture focus, if it's supported
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
final View changeCameraFlashModeBtn = getView().findViewById(R.id.flash);
List<String> flashModes = parameters.getSupportedFlashModes();
if (flashModes != null && flashModes.contains(mFlashMode)) {
parameters.setFlashMode(mFlashMode);
changeCameraFlashModeBtn.setVisibility(View.VISIBLE);
} else {
changeCameraFlashModeBtn.setVisibility(View.INVISIBLE);
}
// Lock in the changes
mCamera.setParameters(parameters);
}
private Size determineBestPreviewSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPreviewSizes(), PREVIEW_SIZE_MAX_WIDTH);
}
private Size determineBestPictureSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPictureSizes(), PICTURE_SIZE_MAX_WIDTH);
}
private Size determineBestSize(List<Size> sizes, int widthThreshold) {
Size bestSize = null;
Size size;
int numOfSizes = sizes.size();
for (int i = 0; i < numOfSizes; i++) {
size = sizes.get(i);
boolean isDesireRatio = (size.width / 4) == (size.height / 3);
boolean isBetterSize = (bestSize == null) || size.width > bestSize.width;
if (isDesireRatio && isBetterSize) {
bestSize = size;
}
}
if (bestSize == null) {
Log.d(TAG, "cannot find the best camera size");
return sizes.get(sizes.size() - 1);
}
return bestSize;
}
/**
* Start the camera preview
*/
private void startCameraPreview() {
determineDisplayOrientation();
setupCamera();
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
setSafeToTakePhoto(true);
setCameraFocusReady(true);
} catch (IOException e) {
Log.d(TAG, "Can't start camera preview due to IOException " + e);
e.printStackTrace();
}
}
private void getCamera(int cameraID) {
try {
mCamera = Camera.open(cameraID);
mPreviewView.setCamera(mCamera);
} catch (Exception e) {
Log.d(TAG, "Can't open camera with id " + cameraID);
e.printStackTrace();
}
}
#Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
HERE YOU GET THE PHOTO BYTE[] arg0
CONVERT IT TO BITMAP OR STROE INTO A FILE
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
mSurfaceHolder = holder;
getCamera(mCameraID);
startCameraPreview();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
}
private static class CameraOrientationListener extends OrientationEventListener {
private int mCurrentNormalizedOrientation;
private int mRememberedNormalOrientation;
public CameraOrientationListener(Context context) {
super(context, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onOrientationChanged(int orientation) {
if (orientation != ORIENTATION_UNKNOWN) {
mCurrentNormalizedOrientation = normalize(orientation);
}
}
/**
* #param degrees Amount of clockwise rotation from the device's natural position
* #return Normalized degrees to just 0, 90, 180, 270
*/
private int normalize(int degrees) {
if (degrees > 315 || degrees <= 45) {
return 0;
}
if (degrees > 45 && degrees <= 135) {
return 90;
}
if (degrees > 135 && degrees <= 225) {
return 180;
}
if (degrees > 225 && degrees <= 315) {
return 270;
}
throw new RuntimeException("The physics as we know them are no more. Watch out for anomalies.");
}
public void rememberOrientation() {
mRememberedNormalOrientation = mCurrentNormalizedOrientation;
}
public int getRememberedNormalOrientation() {
rememberOrientation();
return mRememberedNormalOrientation;
}
}
/*#Override
public void onResume() {
super.onResume();
if (mCamera == null) {
restartPreview();
}
}*/
#Override
public void onStop() {
mOrientationListener.disable();
// stop the preview
if (mCamera != null) {
stopCameraPreview();
mCamera.release();
mCamera = null;
}
if (getKillStatus()) {
android.os.Process.killProcess(android.os.Process.myPid());
}
// CameraSettingPreferences.saveCameraFlashMode(getActivity(), mFlashMode);
super.onStop();
}
#Override
public void onResume() {
super.onResume();
/*if (camera != null) {
camera.stopPreview();
preview.setupCamera(null,isResolutionHigh);
camera.release();
camera = null;
}
int numCams = Camera.getNumberOfCameras();
if (numCams > 0) {
try {
camera = Camera.open(0);
camera.startPreview();
preview.setupCamera(camera,isResolutionHigh);
} catch (RuntimeException ex) {
// Toast.makeText(ctx, getString(R.string.camera_not_found),
// Toast.LENGTH_LONG).show();
}
}*/
if (mCamera == null) {
restartPreview();
}
}
private void restartPreview() {
if (mCamera != null) {
stopCameraPreview();
mCamera.release();
mCamera = null;
}
getCamera(mCameraID);
startCameraPreview();
}
/**
* Stop the camera preview
*/
private void stopCameraPreview() {
setSafeToTakePhoto(false);
setCameraFocusReady(false);
// Nulls out callbacks, stops face detection
mCamera.stopPreview();
mPreviewView.setCamera(null);
}
private int getBackCameraID() {
return CameraInfo.CAMERA_FACING_BACK;
}
}
AND YOUR XML FILE
<com.demo.camera.SquareCameraPreview
android:id="#+id/camerapreview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
ImageParameter Class
public class ImageParameters implements Parcelable {
public boolean mIsPortrait;
public int mDisplayOrientation;
public int mLayoutOrientation;
public int mCoverHeight, mCoverWidth;
public int mPreviewHeight, mPreviewWidth;
public ImageParameters(Parcel in) {
mIsPortrait = (in.readByte() == 1);
mDisplayOrientation = in.readInt();
mLayoutOrientation = in.readInt();
mCoverHeight = in.readInt();
mCoverWidth = in.readInt();
mPreviewHeight = in.readInt();
mPreviewWidth = in.readInt();
}
public ImageParameters() {}
public int calculateCoverWidthHeight() {
return Math.abs(mPreviewHeight - mPreviewWidth) / 2;
}
public int getAnimationParameter() {
return mIsPortrait ? mCoverHeight : mCoverWidth;
}
public boolean isPortrait() {
return mIsPortrait;
}
public ImageParameters createCopy() {
ImageParameters imageParameters = new ImageParameters();
imageParameters.mIsPortrait = mIsPortrait;
imageParameters.mDisplayOrientation = mDisplayOrientation;
imageParameters.mLayoutOrientation = mLayoutOrientation;
imageParameters.mCoverHeight = mCoverHeight;
imageParameters.mCoverWidth = mCoverWidth;
imageParameters.mPreviewHeight = mPreviewHeight;
imageParameters.mPreviewWidth = mPreviewWidth;
return imageParameters;
}
public String getStringValues() {
return "is Portrait: " + mIsPortrait + "," +
"\ncover height: " + mCoverHeight + " width: " + mCoverWidth
+ "\npreview height: " + mPreviewHeight + " width: " + mPreviewWidth;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (mIsPortrait ? 1 : 0));
dest.writeInt(mDisplayOrientation);
dest.writeInt(mLayoutOrientation);
dest.writeInt(mCoverHeight);
dest.writeInt(mCoverWidth);
dest.writeInt(mPreviewHeight);
dest.writeInt(mPreviewWidth);
}
public static final Creator<ImageParameters> CREATOR = new Parcelable.Creator<ImageParameters>() {
#Override
public ImageParameters createFromParcel(Parcel source) {
return new ImageParameters(source);
}
#Override
public ImageParameters[] newArray(int size) {
return new ImageParameters[size];
}
};
}
Another class you need camera setting preference
public class CameraSettingPreferences {
private static final String FLASH_MODE = "squarecamera__flash_mode";
private static SharedPreferences getCameraSettingPreferences(#NonNull final Context context) {
return context.getSharedPreferences("com.desmond.squarecamera", Context.MODE_PRIVATE);
}
protected static void saveCameraFlashMode(#NonNull final Context context, #NonNull final String cameraFlashMode) {
final SharedPreferences preferences = getCameraSettingPreferences(context);
if (preferences != null) {
final SharedPreferences.Editor editor = preferences.edit();
editor.putString(FLASH_MODE, cameraFlashMode);
editor.apply();
}
}
public static String getCameraFlashMode(#NonNull final Context context) {
final SharedPreferences preferences = getCameraSettingPreferences(context);
if (preferences != null) {
return preferences.getString(FLASH_MODE, Camera.Parameters.FLASH_MODE_AUTO);
}
return Camera.Parameters.FLASH_MODE_AUTO;
}
}
Let me know if you have any doubts.
I have implemented my own camera preview layout and functionality. Anyway, when I press the button to take a picture it calls the onPictureTaken method, but the Intent is not fired. The Intent is declared correctly in the manifest file.
Here is my code and I hope someone knows what to do here in order to fire my Intent.
public class TakePicture extends Activity {
private Preview mPreview;
private Camera mCamera;
private int numberOfCameras;
private int defaultCameraId;
private Context context;
AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback() {
#Override
public void onAutoFocus(boolean arg0, Camera arg1) {
// buttonTakePicture.setEnabled(true);
}
};
PictureCallback myPictureCallback_JPG = new PictureCallback() {
#Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
//savePicture(arg0);
Intent ia = new Intent(context, PreviewPhoto.class);
ia.putExtra("groupId", 1);
ia.putExtra("image", arg0);
startActivity(ia);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_LEFT_ICON);
setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
R.drawable.zzz_logo);
context = this;
mPreview = new Preview(this);
setContentView(mPreview);
LayoutInflater controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.camera_control,
null);
LayoutParams layoutParamsControl = new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
this.addContentView(viewControl, layoutParamsControl);
numberOfCameras = Camera.getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
defaultCameraId = i;
}
}
Button buttonTakePicture = (Button) findViewById(R.id.takepicture);
buttonTakePicture.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View arg0) {
mCamera.takePicture(null, null,
myPictureCallback_JPG);
}
});
}
#Override
protected void onResume() {
super.onResume();
mCamera = Camera.open(defaultCameraId);
mPreview.setCamera(mCamera);
}
#Override
protected void onPause() {
super.onPause();
if (mCamera != null) {
mPreview.setCamera(null);
mCamera.release();
mCamera = null;
}
}
public void determineDisplayOrientation() {
CameraInfo cameraInfo = new CameraInfo();
Camera.getCameraInfo(defaultCameraId, cameraInfo);
int rotation = this.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 displayOrientation;
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
displayOrientation = (cameraInfo.orientation + degrees) % 360;
displayOrientation = (360 - displayOrientation) % 360;
} else {
displayOrientation = (cameraInfo.orientation - degrees + 360) % 360;
}
mCamera.setDisplayOrientation(displayOrientation);
}
private void savePicture(byte[] data) {
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Toast.makeText(context, "Can't create directory to save image.",
Toast.LENGTH_LONG).show();
return;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
File pictureFile = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast.makeText(context, "New Image saved:" + photoFile,
Toast.LENGTH_LONG).show();
} catch (Exception error) {
Toast.makeText(context, "Image could not be saved.",
Toast.LENGTH_LONG).show();
}
}
private File getDir() {
File sdDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return new File(sdDir, "Captoom");
}
class Preview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "Preview";
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
Preview(Context context) {
super(context);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSurfaceView.setOnClickListener(new LinearLayout.OnClickListener() {
#Override
public void onClick(View arg0) {
//buttonTakePicture.setEnabled(false);
mCamera.autoFocus(myAutoFocusCallback);
}
});
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters()
.getSupportedPreviewSizes();
requestLayout();
}
}
public void switchCamera(Camera camera) {
setCamera(camera);
//determineDisplayOrientation();
try {
camera.setPreviewDisplay(mHolder);
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
camera.setParameters(parameters);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(),
widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,
height);
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height
/ previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width
/ previewWidth;
child.layout(0, (height - scaledChildHeight) / 2, width,
(height + scaledChildHeight) / 2);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
}
The line ia.putExtra("image", arg0) is causing the error failed binder transaction. I must pass the image path, not the byte[] of data to the new intent :)