How Can I Capture Multiple Images and send the images to next Activity and display them using CameraX [Android Studio]

huangapple go评论73阅读模式
英文:

How Can I Capture Multiple Images and send the images to next Activity and display them using CameraX [Android Studio]

问题

使用最新的cameraX版本

    def camerax_version = "1.0.0-beta11"

我能够拍照并将图像保存到外部存储器中的文件夹使用以下代码

    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(), "已保存图像" + photoFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
                    }
    
                    @Override
                    public void onError(@NonNull ImageCaptureException exception) {
                        Toast.makeText(getBaseContext(), "保存图像时出错" + photoFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
                    }
                });

现在的重点是在将图像保存到外部存储之前如何提取图像我想要实现的目标是捕获多个图像将其保存在缓冲区中并将这些图像发送到下一个Activity并使用列表或其他方式在imageView中显示它们

可以使用`imageCapture`上的`onImageCapturedCallback`来实现这一点它会给我一个ImageProxy然后必须将其转换为字节数组但是这个过程仅适用于小尺寸和单个图像
**如何在更高分辨率和多个图像上实现这一点呢**

以下是我用来捕获`ImageProxy`并将imageCapture设置为"YUV"的代码可惜它根本不起作用

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

我能将图像添加到`ArrayList`中然后发送它们吗

提前感谢
英文:

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..

答案1

得分: 2

这是我为项目所做的两种方式。代码使用的是 Kotlin 语言。
你可以轻松理解它。

val image = imageProxy.image
val bitmap = Bitmap.createBitmap(image.width, image.height, 
Bitmap.Config.ARGB_8888)

如果这种方式不起作用,你可以使用一个 YuvtoRgbConvertor。我有完整的 Kotlin 代码,如果你需要的话,或者你也可以自己编写。然后你可以像这样转换位图。

val convertor = YuvToRgbConvertor
convertor.yuvToRgb(image, bitmap)

这就是我为项目所做的内容。

英文:

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.

答案2

得分: 1

我建议你的做法是将其存储在一个数组列表中,然后将一个数组列表传递给其他活动。

你需要做的是创建一个数组列表,并将 uri.tostring 存储在数组列表中。

String newurl = uri.toString();
arraylist.add(newurl);

这样你可以在 ArrayList 中添加多个图像 URL,并借助 Picasso 库进行显示。无需从数据库获取图像。

英文:

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.

答案3

得分: 0

我发现的最简单的方法是这样的

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

您可以根据您的代码更改路径
英文:

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.

答案4

得分: 0

首先,在拍摄后需要在takepicture回调内关闭图像,使用image.close()来关闭当前图像。创建一个全局的ArrayList<String>,并将图像的URL添加到该数组中。然后,你可以通过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);
    }
});

以下是将ImageProxy转换为位图的函数:

// 将图像代理转换为位图
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);
}

并且将位图保存到本地存储:

// 用于将文件保存到内部存储,可以在图库或内部存储中查看
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);
        // 使用位图对象的compress方法将图像写入输出流
        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();
}
英文:

First you need to close the image after capturing inside the takepicture callback image.close() will close the current image . the create ArrayList<String> 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(&quot;UnsafeExperimentalUsageError&quot;) 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(&quot;image&quot;,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, &quot;directory: &quot; + 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, &quot;bit exception: Success&quot; );
} catch (Exception e) {
Log.d(TAG, &quot;bit exception: &quot; + e.getMessage());
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG, &quot;io exce: &quot; + e.getMessage());
}
}
Log.d(TAG, &quot;absolute path &quot; + myPath.getAbsolutePath());
return myPath.getAbsolutePath();
}

huangapple
  • 本文由 发表于 2020年10月20日 13:54:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/64439247.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定