Как сделать снимок по пользовательской кнопке с уже открытой фронтальной камеры - PullRequest
1 голос
/ 05 мая 2020

Я работаю над приложением дополненной реальности, которое отображает 3D-модели на лице пользователя. Я создал класс, расширяющий ArFragment, в котором я установил переднюю камеру, которая будет открываться после выбора модели. Я сделал настраиваемую кнопку для захвата изображения. изображение, но я не знаю, как реализовать захват самого изображения с отображаемой 3D-моделью и сохранить его в телефоне (желательно без кнопок, сделанных на заказ, показанных на рисунке). Пробовал код, найденный на inte rnet для программный снимок экрана, но при этом снимаются только кнопки (стрелка и кружок). Вот как выглядит действие:

enter image description here Вот класс, расширяющий ArFragment:

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-модель:

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

1 Ответ

2 голосов
/ 06 мая 2020

У меня раньше была подобная проблема.
Захват изображения камеры с размещенными 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()));
    }
}
...