2016-03-07 17 views
1

我想用不同的曝光时间得到多张照片来执行我的HDR algorithm。不过,我不知道如何使用Android camera2 APIImageReader中的captureBurst()保存文件。 我的代码会创建重复的文件。任何人都可以帮我一把吗?安卓相机2连拍和图像朗读器

private ImageReader mImageReader; 
    private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = 
      new ImageReader.OnImageAvailableListener() { 

       @Override 
       public void onImageAvailable(ImageReader reader) { 
        mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage())); 
       } 
      }; 

private static class ImageSaver implements Runnable { 
     private final Image mImage; 

     private ImageSaver(Image image) { 
      mImage = image; 

     } 

     private File createNewImageFile() throws IOException { 
      String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
      String imageFileName = "IMG_" + timeStamp; 
      File storageDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM + "/Camera"); 
      File image = File.createTempFile(imageFileName, ".jpg", storageDirectory); 
      return image; 
     } 

     @Override 
     public void run() { 
      ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer(); 
      byte[] bytes = new byte[byteBuffer.remaining()]; 
      byteBuffer.get(bytes); 

      FileOutputStream fileOutputStream = null; 

      try { 
       File newFile = null; 
       try { 
        newFile = createNewImageFile(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 

       fileOutputStream = new FileOutputStream(newFile); 
       fileOutputStream.write(bytes); 

       mImageFileNameList.add(newFile.getName()); 

      } catch (IOException e) { 
       e.printStackTrace(); 
      } finally { 
       mImage.close(); 
       if (fileOutputStream != null) { 
        try { 
         fileOutputStream.close(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
     } 
    } 

private void captureStillImage() { 
     try { 
      CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 
      captureStillBuilder.addTarget(mImageReader.getSurface()); 

      CaptureRequest.Builder captureStillBuilder2 = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 
      captureStillBuilder2.addTarget(mImageReader.getSurface()); 

      int rotation = getWindowManager().getDefaultDisplay().getRotation(); 

      captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION, 
        ORIENTATIONS.get(rotation)); 
      captureStillBuilder2.set(CaptureRequest.JPEG_ORIENTATION, 
        ORIENTATIONS.get(rotation)); 

      CameraCaptureSession.CaptureCallback captureCallback = 
        new CameraCaptureSession.CaptureCallback() { 

         @Override 
         public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { 
          super.onCaptureCompleted(session, request, result); 
          unlockFocus(); 
         } 
        }; 

      List<CaptureRequest> list = new ArrayList<>(); 

      captureStillBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF); 
      captureStillBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF); 
      captureStillBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, ONE_SECOND/100); 

      captureStillBuilder2.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF); 
      captureStillBuilder2.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF); 
      captureStillBuilder2.set(CaptureRequest.SENSOR_EXPOSURE_TIME, ONE_SECOND/20); 

      list.add(captureStillBuilder.build()); 
      list.add(captureStillBuilder2.build()); 

      mCameraCaptureSession.captureBurst(list, captureCallback, null); 

     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 
+0

看看CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,而不是CaptureRequest.SENSOR_EXPOSURE_TIME –

+0

谢谢,我会看看这个。 – Roderick

回答

0

下面是一个类似的场景,在这里我节省了外部的图片文件夹下创建名为C2的文件夹在我的文件,我的代码:

@Override 
public void onImageAvailable(ImageReader reader) { 
    String currentDateTime = generateTimestamp(); 

    File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() 
      + "/C2/" + mCount++ + "_" + currentDateTime + ".jpg"); 
    if (mCount == 3) mCount = 1; // Reset the counter 
    mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), file)); 
} 

和mCount设置为

private int mCount = 1; 

而generateTimestamp来自Google的示例代码:

/** 
* Generate a string containing a formatted timestamp with the current date and time. 
* 
* @return a {@link String} representing a time. 
*/ 
private static String generateTimestamp() { 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS", Locale.US); 
    return sdf.format(new Date()); 
} 
1

如果一切似乎工作,否则,你的问题只是文件名重复,这可能是因为你的手机可以捕捉两个JPEG比1秒快。

您的格式字符串图像文件名是:“YYYYMMDD_HHMMSS” 这不包括任何小数秒,所以在拍摄的照片,说 12:35:15.100和12:35:15.700(600毫秒间隔)将映射到相同的文件名, IMG _..._ 123515.jpg。

你可以只添加“_SSS”你的字符串,包括毫秒为好,每SimpleDateFormat文档,这应该消除歧义您的文件名,除非他们被抓获真的快。

或者,您可以为同名文件保留某种计数器,并在发生冲突时追加_1,_2等。