Reputation: 111
Am using the latest cameraX
def camerax_version = "1.0.0-beta11"
I able to take picture and save image to External Storage in a folder using this below code
File photoFile = new File(outputDirectory, "Image_" + System.currentTimeMillis() + ".jpg");
ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build();
imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(getBaseContext()), new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
Uri.fromFile(photoFile);
Toast.makeText(getBaseContext(), "Image Saved" + photoFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
}
@Override
public void onError(@NonNull ImageCaptureException exception) {
Toast.makeText(getBaseContext(), "Error Saving Image" + photoFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
}
});
Now the point is on how to extract the image before saving it to external storage. What I want to achieve is to capture multiple images and save it in buffer and send those images to next Activity and display them in a imageView using list or something.
Now this can be achieved using onImageCapturedCallback
on imageCapture
which gives me a ImageProxy which then have to convert to Byte Array. But this process apples to only small size and single image.
How can I achieve this for higher resolution and multiple images.
Below is the code I used to capture ImageProxy
and set imageCapture to "YUV", Sadly it didn't work at all
imageCapture.takePicture(ContextCompat.getMainExecutor(getBaseContext()), new ImageCapture.OnImageCapturedCallback() {
@Override
public void onCaptureSuccess(@NonNull ImageProxy image) {
super.onCaptureSuccess(image);
@SuppressLint("UnsafeExperimentalUsageError") Image cimage = image.getImage();
Image.Plane[] planes = cimage.getPlanes();
ByteBuffer yBuffer = planes[0].getBuffer();
ByteBuffer uBuffer = planes[1].getBuffer();
ByteBuffer vBuffer = planes[2].getBuffer();
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
byte[] nv21 = new byte[ySize + uSize + vSize];
yBuffer.get(nv21,0,ySize);
vBuffer.get(nv21,ySize,vSize);
uBuffer.get(nv21,ySize + vSize,uSize);
YuvImage yuvImage = new YuvImage(nv21,ImageFormat.NV21,cimage.getWidth(),cimage.getHeight(),null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0,0,yuvImage.getWidth(),yuvImage.getHeight()),100,out);
byte[] imageBytes = out.toByteArray();
Intent intent = new Intent(MainActivity.this,MainActivity2.class);
intent.putExtra("image",imageBytes);
MainActivity.this.startActivity(intent);
}
@Override
public void onError(@NonNull ImageCaptureException exception) {
super.onError(exception);
}
});
Can I add Image to ArrayList
and then sent them over?
Thanks in Advance..
Upvotes: 3
Views: 1644
Reputation: 101
First you need to close the image after capturing inside the takepicture callback image.close() will close the current image . the create ArrayList globaly and add the imageURL in the arraylist . After theat you can send the arraylist to any activity by intent.
imageCapture.takePicture(ContextCompat.getMainExecutor(getBaseContext()), new ImageCapture.OnImageCapturedCallback() {
@Override
public void onCaptureSuccess(@NonNull ImageProxy image) {
super.onCaptureSuccess(image);
@SuppressLint("UnsafeExperimentalUsageError") Image cimage = image.getImage();
Image.Plane[] planes = cimage.getPlanes();
ByteBuffer yBuffer = planes[0].getBuffer();
ByteBuffer uBuffer = planes[1].getBuffer();
ByteBuffer vBuffer = planes[2].getBuffer();
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
byte[] nv21 = new byte[ySize + uSize + vSize];
yBuffer.get(nv21,0,ySize);
vBuffer.get(nv21,ySize,vSize);
uBuffer.get(nv21,ySize + vSize,uSize);
YuvImage yuvImage = new YuvImage(nv21,ImageFormat.NV21,cimage.getWidth(),cimage.getHeight(),null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0,0,yuvImage.getWidth(),yuvImage.getHeight()),100,out);
byte[] imageBytes = out.toByteArray();
Intent intent = new Intent(MainActivity.this,MainActivity2.class);
intent.putExtra("image",imageBytes);
MainActivity.this.startActivity(intent);
image.close();
}
@Override
public void onError(@NonNull ImageCaptureException exception) {
super.onError(exception);
}
});
I think this will help you, any doubts just refer here to my blog post
This is the function for converting the ImageProxy to bitmap
// output of the image capture image proxy to bitmap
public Bitmap imageProxyToBitmap(ImageProxy image) {
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
buffer.rewind();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
byte[] clonedBytes = bytes.clone();
return BitmapFactory.decodeByteArray(clonedBytes, 0, clonedBytes.length);
}
And save the bitmap to your local storage
// used for save the files internal storage , can view in the gallery or internal storage
public String saveTOInternamMemory(Activity activity, Bitmap bitmapImage){
File myPath = getInternalStorageDir(internalStorageDir,imageFormat,Environment.DIRECTORY_PICTURES);
Log.d(TAG, "directory: " + myPath.getAbsolutePath());
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myPath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
Log.d(TAG, "bit exception: Success" );
} catch (Exception e) {
Log.d(TAG, "bit exception: " + e.getMessage());
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG, "io exce: " + e.getMessage());
}
}
Log.d(TAG, "absolute path " + myPath.getAbsolutePath());
return myPath.getAbsolutePath();
}
Upvotes: 0
Reputation: 390
The easiest way that I found was this
preview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bitmap scaledBitmap = null;
ContextWrapper cw = new ContextWrapper(getApplicationContext());
String PATH = Environment.getExternalStorageDirectory() + "/download/";
File file = new File(PATH + "myImage.jpeg");
if (file.exists()) {
myImage.setImageDrawable(Drawable.createFromPath(file.toString()));
}
else {
myImage.setImageDrawable(Drawable.createFromPath(null));
Toast.makeText(nextPage.this, "Not found", Toast.LENGTH_LONG).show();
}
}
});
You can change the path according to your code.
Upvotes: 0
Reputation: 261
What I suggest you is to store in an array list. and then pass an array list to other activities.
What you have to do is create an array list and store uri.tostring in the array list
String newurl=uri.toString
`arraylist.add(newurl)`
This way you can add multiple image URLs in ArrayList and display with the help of the Picasso library. No need to fetch images from the database.
Upvotes: 1
Reputation: 1443
There are two ways that I did for my project. The code is in kotlin language. You can understand it easily.
val image = imageProxy.image
val bitmap = Bitmap.createBitmap(image.width, image.height,
Bitmap.Config.ARGB_8888)
If it didn't work you can use a YuvtoRgbConvertor I have the full kotlin code if you want or you can write your own. then you can convert the bitmap like this.
val convertor = YuvToRgbConvertor
convertor.yuvToRgb(image , bitmap)
That is what I have done for my project.
Upvotes: 2