UPDATED with more code
I am trying to grab a picture that was just taken and set it to an ImageView
programmatically.
The picture button is pressed,
picture_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
takePhoto(mTextureView);
}
});
it runs the takePhoto method:
public void takePhoto(View view) {
try {
mImageFile = createImageFile();
final ImageView latest_picture = (ImageView) findViewById(R.id.latest_picture);
final RelativeLayout latest_picture_container = (RelativeLayout) findViewById(R.id.latest_picture_container);
final String mImageFileLocationNew = mImageFileLocation.replaceFirst("^/", "");
Toast.makeText(getApplicationContext(), "" + mImageFile, Toast.LENGTH_SHORT).show();
Uri uri = Uri.fromFile(mImageFile);
Toast.makeText(getApplicationContext(), ""+uri, Toast.LENGTH_LONG).show();
latest_picture.setImageURI(uri);
latest_picture_container.setVisibility(View.VISIBLE);
} catch (IOException e){
e.printStackTrace();
}
lockFocus();
captureStillImage();
}
which runs createImageFile()
and captureStillImage()
private void captureStillImage() {
try {
CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureStillBuilder.addTarget(mImageReader.getSurface());
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
//Toast.makeText(getApplicationContext(), "Image Taken", Toast.LENGTH_SHORT).show();
unLockFocus();
}
};
mCameraCaptureSession.capture(captureStillBuilder.build(), captureCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
File createImageFile() throws IOException {
String timestamp = new SimpleDateFormat("yyyyMMdd").format(new Date());
String subFolder = "";
if(pref_session_unique_gallery.equals("yes")){
if(event_name != null){
subFolder = event_name;
} else {
subFolder = timestamp;
}
} else {
subFolder = "_GEN";
}
if(event_name == null){
event_name = "";
} else {
event_name = event_name + "_";
}
String imageFileName = "CPB_"+event_name+timestamp+"_";
File storageDirectory = new File(Environment.getExternalStorageDirectory() + File.separator + "CPB" + File.separator + subFolder);
storageDirectory.mkdir();
File image = File.createTempFile(imageFileName, ".jpg", storageDirectory);
mImageFileLocation = image.getAbsolutePath();
return image;
}
and image is saved here:
private static class ImageSaver implements Runnable {
private final Image mImage;
private ImageSaver(Image image) {
mImage = image;
}
@Override
public void run() {
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mImageFile);
fileOutputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
if(fileOutputStream != null){
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I am getting the correct path to the image after createImageFile()
and toasting it to show what it is every time. But not even the setVisibility
on latest_picture_container
is working... If I comment out the InputStream
, Bitmap
and setImageBitmap
, then the latest_picture_container
shows up as normal. Not sure why this is wrong.
For some reason, the URI is coming back with three slashes after file,
file:///storage/0/...
URI or Uniform Resource Identifier is a compact sequence of characters that identifies an abstract or physical resource. It can be further classified as a locator, a name, or both. Basically URI (in some cases URL or URN) will point to the image location, or will be the name of the image (why not both?).
Displays image resources, for example Bitmap or Drawable resources. ImageView is also commonly used to apply tints to an image and handle image scaling.
The AssetManager#open()
method only works for your app's assets; i.e., the files in your project's /assets
folder. Since you're trying to open an external file, you should instead use a FileInputStream
on a File
object created from the path. Additionally, the takePhoto()
method is setting the image on the ImageView
before anything has been written to the file, which will result in an empty ImageView
.
Since your app is using the camera directly, we can decode the image from the same byte array being written to the image file, and save ourselves an unnecessary storage read. Furthermore, in the example your code follows, the file write is happening on a separate thread, so we might as well take advantage of that in performing the image decode, as it will minimize the impact on the UI thread.
First we'll create an interface through which ImageSaver
can pass the image back to the Activity
to display in the ImageView
.
public interface OnImageDecodedListener {
public void onImageDecoded(Bitmap b);
}
Then we'll need to alter the ImageSaver
class a bit to take an Activity
parameter in the constructor. I've also added a File
parameter, so the Activity
's corresponding field need not be static
.
private static class ImageSaver implements Runnable {
private final Activity mActivity;
private final Image mImage;
private final File mImageFile;
public ImageSaver(Activity activity, Image image, File imageFile) {
mActivity = activity;
mImage = image;
mImageFile = imageFile;
}
@Override
public void run() {
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
final Bitmap b = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
((OnImageDecodedListener) mActivity).onImageDecoded(b);
}
}
);
FileOutputStream fileOutputStream = null;
...
}
}
As soon as we get the image data in the byte array, we decode it and pass it back to the Activity
, so it doesn't have to wait on the file write, which can proceed quietly in the background. We need to invoke the interface method on the UI thread, since we're "touching" View
s there.
The Activity
will need to implement the interface, and we can move the View
-related stuff from takePhoto()
to the onImageDecoded()
method.
public class MainActivity extends Activity
implements ImageSaver.OnImageDecodedListener {
...
@Override
public void onImageDecoded(Bitmap b) {
final ImageView latest_picture =
(ImageView) findViewById(R.id.latest_picture);
final RelativeLayout latest_picture_container =
(RelativeLayout) findViewById(R.id.latest_picture_container);
latest_picture.setImageBitmap(b);
latest_picture_container.setVisibility(View.VISIBLE);
}
public void takePhoto(View view) {
try {
mImageFile = createImageFile();
captureStillImage();
lockFocus();
}
catch (IOException e) {
e.printStackTrace();
}
}
...
}
Finally, we need to actually execute the ImageSaver
in the ImageReader
's onImageAvailable()
method. Again following the example, it would be something like this.
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
mBackgroundHandler.post(new ImageSaver(MainActivity.this,
reader.acquireNextImage(),
mImageFile)
);
}
};
What I usually do is use the Picasso library
Add the dependency to build.gradle
compile 'com.squareup.picasso:picasso:2.5.2'
Since you are getting the file path, set the path to a File object, and then let Picasso grab the image from the phone, and set it to the required ImageView
File fileLocation = new File(uri) //file path, which can be String, or Uri
Picasso.with(this).load(fileLocation).into(imageView);
I do recommend using Picasso for any kind of Image activity on your app, whether it's online or offline. Picasso is made by Square, and is the best when it comes to image loading, caching...
try this simple code
ImageView imgView = view.findViewById(R.id.lw_foto);
imgView.setImageURI(mListaContactos.get(i).foto);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With