We are trying to build something similar to Instagram
Camera screen. i.e allow the user taking square
photos. While doing it out U.i must be able to let the user see the camera on fullScreen
mode. We want to force the user to take an image in a portrait
mode
We are calculating the best
ratio available from camera
by
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;
}
public FrameLayout setCameraLayout(int width, int height) {
float newProportion = (float) width / (float) height;
// Get the width of the screen
int screenWidth = this.customCameraActivity.getWindowManager().getDefaultDisplay()
.getWidth();
int screenHeight = this.customCameraActivity.getWindowManager().getDefaultDisplay()
.getHeight();
float screenProportion = (float) screenWidth / (float) screenHeight;
// Get the SurfaceView layout parameters
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)preview.getLayoutParams();
if (newProportion > screenProportion) {
lp.width = screenWidth;
lp.height = (int) ((float) screenWidth / newProportion);
} else {
lp.width = (int) (newProportion * (float) screenHeight);
lp.height = screenHeight;
}
//calculate the amount that takes to make it full screen (in the `height` parameter)
float propHeight = screenHeight / lp.height;
//make it full screen(
lp.width = (int)(lp.width * propHeight);
lp.height = (int)(lp.height * propHeight);
frameLayout.setLayoutParams(lp);
return frameLayout;
}
OnCreate
from the Activity
and afterwards surfaceChanged
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (getHolder().getSurface() == null) {
return;
}
try {
cameraManager.getCamera().stopPreview();
} catch (Exception e) {
// tried to stop a non-existent preview
}
try {
Camera.Parameters cameraSettings = cameraManager.getCamera().getParameters();
cameraSettings.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
this.cameraView.setCameraLayout(mPreviewSize.width, mPreviewSize.height);
cameraManager.getCamera().setParameters(cameraSettings);
cameraManager.getCamera().setPreviewDisplay(holder);
cameraManager.getCamera().startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
Fullscreen camera preview on phone.
Now we are getting the preview with no distortion which is GOOD! and it has the same height
as the phone
as well which is also GOOD!. But! the width of the preview
is bigger than the phone width
(of-course) so it turns out the the center of the camera is not on the center of the phone. Possible solutions we have thought about:
move
the layout left to negative position to make the preview center in the center of the screen.crop
the layout and draw only the center of the new preview
that should be visible to the phone screens
Thanks alot! :)
I managed successfully center the preview by setting gravity of SurfaceView:
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(wid, hei);
lp.gravity = Gravity.CENTER;
mSv.setLayoutParams(lp);
The code snippet is taken from here, and you're welcome to use the code if you have the patience to decipher it. I think I was solving similar issues (preview rotation, distortion, fit-in/fill)
Good Luck.
If I'm understanding from the code snippets, you are re-instantiating the camera everytime the user changes orientation or rotates the camera. Is there any reason to do that?
Why not restrict the preview to portrait only and have an overlaying view that rotates? I am pretty sure that is what others (Instagram,Snapchat, etc.) do. I will edit with an example of this, if I can find it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With