如何通过自定义按钮从已打开的前置摄像头捕获图像

How to capture image by custom button from already opened front camera

我正在开发一个在用户身上显示 3d 模型的增强现实应用程序 face.I 制作了一个 class 它扩展了 ArFragment,我在其中设置了一旦模型 selected.I 制作了一个用于捕获图像的自定义按钮,但我不知道如何使用显示的 3d 模型实现图像本身的捕获并将其存储在 phone 中(最好不要显示自定义按钮图片)。尝试了一些在互联网上找到的用于编程截图的代码,但它只截图了按钮(箭头和圆圈)。这是 activity 的样子:

这是扩展 ArFragment 的 class:

public class CustomArFragment extends ArFragment {
@Override
protected Config getSessionConfiguration(Session session) {
    Config config = new Config(session);
    config.setAugmentedFaceMode(Config.AugmentedFaceMode.MESH3D);

    this.getArSceneView().setupSession(session);

    return config;
}

@Override
protected Set<Session.Feature> getSessionFeatures() {
    return EnumSet.of(Session.Feature.FRONT_CAMERA);
}

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    FrameLayout frameLayout = (FrameLayout) super.onCreateView(inflater, container, savedInstanceState);

    getPlaneDiscoveryController().hide();
    getPlaneDiscoveryController().setInstructionView(null);


    return frameLayout;

}
}

这是我设置 3d 模型的activity:

public class ArActivity extends AppCompatActivity {
int pos;
private int[] images = {R.raw.glasses1, R.raw.glasses3, R.raw.glasses4, R.raw.glasses5,
        R.raw.glasses6, R.raw.glasses7, R.raw.glasses8, R.raw.glasses9, R.raw.glasses10};

private ModelRenderable modelRenderable;
private boolean isAdded = false;

@Override
protected void onCreate(Bundle savedInstanceState) {

    Bundle extras = getIntent().getExtras();
    if (extras != null) {
        pos = extras.getInt("pos");

    }

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_ar);

    CustomArFragment customArFragment = (CustomArFragment) getSupportFragmentManager().findFragmentById(R.id.arFragment);

    ModelRenderable
            .builder().setSource(this, images[pos])
            .build()
            .thenAccept(renderable -> {
                modelRenderable = renderable;
                modelRenderable.setShadowCaster(false);
                modelRenderable.setShadowReceiver(false);
            });

    customArFragment.getArSceneView().setCameraStreamRenderPriority(Renderable.RENDER_PRIORITY_FIRST);
    customArFragment.getArSceneView().getScene().addOnUpdateListener(frameTime -> {

        if (modelRenderable == null)
            return;

        Frame frame = customArFragment.getArSceneView().getArFrame();
        Collection<AugmentedFace> augmentedFaces = frame.getUpdatedTrackables(AugmentedFace.class);

        for (AugmentedFace augmentedFace : augmentedFaces) {

            if (isAdded)
                return;

            AugmentedFaceNode augmentedFaceNode = new AugmentedFaceNode(augmentedFace);
            augmentedFaceNode.setParent(customArFragment.getArSceneView().getScene());
            augmentedFaceNode.setFaceRegionsRenderable(modelRenderable);

            isAdded = true;
        }
    });
}
}

我之前遇到过类似的问题
使用放置的 3d 模型捕获相机图像。

我用 PixelCopy 解决了。
我在下面添加了我的那部分代码。
很抱歉,这不会是您问题的直接答案,但我希望您能得到一些想法

ImageButton btn3 = (ImageButton)findViewById(R.id.camera_btn);
    btn3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            takePhoto();
        }
    }); 

private String generateFilename() {

    //현재시간을 기준으로 파일 이름 생성
    String date =
            new SimpleDateFormat("yyyyMMddHHmmss", java.util.Locale.getDefault()).format(new Date());
    return Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES) + File.separator + "IM/" + date + "_screenshot.jpg";
}

private void saveBitmapToDisk(Bitmap bitmap, String filename) throws IOException {

    //사용자의 갤러리에 IM 디렉토리 생성 및 Bitmap 을 JPEG 형식으로 갤러리에 저장
    File out = new File(filename);
    if (!out.getParentFile().exists()) {
        out.getParentFile().mkdirs();
    }
    try (FileOutputStream outputStream = new FileOutputStream(filename);
         ByteArrayOutputStream outputData = new ByteArrayOutputStream()) {
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputData);
        outputData.writeTo(outputStream);
        outputStream.flush();
        outputStream.close();
    } catch (IOException ex) {
        throw new IOException("Failed to save bitmap to disk", ex);
    }
}

private void takePhoto(){
    //PixelCopy 를 사용하여 카메라 화면과 object 를 bitmap 으로 생성
    final String filename = generateFilename();
    ArSceneView view = arFragment.getArSceneView();

    final Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),view.getHeight(),
            Bitmap.Config.ARGB_8888);

    final HandlerThread handlerThread = new HandlerThread("PixelCopier");
    handlerThread.start();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        PixelCopy.request(view, bitmap, (copyResult) -> {
            if (copyResult == PixelCopy.SUCCESS) {
                try {
                    saveBitmapToDisk(bitmap, filename);

                    //Media Scanning 실시
                    Uri uri = Uri.parse("file://" + filename);
                    Intent i = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                    i.setData(uri);
                    sendBroadcast(i);

                } catch (IOException e) {
                    Toast toast = Toast.makeText(AR_Activity.this, e.toString(),
                            Toast.LENGTH_LONG);
                    toast.show();
                    return;
                }
                Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content),
                        "스크린샷이 저장되었습니다.", Snackbar.LENGTH_LONG);
                snackbar.setAction("갤러리에서 보기", v -> {
                    //어플 내에서 저장한 스크린샷을 확인 가능
                    File photoFile = new File(filename);

                    Uri photoURI = FileProvider.getUriForFile(AR_Activity.this,
                            AR_Activity.this.getPackageName() + ".ar.codelab.name.provider",
                            photoFile);
                    Intent intent = new Intent(Intent.ACTION_VIEW, photoURI);
                    intent.setDataAndType(photoURI, "image/*");
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    startActivity(intent);
                });
                snackbar.show();
            } else {
                Toast toast = Toast.makeText(AR_Activity.this,
                        "스크린샷 저장 실패!: " + copyResult, Toast.LENGTH_LONG);
                toast.show();
            }
            handlerThread.quitSafely();
        }, new Handler(handlerThread.getLooper()));
    }
}