2017-08-16 36 views
0

我开发了一款安卓相机应用程序!我使用camera2来实现相机模块!问题是,当我用它拍摄照片时,图像的大小太高了,大约9MB!所以我的画廊太慢了!这是什么原因?Android:如何提高我的相机性能

我在不同的手机测试它,图像的大小不同,但仍然太高!我试过photo.compress(Bitmap.CompressFormat.JPEG, 50, out);这个代码来缩小尺寸,但是图像的质量对我来说太重要了,所以我不想降低分辨率!这里是我的相机代码:

public class MainActivity extends AppCompatActivity { 

    private Size previewsize; 
    private Size jpegSizes[] = null; 
    private TextureView textureView; 
    private CameraDevice cameraDevice; 
    private CaptureRequest.Builder previewBuilder; 
    private CameraCaptureSession previewSession; 
    private static VirtualFileSystem vfs; 
    ImageButton getpicture; 
    ImageButton btnShow; 
    Button btnSetting; 

    private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); 

    static { 
     ORIENTATIONS.append(Surface.ROTATION_0, 90); 
     ORIENTATIONS.append(Surface.ROTATION_90, 0); 
     ORIENTATIONS.append(Surface.ROTATION_180, 270); 
     ORIENTATIONS.append(Surface.ROTATION_270, 180); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     textureView = (TextureView) findViewById(R.id.textureview); 
     textureView.setSurfaceTextureListener(surfaceTextureListener); 
     getpicture = (ImageButton) findViewById(R.id.getpicture); 
     btnShow = (ImageButton) findViewById(R.id.button2); 
     btnSetting = (Button) findViewById(R.id.btn_setting); 

     btnSetting.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       startActivity(new Intent(MainActivity.this, Setting.class)); 
      } 
     }); 

     btnShow.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       startActivity(new Intent(MainActivity.this, Gallery2.class)); 
      } 
     }); 

     getpicture.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       getPicture(); 
      } 
     }); 

    } 

    void getPicture() { 
     if (cameraDevice == null) { 
      return; 
     } 
     CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
     try { 
      CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId()); 
      if (characteristics != null) { 
       jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG); 
      } 
      int width = 640, height = 480; 
      if (jpegSizes != null && jpegSizes.length > 0) { 
       width = jpegSizes[0].getWidth(); 
       height = jpegSizes[0].getHeight(); 
      } 
      ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1); 
      List<Surface> outputSurfaces = new ArrayList<Surface>(2); 
      outputSurfaces.add(reader.getSurface()); 
      outputSurfaces.add(new Surface(textureView.getSurfaceTexture())); 
      final CaptureRequest.Builder capturebuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 
      capturebuilder.addTarget(reader.getSurface()); 
      capturebuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 
      int rotation = getWindowManager().getDefaultDisplay().getRotation(); 
      capturebuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); 
      ImageReader.OnImageAvailableListener imageAvailableListener = new ImageReader.OnImageAvailableListener() { 
       @Override 
       public void onImageAvailable(ImageReader reader) { 
        Image image = null; 
        try { 
         image = reader.acquireLatestImage(); 
         ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 
         byte[] bytes = new byte[buffer.capacity()]; 
         buffer.get(bytes);      

         Bitmap photo = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, null); 
         ByteArrayOutputStream out = new ByteArrayOutputStream(); 
         photo.compress(Bitmap.CompressFormat.JPEG, 50, out); 
         save(out); 
         photo = Bitmap.createScaledBitmap(photo, 120, 120, false); 
         btnShow.setImageBitmap(photo); 

         save(out); 
        } catch (Exception ee) { 
        } finally { 
         if (image != null) 
          image.close(); 
        } 
       } 

       void save(ByteArrayOutputStream bytes) { 

        File file12 = getOutputMediaFile(); 
        OutputStream outputStream = null; 
        try { 
         outputStream = new FileOutputStream(file12); 
         outputStream.write(bytes.toByteArray()); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } finally { 
         try { 
          if (outputStream != null) 
           outputStream.close(); 
         } catch (Exception e) { 
         } 
        } 
       } 
      }; 
      HandlerThread handlerThread = new HandlerThread("takepicture"); 
      handlerThread.start(); 
      final Handler handler = new Handler(handlerThread.getLooper()); 
      reader.setOnImageAvailableListener(imageAvailableListener, handler); 
      final CameraCaptureSession.CaptureCallback previewSSession = new CameraCaptureSession.CaptureCallback() { 
       @Override 
       public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) { 
        super.onCaptureStarted(session, request, timestamp, frameNumber); 
       } 

       @Override 
       public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { 
        super.onCaptureCompleted(session, request, result); 
        startCamera(); 
       } 
      }; 
      cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { 
       @Override 
       public void onConfigured(CameraCaptureSession session) { 
        try { 
         session.capture(capturebuilder.build(), previewSSession, handler); 
        } catch (Exception e) { 
        } 
       } 

       @Override 
       public void onConfigureFailed(CameraCaptureSession session) { 
       } 
      }, handler); 
     } catch (Exception e) { 
     } 
    } 

    public void openCamera() { 
     CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
     try { 
      String camerId = manager.getCameraIdList()[0]; 
      CameraCharacteristics characteristics = manager.getCameraCharacteristics(camerId); 
      StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 
      previewsize = map.getOutputSizes(SurfaceTexture.class)[0]; 
      if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { 

       return; 
      } 
      manager.openCamera(camerId, stateCallback, null); 
     }catch (Exception e) 
     { 
     } 
    } 
    private TextureView.SurfaceTextureListener surfaceTextureListener=new TextureView.SurfaceTextureListener() { 
     @Override 
     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 
      openCamera(); 
     } 
     @Override 
     public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 
     } 
     @Override 
     public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 
      return false; 
     } 
     @Override 
     public void onSurfaceTextureUpdated(SurfaceTexture surface) { 
     } 
    }; 
    private CameraDevice.StateCallback stateCallback=new CameraDevice.StateCallback() { 
     @Override 
     public void onOpened(CameraDevice camera) { 
      cameraDevice=camera; 
      startCamera(); 
     } 
     @Override 
     public void onDisconnected(CameraDevice camera) { 
     } 
     @Override 
     public void onError(CameraDevice camera, int error) { 
     } 
    }; 
    @Override 
    protected void onPause() { 
     super.onPause(); 
     if(cameraDevice!=null) 
     { 
      cameraDevice.close(); 
     } 
    } 
    void startCamera() 
    { 
     if(cameraDevice==null||!textureView.isAvailable()|| previewsize==null) 
     { 
      return; 
     } 
     SurfaceTexture texture=textureView.getSurfaceTexture(); 
     if(texture==null) 
     { 
      return; 
     } 
     texture.setDefaultBufferSize(previewsize.getWidth(),previewsize.getHeight()); 
     Surface surface=new Surface(texture); 
     try 
     { 
      previewBuilder=cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
     }catch (Exception e) 
     { 
     } 
     previewBuilder.addTarget(surface); 
     try 
     { 
      cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() { 
       @Override 
       public void onConfigured(CameraCaptureSession session) { 
        previewSession=session; 
        getChangedPreview(); 
       } 
       @Override 
       public void onConfigureFailed(CameraCaptureSession session) { 
       } 
      },null); 
     }catch (Exception e) 
     { 
     } 
    } 
    void getChangedPreview() 
    { 
     if(cameraDevice==null) 
     { 
      return; 
     } 
     previewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 
     HandlerThread thread=new HandlerThread("changed Preview"); 
     thread.start(); 
     Handler handler=new Handler(thread.getLooper()); 
     try 
     { 
      previewSession.setRepeatingRequest(previewBuilder.build(), null, handler); 
     }catch (Exception e){} 
    } 
    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.menu, menu); 
     return true; 
    } 
    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 
     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) { 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 
    private File getOutputMediaFile() { 


     String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss") 
       .format(new Date()); 
     File mediaFile; 
File(Environment.getExternalStorageDirectory()+"/MyCamAppCipher1"+"/" + mTime + ".jpg"); 

     mediaFile = new File("/myfiles.db"+"/" + mTime + ".jpg"); 
     return mediaFile; 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 

    } 
} 

