2012-10-05 8 views
5

Sto implementando un'applicazione per fotocamera e quando guardo l'anteprima (specialmente con la fotocamera anteriore), l'immagine è molto grossa. Sembra che l'immagine venga allungata orizzontalmente. Seguo l'esempio sdk con le dimensioni della fotocamera ottimizzata ma non aiuta. Come posso regolare le impostazioni della mia fotocamera in modo che sia in anteprima come l'altra app della fotocamera?L'anteprima della fotocamera Android sembra strana

Grazie.

Il mio codice è di sotto.

public class CameraActivity extends Activity implements SurfaceHolder.Callback, Camera.ShutterCallback, Camera.PictureCallback { 

Camera m_camera; 
SurfaceView m_surfaceView; 
int m_numOfCamera; 
int m_defaultCameraId; 
int m_currentCamera; 
int m_surfaceWidth; 
int m_surfaceHeight; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_camera); 
    getActionBar().setDisplayHomeAsUpEnabled(true); 


    m_surfaceView = (SurfaceView)findViewById(R.id.cameraPreview); 
    m_surfaceView.getHolder().addCallback(this); 

    m_camera = Camera.open(); 

    m_numOfCamera = Camera.getNumberOfCameras(); 

    CameraInfo cameraInfo = new CameraInfo(); 
    for (int i = 0; i < m_numOfCamera; ++i) { 
     Camera.getCameraInfo(i, cameraInfo); 
     if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) { 
      m_defaultCameraId = i; 
      m_currentCamera = m_defaultCameraId; 
     }  
    } 

    if (m_numOfCamera < 1) { 
     MenuItem switchCam = (MenuItem)findViewById(R.id.menu_switch_camera); 
     switchCam.setVisible(false); 
    } 
} 

