截取SurfaceView的截图

问题描述 投票:10回答:3

我正在开发一个简单的相机应用我有代码截取整个活动的截图并将其写入Sd卡。问题是Surfaceview返回黑屏。

我想知道如何独立拍摄surfaceview的截图。这是获取整个活动屏幕截图的代码。

    findViewById(R.id.screen).setOnClickListener(new OnClickListener() {
      @Override
     public void onClick(View v) {
     final RelativeLayout layout = (RelativeLayout) findViewById(R.id.RelativeLayout1);
      layout.setVisibility(RelativeLayout.GONE);
       Bitmap bitmap = takeScreenshot();
        Toast.makeText(getApplicationContext(),"Please Wait",         Toast.LENGTH_LONG).show();
       saveBitmap(bitmap);
   }
});

}



      public Bitmap takeScreenshot() {
       View rootView = findViewById(android.R.id.content).getRootView();
       rootView.setDrawingCacheEnabled(true);
       return rootView.getDrawingCache();
    }


           public void saveBitmap(Bitmap bitmap) {
         final MediaPlayer cheer = MediaPlayer.create(PicShot.this, R.raw.shutter);
       cheer.start();
        Random generator = new Random();
      int n = 10000;
       n = generator.nextInt(n);
        String fname = "Image-"+ n +".png";
      final RelativeLayout layout = (RelativeLayout)     findViewById(R.id.RelativeLayout1);
     File imagePath = new File(Environment.getExternalStorageDirectory() + "/" + fname);
     FileOutputStream fos;
      try {
        fos = new FileOutputStream(imagePath);
        bitmap.compress(CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();
        layout.setVisibility(RelativeLayout.VISIBLE);
        Intent share = new Intent(Intent.ACTION_SEND);
        share.setType("image/*");
        Uri uri = Uri.fromFile(imagePath);
        share.putExtra(Intent.EXTRA_STREAM,uri);
        startActivity(Intent.createChooser(share, "Share Image"));
    } catch (FileNotFoundException e) {
        Log.e("GREC", e.getMessage(), e);
    } catch (IOException e) {
        Log.e("GREC", e.getMessage(), e);
    }
}
android camera screenshot surfaceview
3个回答
12
投票

SurfaceView的表面独立于绘制View元素的表面。因此捕获View内容将不包括SurfaceView。

您需要单独捕获SurfaceView内容并执行自己的合成步骤。捕获的最简单方法可能是重新渲染内容,但使用屏幕外位图作为目标而不是表面。如果您使用GLES渲染到屏幕外的pbuffer,则可以在交换缓冲区之前使用glReadPixels()

更新:Grafika's“相机纹理”活动演示了如何使用OpenGL ES处理来自相机的实时视频。 EglSurfaceBase#saveFrame()展示了如何将GLES渲染捕获到位图。

更新:另请参阅this answer,它提供了更多背景知识。


3
投票

只需复制并粘贴代码即可

注意:仅适用于API级别> = 24

private void takePhoto() {

        // Create a bitmap the size of the scene view.
        final Bitmap bitmap = Bitmap.createBitmap(surfaceView.getWidth(), surfaceView.getHeight(),
                Bitmap.Config.ARGB_8888);



        // Create a handler thread to offload the processing of the image.
        final HandlerThread handlerThread = new HandlerThread("PixelCopier");
        handlerThread.start();
        // Make the request to copy.
        PixelCopy.request(holder.videoView, bitmap, (copyResult) -> {
            if (copyResult == PixelCopy.SUCCESS) {
                Log.e(TAG,bitmap.toString());
                String name = String.valueOf(System.currentTimeMillis() + ".jpg");
                imageFile = ScreenshotUtils.store(bitmap,name);

            } else {
                Toast toast = Toast.makeText(getViewActivity(),
                        "Failed to copyPixels: " + copyResult, Toast.LENGTH_LONG);
                toast.show();
            }
            handlerThread.quitSafely();
        }, new Handler(handlerThread.getLooper()));
    }

2
投票

如果您的情况允许,使用TextureView而不是SurfaceView将使这个问题更容易解决。它有一个方法getBitmap()返回Bitmap当前帧的TextureView

© www.soinside.com 2019 - 2024. All rights reserved.