Picture distorted with Camera and getOptimalPreviewSize
I am on a Camera App which taking basic pictures. I have an issue when I get the best optimal preview size.
In fact, with this first code :
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (isPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters parameters = mCamera.getParameters();
mCamera.setParameters(parameters);
mCamera.startPreview();
isPreviewRunning = true;
}
The picture has a good quality :
http://img6开发者_如何学Python89.imageshack.us/i/04042011172937.jpg/
But, with this code :
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.05;
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) {
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;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
if (isPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters parameters = mCamera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, w, h);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
isPreviewRunning =true;
}
The picture is totally distorted :
http://img97.imageshack.us/i/04042011173220.jpg/
How can I resolve this problem??
I am using a HTC Desire HD.
It is probably my saving method too ? :
PictureCallback mPictureCallbackJpeg = new PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera camera) {
....
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 5;
Bitmap myImage = BitmapFactory.decodeByteArray(imageData, 0,imageData.length,options);
FileOutputStream fOut = new FileOutputStream(path + "/"+fl);
BufferedOutputStream bos = new BufferedOutputStream(fOut);
myImage.compress(CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
....
}
Thanks
I just suffered through the same problem, and came up with a similar but lighter weight solution. I don't see anything wrong with your saving method though.
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;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//This line helped me set the preview Display Orientation to Portrait
//Only works API Level 8 and higher unfortunately.
camera.setDisplayOrientation(90);
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = getBestPreviewSize(width, height);
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
camera.startPreview();
}
The best way is to get preview size with the closest aspect ratio:
Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
Camera.Size result=null;
float dr = Float.MAX_VALUE;
float ratio = (float)width/(float)height;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
float r = (float)size.width/(float)size.height;
if( Math.abs(r - ratio) < dr && size.width <= width && size.height <= height ) {
dr = Math.abs(r - ratio);
result = size;
}
}
return result;
}
Where width and height parameters are your surface size.
精彩评论