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