回答

0

在这一段代码,你要选择的第一个可用的分辨率,这通常是最高的国家之一。

 int width = 640, height = 480; 
     if (jpegSizes != null && jpegSizes.length > 0) { 
      width = jpegSizes[0].getWidth(); 
      height = jpegSizes[0].getHeight(); 
     } 
从做你在说什么,这是通过调用 photo.compress(Bitmap.CompressFormat.JPEG, 50, out);降低图像质量,您的另一种方法是选择一个更小的摄像头分辨率,通过迭代 jpegSizes阵列和选择较低的分辨率

除了。考虑到要做到这一点,你应该使用相对比较(即width> = minWidth),或者找到中间分辨率,但总是选择在这个数组中可用的分辨率之一。请注意,这个阵列因手机而异(即取决于相机的特性)。

例如,假设您需要至少3M像素(2048x1536)。你可以有以下代码:

int width = Integer.MAX_VALUE, height = Integer.MAX_VALUE; 
for (int i = 0; i < jpegSizes.length; i++) { 
    int currWidth = jpegSizes[0].getWidth(); 
    int currHeight = jpegSizes[0].getHeight(); 
    if ((currWidth < width && currHeight < height) && // smallest resolution 
     (currWidth > 2048 && currHeight > 1536)) { // at least 3M pixels 
     width = currWidth; 
     height = currHeight; 
    } 
} 

注意,有两个条件:

    在第一线
  • ,我们正在寻找可能的最小分辨率(总是比前一个更小;通知也为widthheightInteger.MAX_VALUE的初始值,这意味着,至少所述第一值将总是匹配该条件)在第二行
  • ,我们确保是至少 3M像素

因此,所有组合此代码将选择最小的分辨率可能,至少3M像素。

最后,您可以添加一个备用条件:如果没有匹配的分辨率被找到(即widthheightInteger.MAX_VALUE),选择以你目前做的第一个。

+0

我不明白如何选择一个较小的相机分辨率,你能解释一下吗?!? – Zeinab

+0

基本上,你必须迭代数组(一个普通的for循环),并检查候选者是否符合你的期望。我会用一个例子来更新答案。 –

0

我也使用camera2完成了一个相机应用程序,并且即使使用12或15 Mb图片尺寸(不需要压缩到50%),也可以将图像保存到磁盘中。当你说你的画廊很慢...你是否将全尺寸图片加载到缩略图中?你是否显示全尺寸图像?尝试将小图片加载到缩略图并显示。

+0

我在我的画廊中使用此代码缩略图:BitmapFactory.Options options.inSampleSize = 16; final int THUMBSIZE = 64; 尝试{} {bmp = ThumbnailUtils.extractThumbnail(BitmapFactory。decodeStream(新FileInputStream(file),null,options), THUMBSIZE,THUMBSIZE); } catch(FileNotFoundException e){ e.printStackTrace(); }好吗?!?!! ?? – Zeinab

+0

我在这段代码中看不到任何错误。也许你可以尝试使用更大的inSampleSize。你是在一个线程中做这件事吗? –

+0

是的,我在一个线程中做!但我不保存缩略图,我应该保存它!?! – Zeinab