I am working on my custom camera on android device.The preview is full screen activity.
To solve the stretch problem I use the codes like this:
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
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.height / size.width;
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;
}
//optimalSize
myParam.setPreviewSize(optimalSize.width,optimalSize.height);
mCamera.setParameters(myParam);
mCamera.startPreview();
yes ,it works in almost of devices.But in some device it does't work! what ever size i setted which the device was supported,it does't work! so what's wrong?
Related
I'm trying to use a SurfaceView to preview the camera in portrait mode. I'm initializing the camera correctly, and everything is working fine.
However, my SurfaceView has a fixed size, something like this:
<SurfaceView android:id="#+id/surface_view"
android:layout_width="match_parent"
android:layout_height="250dp" />
and I can't get it to preview with the correct ratio, the preview is always stretched.
I'm calculating the preview camera resolution with the following method:
private Point findBestPreviewSizeValue(Camera.Parameters parameters, Point screenResolution, Rect surfaceFrame) {
// Sort by size, descending
List<Camera.Size> supportedPreviewSizes = new ArrayList<Camera.Size>(parameters.getSupportedPreviewSizes());
Collections.sort(supportedPreviewSizes, new Comparator<Camera.Size>() {
#Override
public int compare(Camera.Size a, Camera.Size b) {
int aPixels = a.height * a.width;
int bPixels = b.height * b.width;
if (bPixels < aPixels) {
return -1;
}
if (bPixels > aPixels) {
return 1;
}
return 0;
}
});
int w;
int h;
if(surfaceFrame == null) {
w = screenResolution.x;
h = screenResolution.y;
} else {
w = surfaceFrame.width();
h = surfaceFrame.height();
}
Log.i(TAG, "Surface resolution is " + new Point(w, h));
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (supportedPreviewSizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : supportedPreviewSizes) {
double ratio = (double) size.height / size.width;
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 : supportedPreviewSizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
Point p = new Point(optimalSize.width, optimalSize.height);
Log.i(TAG, "Camera resolution is "+ p.toString());
return p;}
Is there a way to show the camera preview with the correct aspect ratio without modifying the size of the SurfaceView?
Thanks in advance
I am trying to read more about media recorder. The Video size is coming out to be different in different devices. In one device video size was around 31 MB and in other it was 88.5 MB.
Below is the code, that I am used for the media recorder.
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
recorder.setProfile(camcorderProfile);
recorder.setVideoSize(optimalVideoSize.width, optimalVideoSize.height);
recorder.setVideoEncodingBitRate(1000000);
recorder.setPreviewDisplay(holder.getSurface());
recorder.setMaxDuration(time_limit*1000);
where, optimalvideosize is an arraylist outputted using the below function:
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h)
{
final double ASPECT_TOLERANCE = 0.2;
double targetRatio = (double) w / h;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes)
{
Log.d("Camera", "Checking size " + size.width + "w " + size.height
+ "h");
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);
}
}
// Cannot find the one match the aspect ratio, ignore the
// requirement
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;
}
Thanks for the Help!!
I have gone through lot of stackoverflow threads on this topic but I did not get solution for my problem. I found a method which calcultate best PreviewSize for your screen. For example this method--
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;
}
To the above method I have to pass screen width and height. Consider I want a picture in 1024*768 but my screen resolution is 1280*720, above method returns 1280*720 as best PreviewSize and camera is capturing more than what actually visible in my display. Is there any way to calculate matching PreviewSize based on required picture size.
We implemented the custom camera functionality in my app. This was working fine in all the devices like nexus4,5,samsung s3,s4 etc except in Samsung galaxy S4 mini. The issue is image was stretching in front camera only but it's working good in back camera of that device.
For Samsung galaxy s4 mini, we are getting the screen size is 540X960 and we got supported preview size is 1280x720. The aspect ratio also same but we are facing image stretching issue. I was tried a lot but i am unable to solve this issue especially in front camera of samsung galaxy s4 mini. Please can anyone help me.
Code
int currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
Camera camera = Camera.open(currentCameraId);
try {
camera.setPreviewDisplay(surfaceHolder);
Camera.Parameters parameters = camera.getParameters();
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.set("orientation", "portrait");
camera.setDisplayOrientation(90);
parameters.setRotation(270);
Display display = getWindowManager().getDefaultDisplay();
int widthd = display.getWidth(); // deprecated
int heightd = display.getHeight();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes();
Camera.Size mPreviewSize = getOptimalPreviewSize(previewSizes, widthd, heightd);
Camera.Size mpicSize = getOptimalPreviewSize(pictureSizes, widthd, heightd);
parameters.setPreviewSize(mPreviewSize.width,mPreviewSize.height);
parameters.setPictureSize(mpicSize.width,mpicSize.height);
camera.setParameters(parameters);
} catch (IOException exception) {
camera.release();
}
camera.startPreview();
Please refer the following code for computing the optimal size.
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 am developing a custom camera app and I am facing the problem with setting the preview size for the camera. The problem is that the camera preview does not persist the aspect ration so the preview looks stretched to the sides.
The code I use to calculate the best size:
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 1;
double targetRatio=(double)w / h;
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;
Log.d("Test", "Ration: " + Math.abs(ratio - targetRatio));
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) {
Log.d("Test", "MATCFH!");
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
I have been struggling with this for a day now and cannot find an optimal solution. Any suggestions will be greatly appreciated!
You are right, changing camera preview size may not preserve aspect ratio. To keep the preview display look nice, you should resize the preview surfaceView accordingly.