I'm using the Mobile vision api's face tracking example and i'm trying to take picture with tapping on the screen. Firstly i wanted to take any picture on the screen with button and i tryed this code but it failed. I look at the barcode reader example and there is tap method but i couldn't succeed. What approach that i should use this case?
pure FaceTracking github code
private void takeImage() {
camera.takePicture(null, null, new PictureCallback() {
private File imageFile;
#Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
// convert byte array into bitmap
Bitmap loadedImage = null;
Bitmap rotatedBitmap = null;
loadedImage = BitmapFactory.decodeByteArray(data, 0,
data.length);
// rotate Image
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(rotation);
rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0,
loadedImage.getWidth(), loadedImage.getHeight(),
rotateMatrix, false);
String state = Environment.getExternalStorageState();
File folder = null;
if (state.contains(Environment.MEDIA_MOUNTED)) {
folder = new File(Environment
.getExternalStorageDirectory() + "/Demo");
} else {
folder = new File(Environment
.getExternalStorageDirectory() + "/Demo");
}
boolean success = true;
if (!folder.exists()) {
success = folder.mkdirs();
}
if (success) {
java.util.Date date = new java.util.Date();
imageFile = new File(folder.getAbsolutePath()
+ File.separator
+ new Timestamp(date.getTime()).toString()
+ "Image.jpg");
imageFile.createNewFile();
} else {
Toast.makeText(getBaseContext(), "Image Not saved",
Toast.LENGTH_SHORT).show();
return;
}
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
// save image into gallery
rotatedBitmap.compress(CompressFormat.JPEG, 100, ostream);
FileOutputStream fout = new FileOutputStream(imageFile);
fout.write(ostream.toByteArray());
fout.close();
ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN,
System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.DATA,
imageFile.getAbsolutePath());
CameraDemoActivity.this.getContentResolver().insert(
Images.Media.EXTERNAL_CONTENT_URI, values);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
#Override
public void onClick(View v) {
case R.id.captureImage:
takeImage();
break;
default:
break;
}
}
I solved the problem.
findViewById(R.id.capture).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCameraSource.takePicture(null, new CameraSource.PictureCallback() {
private File imageFile;
#Override
public void onPictureTaken(byte[] bytes) {
try {
// convert byte array into bitmap
Bitmap loadedImage = null;
Bitmap rotatedBitmap = null;
loadedImage = BitmapFactory.decodeByteArray(bytes, 0,
bytes.length);
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(rotation);
rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0,
loadedImage.getWidth(), loadedImage.getHeight(),
rotateMatrix, false);
dir = new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyPhotos");
boolean success = true;
if (!dir.exists())
{
success = dir.mkdirs();
}
if (success) {
java.util.Date date = new java.util.Date();
imageFile = new File(dir.getAbsolutePath()
+ File.separator
+ new Timestamp(date.getTime()).toString()
+ "Image.jpg");
imageFile.createNewFile();
} else {
Toast.makeText(getBaseContext(), "Image Not saved",
Toast.LENGTH_SHORT).show();
return;
}
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
// save image into gallery
rotatedBitmap.compress(CompressFormat.JPEG, 100, ostream);
FileOutputStream fout = new FileOutputStream(imageFile);
fout.write(ostream.toByteArray());
fout.close();
ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN,
System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.DATA,
imageFile.getAbsolutePath());
FaceTrackerActivity.this.getContentResolver().insert(
Images.Media.EXTERNAL_CONTENT_URI, values);
//saveToInternalStorage(loadedImage);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
});
Less lines of code
#Override
public void onPictureTaken(byte[] bytes) {
Log.d(TAG, "onPictureTaken - jpeg");
capturePic(bytes);
}
private void capturePic(byte[] bytes) {
try {
String mainpath = getExternalStorageDirectory() + separator + "MaskIt" + separator + "images" + separator;
File basePath = new File(mainpath);
if (!basePath.exists())
Log.d("CAPTURE_BASE_PATH", basePath.mkdirs() ? "Success": "Failed");
File captureFile = new File(mainpath + "photo_" + getPhotoTime() + ".jpg");
if (!captureFile.exists())
Log.d("CAPTURE_FILE_PATH", captureFile.createNewFile() ? "Success": "Failed");
FileOutputStream stream = new FileOutputStream(captureFile);
stream.write(bytes);
stream.flush();
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private String getPhotoTime(){
SimpleDateFormat sdf=new SimpleDateFormat("ddMMyy_hhmmss");
return sdf.format(new Date());
}
Related
So, I am creating a QRCode generator application in which user can generate QR code from the data they have entered.I can successfully generate the QR code and show it to the imageview on a Button click but I am facing issue when I tried to save that QR code to my phone's storage (or gallery).
On this button click, QRGenerator function will be called and It will generate the QR code from the Edittext data.
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
QRGenerator();
}
});
Here is the QRGenerator() funcion :
private void QRGenerator() {
String data = text.getText().toString();
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
try {
BitMatrix bitMatrix = multiFormatWriter.encode(data, BarcodeFormat.QR_CODE, 300, 300);
BarcodeEncoder barcodeEncoder = new BarcodeEncoder();
Bitmap bitmap = barcodeEncoder.createBitmap(bitMatrix);
imgView.setImageBitmap(bitmap);
bitmap2 = ((BitmapDrawable)imgView.getDrawable()).getBitmap();
saveImg.setVisibility(View.VISIBLE);
} catch (WriterException e) {
e.printStackTrace();
}
}
and from here I can call the save image function :
saveImg.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
saveImageFunction(bitmap2);
}
});
and here my issue arise, I have put a Toast to notify when my image will saved to gallery but it never pops up
Here is the saveImageFunction :
private void saveImageFunction(Bitmap bitmap) {
String savedImagePath = null;
String imageFileName = "JPEG_" + "test" + ".jpg";
File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+ "/Demo");
boolean success = true;
if(!storageDir.exists()){
success = storageDir.mkdirs();
}
if(success){
File imageFile = new File(storageDir, imageFileName);
savedImagePath = imageFile.getAbsolutePath();
try {
OutputStream fOut = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
addToGallery(savedImagePath);
Toast.makeText(MainActivity.this,"Saved to Gallery!",Toast.LENGTH_SHORT).show();
}
}
and to put that saved image to gallery I have used this function :
addToGallery() :
private void addToGallery(String imagePath){
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(imagePath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
sendBroadcast(mediaScanIntent);
}
As per Gk Mohammad Emon says, I tried adding Toast as well as Log.d in my catch method of SaveImage function but nothing pops up neither on Screen nor in LogCat (Please address any type of mistake if there) :
private void saveImageFunction(Bitmap bitmap) {
String savedImagePath = null;
String imageFileName = "JPEG_" + "test" + ".jpg";
File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+ "/Demo");
boolean success = true;
if(!storageDir.exists()){
success = storageDir.mkdirs();
}
if(success){
File imageFile = new File(storageDir, imageFileName);
savedImagePath = imageFile.getAbsolutePath();
try {
OutputStream fOut = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
Toast.makeText(MainActivity.this,"Image Saved!", Toast.LENGTH_SHORT).show();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(MainActivity.this,"hello There",Toast.LENGTH_SHORT).show();
Log.d("Exception e",e.toString());
}
addToGallery(savedImagePath);
Toast.makeText(MainActivity.this,"Saved to Gallery!",Toast.LENGTH_SHORT).show();
}
}
After hours of searching, i'm finally able to save screenshot of ArFragment.
but the problem is it only saves the current image of the camera except the 3D object which is placed.
how can i get the full screenshot (current image of the camera + 3D object which is placed)?
the codes that i used is below here.
ImageButton btn3 = (ImageButton)findViewById(R.id.camera_btn);
btn3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onSceneUpdate((FrameTime) frameTime);
Toast.makeText(AR_Activity.this, "스크린샷이 저장되었습니다.", Toast.LENGTH_SHORT).show();
}
});
private void onSceneUpdate(FrameTime frameTime) {
try {
Date now = new Date();
android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);
String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";
Frame currentFrame = arFragment.getArSceneView().getArFrame();
Image currentImage = currentFrame.acquireCameraImage();
int imageFormat = currentImage.getFormat();
if (imageFormat == ImageFormat.YUV_420_888) {
Log.d("ImageFormat", "Image format is YUV_420_888");
}
WriteImageInformation((Image) currentImage, (String) mPath);
} catch (Exception e) {
}
}
private static byte[] NV21toJPEG(byte[] nv21, int width, int height) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
YuvImage yuv = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
yuv.compressToJpeg(new Rect(0, 0, width, height), 100, out);
return out.toByteArray();
}
public static void WriteImageInformation(Image image, String path) {
byte[] data = null;
data = NV21toJPEG(YUV_420_888toNV21(image),
image.getWidth(), image.getHeight());
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(path));
bos.write(data);
bos.flush();
bos.close();
} catch (Throwable e) {
e.printStackTrace();
}
}
private static byte[] YUV_420_888toNV21(Image image) {
byte[] nv21;
ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();
ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
nv21 = new byte[ySize + uSize + vSize];
//U and V are swapped
yBuffer.get(nv21, 0, ySize);
vBuffer.get(nv21, ySize, vSize);
uBuffer.get(nv21, ySize + vSize, uSize);
return nv21;
}
Use PixelCopy. it worked perfectly.
For those who might wonder,
I will add my code below.
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()));
}
}
I am trying to save a picture taken from an Android camera and I get the following error
Throwing OutOfMemoryError "Failed to allocate a 51916812 byte allocation with 12763771 free bytes and 12MB until OOM"
I want to store it with the best image quality.
Is it possible?
Below is the source code
private class SaveImageTask extends AsyncTask<byte[], Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(byte[]... data) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeByteArray(data[0], 0, data[0].length, options);
Log.i("sinwhod","matrix = " + orientation);
Matrix matrix = new Matrix();
//matrix.postRotate(orientation);
matrix.setRotate(orientation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] currentData = stream.toByteArray();
Date day = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault());
fileName = String.valueOf(sdf.format(day));
savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
temp = savePath + "/" + fileName + ".jpg";
File file = new File(temp);
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(currentData);
fos.flush();
fos.close();
} catch (Exception e) {
Log.i("sinwhod", "error = " + e);
}
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + temp)));
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Toast.makeText(MainActivity.this, temp, Toast.LENGTH_SHORT).show();
}
}
'''
I have the following code:
YuvImage yuv = new YuvImage(result.getExtractImageData(),
camera.getParameters().getPreviewFormat(),
result.getWidth(),
result.getHeight(), null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
yuv.compressToJpeg(new Rect(0, 0, result.getWidth(), result.getHeight()), 100, out);
byte[] bytes = out.toByteArray();
Bitmap image = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
image = RotateImage(image, rotation);
createDirectoryAndSaveFile(image, "Image_" + result.getCaptureTime() + ".jpg");
String filePath = Environment.getExternalStorageDirectory() + "/MyFolder/Image_" + result.getCaptureTime() + ".jpg";
try {
ExifInterface exif = new ExifInterface(filePath);
exif.getAttribute("UserComment");
// call this next setAttributes a few times to write all the GPS data to it.
exif.setAttribute("UserComment", String.valueOf(result.getCaptureTime()));
exif.saveAttributes();
}
catch (IOException e) {
e.printStackTrace();
}
It is supposed to punt under UserComment the result.getCaptureTime() at which it was captured from the camera. I download it to a Windows folder and I can't see the properties I just created...
What I'm doing wrong?
EDIT:
private void createDirectoryAndSaveFile(Bitmap imageToSave, String fileName)
{
File direct = new File(Environment.getExternalStorageDirectory() + "/MyFolder");
if (!direct.exists()) {
File wallpaperDirectory = new File("/sdcard/MyFolder/");
wallpaperDirectory.mkdirs();
}
File file = new File(new File("/sdcard/MyFolder/"), fileName);
if (file.exists()) {
file.delete();
}
try {
FileOutputStream out = new FileOutputStream(file);
imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
I inserted on my App a option to take a photo and save it on a directory.
But when I check the taken photo it appears turned. The horizontal photos appears vertical, and the vertical photos appears horizontal.
how can change my code and automatically rotate the photos?
My code:
if (options[item].equals("Take Photo"))
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(android.os.Environment.getExternalStorageDirectory(), "temp.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
startActivityForResult(intent, 1);
}
...
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
File f = new File(Environment.getExternalStorageDirectory().toString());
for (File temp : f.listFiles()) {
if (temp.getName().equals("temp.jpg")) {
f = temp;
break;
}
}
try {
Bitmap bitmap;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(),
bitmapOptions);
int nh = (int) ( bitmap.getHeight() * (612.0 / bitmap.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(bitmap, 612, nh, true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
scaled.compress(Bitmap.CompressFormat.JPEG, 90, stream);
byte [] byte_arr = stream.toByteArray();
String image_str = Base64.encodeBytes(byte_arr);
viewImage.setScaleType(ScaleType.CENTER);
viewImage.setImageBitmap(scaled);
task = new getinfo();
task.execute(image_str);
String path = android.os.Environment
.getExternalStorageDirectory()
+ File.separator
+ "Phoenix" + File.separator + "default";
f.delete();
OutputStream outFile = null;
File file = new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg");
try {
outFile = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, outFile);
outFile.flush();
outFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
This piece helped me to do the same task
private Bitmap rotateImage(String pathToImage) {
// 1. figure out the amount of degrees
int rotation = getImageRotation();
// 2. rotate matrix by postconcatination
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
// 3. create Bitmap from rotated matrix
Bitmap sourceBitmap = BitmapFactory.decodeFile(pathToImage);
return Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), matrix, true);
}
Also check this,this and this for more details.