@Override 
public void onPause() { 
    super.onPause(); 
    m_camera.stopPreview(); 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    m_camera.release(); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.activity_camera, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(final MenuItem item) 
{ 
    if (item.getItemId() == android.R.id.home) 
    { 
     Intent intent = new Intent(this, MainActivity.class); 
     intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
     startActivity(intent); 

     return true; 
    } 
    else if (item.getItemId() == R.id.menu_switch_camera) 
    { 
     if (m_camera != null) { 
      m_camera.stopPreview(); 
      m_camera.release(); 
      m_camera = null; 
     } 

     m_camera = Camera.open((m_currentCamera + 1) % m_numOfCamera); 
     m_currentCamera = (m_currentCamera + 1) % m_numOfCamera; 

     Camera.Parameters params = m_camera.getParameters(); 
     List<Camera.Size> sizes = params.getSupportedPreviewSizes(); 
     Camera.Size size = getOptimalPreviewSize(sizes, m_surfaceWidth, m_surfaceHeight); 

     params.setPreviewSize(size.width, size.height); 

     m_camera.setParameters(params); 
     setCameraDisplayOrientation(this, m_currentCamera, m_camera); 
     m_camera.startPreview(); 
     try { 
      m_camera.setPreviewDisplay(m_surfaceView.getHolder()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return true; 
    } 
    return true; 
} 

public void onPictureTaken(byte[] arg0, Camera arg1) { 
    // TODO Auto-generated method stub 

} 

public void onShutter() { 
    // TODO Auto-generated method stub 

} 

public void surfaceChanged(SurfaceHolder arg0, int format, int w, int h) { 
    m_surfaceWidth = w; 
    m_surfaceHeight = h; 
    Camera.Parameters params = m_camera.getParameters(); 
    List<Camera.Size> sizes = params.getSupportedPreviewSizes(); 
    Camera.Size selected = getOptimalPreviewSize(sizes, w, h); 

    params.setPreviewSize(selected.width, selected.height); 


    m_camera.setParameters(params); 
    setCameraDisplayOrientation(this, m_currentCamera, m_camera); 
    m_camera.startPreview();  
} 

private static void setCameraDisplayOrientation(Activity activity, 
     int cameraId, android.hardware.Camera camera) { 
    android.hardware.Camera.CameraInfo info = 
      new android.hardware.Camera.CameraInfo(); 
    android.hardware.Camera.getCameraInfo(cameraId, info); 
    int rotation = activity.getWindowManager().getDefaultDisplay() 
      .getRotation(); 
    int degrees = 0; 
    switch (rotation) { 
     case Surface.ROTATION_0: degrees = 0; break; 
     case Surface.ROTATION_90: degrees = 90; break; 
     case Surface.ROTATION_180: degrees = 180; break; 
     case Surface.ROTATION_270: degrees = 270; break; 
    } 

    int result; 
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
     result = (info.orientation + degrees) % 360; 
     result = (360 - result) % 360; // compensate the mirror 
    } else { // back-facing 
     result = (info.orientation - degrees + 360) % 360; 
    } 
    camera.setDisplayOrientation(result); 
} 


public void surfaceCreated(SurfaceHolder arg0) { 
    try { 
     m_camera.setPreviewDisplay(m_surfaceView.getHolder()); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

public void surfaceDestroyed(SurfaceHolder arg0) { 
    // TODO Auto-generated method stub 

} 

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; 
} 

} 

risposta

15

L'anteprima della fotocamera riempie sempre lo SurfaceView mostrandolo. Se lo aspect ratio di m_surfaceView non corrisponde allo aspect ratio della fotocamera, l'anteprima verrà allungata.

È necessario creare m_surfaceView corrispondente allo proporzioni. Ciò significa che dovrai crearlo dal codice, non dal file XML di layout.

C'è un progetto di esempio APIDemos che troverete nei progetti di esempio Android. Nel progetto c'è una cosa chiamata CameraPreview. Questo ha una buona dimostrazione per l'impostazione dell'anteprima della telecamera in un SurfaceView. Ha una classe che è extends ViewGroup e aggiunge il SurfaceView come figlio dal codice. Il metodo onMeasure() è stato sovrascritto per determinare l'altezza e la larghezza di SurfaceView, quindi le proporzioni vengono mantenute. Dai un'occhiata al progetto e spero che sarà chiaro.

[Mi dispiace non è stato possibile inserire il collegamento qui - this dovrebbe essere il collegamento, ma l'ho trovato rotto. Ma se hai installato i progetti di esempio con l'SDK di Android, puoi trovare il progetto nei campioni. Apri un nuovo progetto di esempio Android, seleziona APIDemos, quindi cerca una classe denominata CameraPreview. Dovrebbe essere nel pacchetto com.example.android.apis.graphics, per quanto mi ricordo.]

+0

Grazie Un sacco! Ci proverò. –

+2

Com'è possibile che la normale fotocamera di qualsiasi dispositivo abbia un'anteprima a tutto schermo, senza alcun allungamento? – idish

+0

L'ho preso all'interno di sdk/sample/adroid-18. Grazie –

0

Ho modificato il metodo Loutout e non l'anteprima della fotocamera non è allungata. Il resto della cosa è lo stesso di APiDemo che trova qui sdk/sample/adroid-18. L'idea è che abbiamo solo alcune dimensioni supportate dell'anteprima, ma la nostra dimensione di visualizzazione potrebbe non corrispondere sempre alle dimensioni dell'anteprima. quindi ho preso dimensioni di anteprima più grandi quindi la mia dimensione di immagini. per me funziona. Può aiutare qualcuno ..

@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.width; 
       previewHeight = mPreviewSize.height; 
      } 

      // Center the child SurfaceView within the parent. 
      if (width * previewHeight < height * previewWidth) { 

       final int scaledChildWidth = previewWidth * height 
         /previewHeight; 

       left = (width - scaledChildWidth)/2; 
       top = 0; 
       right = (width + scaledChildWidth)/2; 
       bottom = height; 

       child.layout(left, top, right, bottom); 
      } else { 
       final int scaledChildHeight = previewHeight * width 
         /previewWidth; 

       left = 0; 
       top = (height - scaledChildHeight)/2; 
       right = width; 
       bottom = (height + scaledChildHeight)/2; 

       child.layout(left, top, right, bottom); 
      } 
     } 
    } 
+0

cosa potrebbe essere lasciato, a destra, in basso e in alto, dove vengono dichiarati? lo stesso l, r, t, b? – desgraci

+0

è un metodo sottoposto a override, non è necessario passare valori per questo. Prenderà il valore l, r, t, b in base al layout –

0

