2017-09-03 4 views
0

J'ai essayé un code simple d'Android Dev. (https://developer.android.com/guide/topics/media/camera.html) qui affiche un aperçu de la caméra. Cependant, lorsque je lance l'application sur mon téléphone, la résolution est faible (floue). Ma question est comment augmenter la résolution?Comment augmenter la résolution dans l'aperçu de la caméra?

Le code que j'utilise est écrit ci-dessous

public class CameraApp extends AppCompatActivity { 
    Button captureButton; 

    private static final String TAG = CameraApp.class.getSimpleName(); 

    private Camera mCamera; 
    private CameraPreview mPreview; 


    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_camera_app); 

    // Create an instance of Camera 
    mCamera = getCameraInstance(); 

    // Create our Preview view and set it as the content of our activity. 
    mPreview = new CameraPreview(this, mCamera); 
    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); 
    preview.addView(mPreview); 
    //previewHolder = 

    // Add a listener to the Capture button 
    Button captureButton = (Button) findViewById(R.id.button_capture); 
    captureButton.setOnClickListener(
      new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        // get an image from the camera 
        mCamera = getCameraInstance(); 
        if (mCamera != null) 
         mCamera.takePicture(null, null, mPicture); 
       } 
      } 
    ); 
} 

private Camera.PictureCallback mPicture = new Camera.PictureCallback() { 

    @Override 
    public void onPictureTaken(byte[] data, Camera camera) { 
     Intent saveImageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
     File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); 
     Uri savedImage = Uri.fromFile(pictureFile); 
     saveImageIntent.putExtra(MediaStore.EXTRA_OUTPUT, savedImage); 
     if (pictureFile == null) { 
      Log.d(TAG, "Error creating media file, check storage permissions: "); 
      return; 
     } 

     try { 
      FileOutputStream fos = new FileOutputStream(pictureFile); 
      fos.write(data); 
      fos.close(); 
     } catch (FileNotFoundException e) { 
      Log.d(TAG, "File not found: " + e.getMessage()); 
     } catch (IOException e) { 
      Log.d(TAG, "Error accessing file: " + e.getMessage()); 
     } 
     camera.startPreview(); 
    } 
}; 


/** 
* Check if this device has a camera 
*/ 
/* 
private boolean checkCameraHardware(Context context) { 
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) { 
     // this device has a camera 
     return true; 
    } else { 
     // no camera on this device 
     return false; 
    } 
}*/ 

/** 
* A safe way to get an instance of the Camera object. 
*/ 
public static Camera getCameraInstance() { 
    Camera c = null; 
    try { 
     c = Camera.open(); // attempt to get a Camera instance 
    } catch (Exception e) { 
     // Camera is not available (in use or does not exist) 
    } 
    return c; // returns null if camera is unavailable 
} 

/** 
* A basic Camera preview class 
*/ 
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 

    public CameraPreview(Context context, Camera camera) { 
     super(context); 
     mCamera = camera; 

     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed. 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     // deprecated setting, but required on Android versions prior to 3.0 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     // The Surface has been created, now tell the camera where to draw the preview. 
     try { 
      if (mCamera != null) { 
       mCamera.setPreviewDisplay(holder); 
       mCamera.startPreview(); 
      } 
     } catch (IOException e) { 
      Log.d(TAG, "Error setting camera preview: " + e.getMessage()); 
     } 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     // empty. Take care of releasing the Camera preview in your activity. 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
     // If your preview can change or rotate, take care of those events here. 
     // Make sure to stop the preview before resizing or reformatting it. 
     //holder.getSurface().release(); 



     if (mHolder.getSurface() == null) { 
      // preview surface does not exist 
      return; 
     } 

     // stop preview before making changes 
     try { 
      mCamera.stopPreview(); 
     } catch (Exception e) { 
      // ignore: tried to stop a non-existent preview 
     } 

     // set preview size and make any resize, rotate or 
     // reformatting changes here 

     // start preview with new settings 
     try { 
      mCamera.setPreviewDisplay(mHolder); 
      mCamera.startPreview(); 

     } catch (Exception e) { 
      Log.d(TAG, "Error starting camera preview: " + e.getMessage()); 
     } 
    } 
} 

public static final int MEDIA_TYPE_IMAGE = 1; 
public static final int MEDIA_TYPE_VIDEO = 2; 

/** 
* Create a file Uri for saving an image or video 
*/ 
private static Uri getOutputMediaFileUri(int type) { 
    return Uri.fromFile(getOutputMediaFile(type)); 
} 

/** 
* Create a File for saving an image or video 
*/ 
private static File getOutputMediaFile(int type) { 
    // To be safe, you should check that the SDCard is mounted 
    // using Environment.getExternalStorageState() before doing this. 

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
      Environment.DIRECTORY_PICTURES), "MyCameraApp"); 
    // This location works best if you want the created images to be shared 
    // between applications and persist after your app has been uninstalled. 

    // Create the storage directory if it does not exist 
    if (!mediaStorageDir.exists()) { 
     if (!mediaStorageDir.mkdirs()) { 
      Log.d("MyCameraApp", "failed to create directory"); 
      return null; 
     } 
     mediaStorageDir.mkdirs(); 
    } 

    // Create a media file name 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
    File mediaFile; 
    if (type == MEDIA_TYPE_IMAGE) { 
     mediaFile = new File(mediaStorageDir.getPath() + File.separator + 
       "IMG_" + timeStamp + ".jpg"); 
    } else if (type == MEDIA_TYPE_VIDEO) { 
     mediaFile = new File(mediaStorageDir.getPath() + File.separator + 
       "VID_" + timeStamp + ".mp4"); 
    } else { 
     return null; 
    } 
    return mediaFile; 
    } 
} 

Répondre

0

S'il vous plaît suivre Picture distorted with Camera and getOptimalPreviewSize, qui explique comment vous devez choisir la taille de l'aperçu soutenu qui est le mieux pour votre écran (et mise en page). J'ai donné plus d'explications here.

Ici, je coller pour les générations futures le meilleur implementation je jamais trouvé, bravo à Shaked Klein Orbach:

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

Notez que vous utilisez dépréciéeAPI hardware.Camera. Si votre code ne cible pas principalement les périphériques plus anciens (pré-Lollipop), envisagez de passer à la nouvelle API camera2. Il peut produire de meilleures images, et sa performance est meilleure. Mais les principes de base du choix de la résolution d'aperçu optimale restent les mêmes.

+0

Bonjour @AlexCohn, j'ai essayé le code mais malheureusement la résolution est encore faible (floue). Avez-vous une autre idée? ... Merci – user8447949

+0

Je crains que vous ne deviez divulguer plus de détails si vous avez besoin d'aide pour cela. Au moins: quel est votre périphérique, quelle est la taille de la frame 'camera_preview', quelle résolution a été choisie. –

+0

Appareil: Sony C5303 (Android 4.3, API 18) | Taille du cadre: à la fois W. et H. sont fill_parent | Si vous voulez dire par résolution la sortie de getBestPreviewSize() alors il est 480 * 320 – user8447949