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
Related
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?
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.
i'm on creating custom camera for android, but camera previewSize is showing low resolution , how can i make that to best preview size
this is the code for i used get previewSize
private Camera.Size getBestPreviewSize(int width, int height) {
Camera.Size result = null;
Camera.Parameters p = camera.getParameters();
for (Camera.Size size : p.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) {
result = size;
}
}
}
}
return result;
}
results of this code is shows width: 352: height: 288
using below code shows some other resolution
private Camera.Size getBestPreviewSize(int width, int height)
{
List<Size> sizes = camera.getParameters().getSupportedPreviewSizes();
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = height;
int targetWidth = width;
int minWidthDiff = 0;
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.width - targetWidth) < minDiff) {
if(size.width > width) {
if (minWidthDiff == 0) {
minWidthDiff = size.width - width;
optimalSize = size;
}
else if (Math.abs(size.width - targetWidth) < minWidthDiff) {
minWidthDiff = size.width - width;
optimalSize = size;
}
minDiff = Math.abs(size.width - targetWidth);
}
}
}
}
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;
}
results of this code width: 640 : height: 480
but still preview looks blur
EDIT: stop preview before using it
camera.stopPreview();
parameters.setPreviewSize(size.width, size.height);
parameters.setRotation(0);
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.