Ho un problema con l'anteprima della fotocamera troppo allungata. È troppo che si estende in modalità verticale e orizzontale.

Così a manifestare ho aggiunto screenOrentation = "Ritratto", ma non ha aiutato, ancora di anteprima viene ridimensionata in qualsiasi posizione (verticale - anteprima è quello di largo o paesaggio è troppo lungo) è possibile vedere questo a schermi. Vorrei aggiungere a Samsung Ace III è tutto a posto, ma a LG Nexus 4 è estende problema

package pl.probs.camera.component; 

import java.io.IOException; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.List; 
import android.annotation.SuppressLint; 
import android.app.Activity; 
import android.content.Context; 
import android.graphics.Point; 
import android.hardware.Camera; 
import android.hardware.Camera.AutoFocusCallback; 
import android.hardware.Camera.CameraInfo; 
import android.hardware.Camera.Parameters; 
import android.hardware.Camera.Size; 
import android.util.Log; 
import android.view.Display; 
import android.view.MotionEvent; 
import android.view.Surface; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import pl.probs.lib.debug.L; 

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 
    private static final String TAG = "CameraPreview"; 
    private static boolean showLogs = true; 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 
    private Context context; 
    private Parameters resolution; 
    private List<Size> lSuportedPreviewSize; 
    private static int cOrientation = 0; // aktualny kat orientacji 
    private static boolean cOrientationChanged = false; // Stan orientacji 
                 // zostal zmieniony 
                 // wzgledem poprzedniego 
    private Display display; // Rozmiar ekranu 
    private Point displaySize; // Zmienna przechowuje Rozmiar Ekranu 
    private Point optimalPreviewSize; 
public CameraPreview(Context context, Camera camera, int resolution) { 
    super(context); 
    this.optimalPreviewSize = new Point(); 
    this.context = context; 
    this.mCamera = camera; 
    setDisplaySize(this.display); 
    setFocusable(true); 
    setFocusableInTouchMode(true); 
    mHolder = getHolder(); 
    mHolder.addCallback(this); 
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    this.resolution = getMinResolution(resolution); 
    this.optimalPreviewSize = getOptimalPreviewResolution(this.display); 
    Size s = mCamera.getParameters().getPreviewSize(); // Sprawdzenie jaki 
                 // prewiev ustawiony 
} 

public Point getOptimalPreviewSize() { 
    return optimalPreviewSize; 
} 

public void surfaceCreated(SurfaceHolder holder) { 
    try { 
     if (mCamera != null) { 
      mCamera.stopPreview(); 
      mCamera.setPreviewDisplay(holder); 
      Size s = mCamera.getParameters().getPreviewSize(); 
      mCamera.startPreview(); 
     } 
    } catch (IOException e) { 
     L.d("Błąd ustawiania podglÄ…du: " + e.getMessage()); 
    } 
} 

protected void onPause() { 
    // Because the Camera object is a shared resource, it's very 
    // important to release it when the activity is paused. 
    if (mCamera != null) { 
     mCamera.release(); 
     mCamera = null; 
    } 
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    if (mCamera != null) { 
     mCamera.stopPreview(); 
    } 
} 

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
    Camera.Parameters setPrevOrientation = mCamera.getParameters(); 
    if (mHolder.getSurface() == null) 
     return; 

    try { 
     mCamera.stopPreview(); 
     Size sizeBefore = mCamera.getParameters().getPreviewSize(); 
     setPrevOrientation.setRotation(setCameraDisplayOrientation((Activity) context, getCameraId(), mCamera)); 
     // Orientacja Portrait np 640x480 Landscape 480x640 
     this.resolution.setPreviewSize(this.optimalPreviewSize.x, this.optimalPreviewSize.y); 
     mCamera.setParameters(this.resolution); 
     Size sizeAfter = mCamera.getParameters().getPreviewSize(); 
    } catch (RuntimeException e) { 
     L.d("Podgląd nie istnieje"); 
    } 

    try { 
     mCamera.stopPreview(); 
     mCamera.setPreviewDisplay(mHolder); 
     mCamera.startPreview(); 

    } catch (Exception e) { 
     L.d("błąd podgladu: " + e.getMessage()); 
    } 
} 

