Prévisualisation de la caméra tendu, même après le réglage de l'dimensions
Je suis de la création d'une application de caméra qui implémente son propre aperçu de l'appareil photo pour prendre des photos.
L'application est actuellement en cours forcé en mode portrait.
Mon problème est que l'aperçu de la caméra est un peu tendue (les proportions sont un peu off).
Le plus drôle, c'est que je suis mon SurfaceView taille de toujours correspondre à la taille de l'aperçu. Cela garantit que le ratio d'aspect doit toujours être perserved... mais il ne l'est pas...
Ici est la mise en page je peux montrer mon aperçu de l'appareil photo:
public class Cp extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "CameraPreview";
private boolean mPreviewRunning = false;
private SurfaceView mSurfaceView;
private SurfaceHolder mHolder;
private Size mPreviewSize;
private List<Size> mSupportedPreviewSizes;
private Camera mCamera;
public boolean IsPreviewRunning() {
return mPreviewRunning;
}
public Cp(Context context) {
this(context, null, 0);
}
public Cp(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Cp(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
//Install a SurfaceHolder.Callback so we get notified when the
//underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
requestLayout();
}
}
public void switchCamera(Camera camera) {
setCamera(camera);
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) {
//We purposely disregard child measurements because act as a wrapper to
//a SurfaceView that
//centers the camera preview instead of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(),
widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes == null && mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters()
.getSupportedPreviewSizes();
}
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.height;
previewHeight = mPreviewSize.width;
}
if (previewWidth == 0) {
previewWidth = 1;
}
if (previewHeight == 0) {
previewHeight = 1;
}
//Center the child SurfaceView within the parent.
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);
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//The Surface has been created, acquire the camera and tell it where to
//draw.
try {
if (mCamera != null) {
Parameters params = mCamera.getParameters();
mSupportedPreviewSizes = params.getSupportedPreviewSizes();
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//Surface will be destroyed when we return, so stop the preview.
stop();
}
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;
//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;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mCamera != null) {
//Now that the size is known, set up the camera parameters and
//begin the preview.
Camera.Parameters parameters = mCamera.getParameters();
if (mPreviewSize != null) {
parameters.setPreviewSize(mPreviewSize.width,
mPreviewSize.height);
}
requestLayout();
mCamera.setParameters(parameters);
mCamera.startPreview();
mPreviewRunning = true;
}
}
public void stop() {
if (mCamera != null) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera = null;
}
}
}
Veuillez noter que dans onLayout
la largeur et la hauteur sont inversés, car l'application est toujours en cours d'exécution dans le portrait.
Je suis, y compris quelques photos pour vous montrer ce que le problème ressemble à:
J'ai débogué le code. La taille de l'aperçu est mis en 1280x720 et la taille de la mise en page est également être correctement réglée pour correspondre à la taille.
J'ai aussi essayé différentes mises en page, mais le résultat était toujours le même...
Vous devez vous connecter pour publier un commentaire.
J'ai eu le même problème, après quelques jours dans ce puzzle, ma classe Java fin sur ce code:
Donc, Le problème qui se passait parce que l'écran de la caméra a une taille (hauteur x largeur) 576x720, et mon écran était 1184x720. Ainsi, l'aperçu de la caméra (ma surface d'affichage de la classe) étirée pour remplir le parent.
Donc, l'approche qui a travaillé pour faire de ce point de vue plus grande que mon écran, et qui vient d'affichage la zone d'affichage de mon écran. Donc, j'ai eu à utiliser cette étrange monture (un parent de mise en page à l'intérieur d'un linearlayout), de sorte que la taille de la relative sera aussi grande que je veux - la surface d'affichage de remplir, et le linéaire prendra juste la partie que je veux afficher.
J'ai essayé de résoudre le même problème... ci-Dessous le code a fonctionné pour moi:
Vous pouvez voir le fil: Redimensionnement de la surface d'affichage pour le ratio d'aspect de changement d'affichage vidéo sous android
Voici une solution
surfaceChanged est juste pour obtenir le meilleur aperçu de la taille
L'image capturée sur imageReview, mais vous avez besoin d'une méthode pour obtenir la rotation de l'image bitmap
vous devez définir imageView scaleType attribut pour étirée question d'image