@SuppressLint("ClickableViewAccessibility") 
public boolean onTouchEvent(MotionEvent event) { 
    if (event.getAction() == MotionEvent.ACTION_DOWN) { 
     mCamera.autoFocus(new AutoFocusCallback() { 

      @Override 
      public void onAutoFocus(boolean success, Camera camera) { 
       // do something 
      } 
     }); 

    } 

    return true; 
} 

private static int setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) { 
    android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); 

    android.hardware.Camera.getCameraInfo(cameraId, info); 
    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 
    int degrees = 0; 
    switch (rotation) { 
    case Surface.ROTATION_0: 
     degrees = 0; 
     break; 
    case Surface.ROTATION_90: 
     degrees = 90; 
     break; 
    case Surface.ROTATION_180: 
     degrees = 180; 
     break; 
    case Surface.ROTATION_270: 
     degrees = 270; 
     break; 
    } 

    cOrientation = degrees; 

    int result; 
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
     result = (info.orientation + degrees) % 360; 
     result = (360 - result) % 360; // compensate the mirror 
    } else { // back-facing 
     result = (info.orientation - degrees + 360) % 360; 
    } 

    camera.setDisplayOrientation(result); 
    return result; 
} 

private int getCameraId() { 
    int cameraId = -1; 
    int numberOfCameras = Camera.getNumberOfCameras(); 
    for (int i = 0; i < numberOfCameras; i++) { 
     CameraInfo info = new CameraInfo(); 
     Camera.getCameraInfo(i, info); 
     if (info.facing == CameraInfo.CAMERA_FACING_BACK) { 
      cameraId = i; 
      break; 
     } 
    } 
    return cameraId; 
} 

private Parameters getMinResolution(int desireResolutionInMpx) { 
    int height[], width[], size; 
    float megapixels; 
    Camera.Parameters p = mCamera.getParameters(); 
    size = p.getSupportedPictureSizes().size(); 
    height = new int[size]; 
    width = new int[size]; 
    for (int i = 0; i < size; i++) { 
     height[i] = p.getSupportedPictureSizes().get(i).height; 
     width[i] = p.getSupportedPictureSizes().get(i).width; 
     megapixels = (float) (((float) height[i] * (float) width[i])/1024000); 
     if (megapixels <= desireResolutionInMpx) { 
      p.setPictureSize(width[i], height[i]); 
      break; 
     } 
    } 
    return p; 
} 

private Point getOptimalPreviewResolution(Display displaySize) { 
    lSuportedPreviewSize = mCamera.getParameters().getSupportedPreviewSizes(); 
    Point optimalPreviewSize = new Point(); 
    int displayWidth = displaySize.getWidth(); // szerokosc ekranu 
    int displayHeight = displaySize.getHeight(); // wysokosc ekranu 
    int cameraHeight; // wspierana wysokosc kamery 
    int cameraWidth; // wspierana szerokosc kamery 

    // Lista przechowywujace SupportedPreviewSize kamery, wszyskie 
    // rozdzielczosci mniejsze od szerokosc i wysokosci ekranu 
    List<Point> lOptimalPoint = new ArrayList<Point>(); 

    // Pomocniczo do listowania zawartosci listy 
    // TODO manta displayHeight cameraHeight brak oraz width brak zgodnosci 
    // (
    System.out.println(lOptimalPoint.toString()); 
    for (int i = 0; i < lSuportedPreviewSize.size(); i++) { 
     Log.i(TAG, "w " + lSuportedPreviewSize.get(i).width + " h " + lSuportedPreviewSize.get(i).height + " \n"); 
    } 

    // Wyszukanie wszystkich wysokosci kamery mniejszej od wysokosci ekranu 
    for (int i = 0; i < lSuportedPreviewSize.size(); i++) { 
     // TODO Uwazaj kamera zapisuje swoj rozmiar dla pozycji landscape 
     // gdzie height = 480 a width = 800 
     cameraHeight = lSuportedPreviewSize.get(i).width; 
     cameraWidth = lSuportedPreviewSize.get(i).height; 
     // Porownaj wysokosc ekranu urzadzenia z wysokosci supportedPreview 
     // dodaj do listy 
     if (displayHeight > cameraHeight) { 
      lOptimalPoint.add(new Point(cameraHeight, cameraWidth)); 
     } 
    } 

    // Sortowanie rosnaco 
    Collections.sort(lOptimalPoint, new ComapreSupportedPreviewByWidth()); 
    // Ostatni element listy optymalny 
    optimalPreviewSize = lOptimalPoint.get(lOptimalPoint.size()-1); 

    // Zwracana rozdzielczosc landscape aparatu np (800x600) 
    return optimalPreviewSize; 
} 

private void setDisplaySize(Display display) { 
    Activity activity = (Activity) this.context; // Pobierz aktywnosc aby 
                // znać rozmiar ekranu 

    this.display = activity.getWindowManager().getDefaultDisplay(); 
} 

class ComapreSupportedPreviewByWidth implements Comparator<Point> { 

    @Override 
    public int compare(Point lhs, Point rhs) { 
     return lhs.x - rhs.x; 
    } 
} 

}

Link to screens and project doing at eclipse

0

ho già risolto. Cosa potrebbe causare problemi con la strana anteprima della fotocamera.

  • barra di stato prende spazi - si può nascondere Hiding the Status Bar

  • Alcuni spazi anche prendere TitleBar - è possibile disattivare questo a manifestare

android: theme = "@ android: style/Theme.NoTitleBar ">

  • Cambiato l'attività orientamento orizzontale "Allucinante il supporto di anteprima della fotocamera che l'orientamento" - è possibile verificare questo a API demo Grafica-> CameraPreview

  • algoritmo che confronta la dimensione della Display.getWidth() Camera.getParameters size(). getSupportedPreviewSizes(); se sono la stessa è una funzione di surfaceChanged cambiamento Parametrs.setPreviewSize (x, y) che hai ricevuto durante la ricerca della lista


public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
    Camera.Parameters setPrevOrientation = mCamera.getParameters(); 
    if (mHolder.getSurface() == null) 
     return; 

    try { 
     mCamera.stopPreview(); 
     Size sizeBefore = mCamera.getParameters().getPreviewSize(); 
     setPrevOrientation.setRotation(setCameraDisplayOrientation(
       (Activity) context, getCameraId(), mCamera)); 
     // Orientacja Portrait np 640x480 Landscape 480x640 
     this.resolution.setPreviewSize(this.optimalPreviewSize.x, 
       this.optimalPreviewSize.y); 
     mCamera.setParameters(this.resolution); 
     Size sizeAfter = mCamera.getParameters().getPreviewSize(); 
    } catch (RuntimeException e) { 

     L.d("Podgląd nie istnieje"); 
    } 

    try { 
     mCamera.stopPreview(); 
     mCamera.setPreviewDisplay(mHolder); 
     mCamera.startPreview(); 

    } catch (Exception e) { 
     L.d("błąd podgladu: " + e.getMessage()); 
    } 
} 

private Point getOptimalPreviewResolution(Display displaySize) { 

     lSuportedPreviewSize = mCamera.getParameters() 
       .getSupportedPreviewSizes(); 
     Point optimalPreviewSize = new Point(); 
     int displayWidth = displaySize.getWidth(); 
     int displayHeight = displaySize.getHeight(); 
     int cameraHeight; 
     int cameraWidth; 

     List<Point> lOptimalPoint = new ArrayList<Point>(); 

     for (int i = 0; i < lSuportedPreviewSize.size(); i++) { 
      cameraHeight = lSuportedPreviewSize.get(i).width; 
      cameraWidth = lSuportedPreviewSize.get(i).height; 
      if (displayHeight >= cameraHeight) { 
       lOptimalPoint.add(new Point(cameraHeight, cameraWidth)); 
      } 
     } 

     // Sort ascending 
     Collections.sort(lOptimalPoint, 
       new ComapreSupportedPreviewByWidth()); 
     // Last element is optimal 
     optimalPreviewSize = lOptimalPoint.get(lOptimalPoint.size() - 1); 

     // Return resolution - camera at landscape mode (800x600) 
     return optimalPreviewSize; 
    } 

class ComapreSupportedPreviewByWidth implements Comparator<Point> { 

    @Override 
    public int compare(Point lhs, Point rhs) { 
     return lhs.x - rhs.x; 
    } 
Problemi correlati