How to capture photo and get image and thumbnail?
Asked Answered
L

2

8

I cannot believe that I've struggled with this simple problem for hours now, but I cannot get it to run properly. In principle I want this functionality:

The user clicks a button. An ACTION_IMAGE_CAPTURE intent is fired and the default camera app opens. The user takes the photo and returns to my app. My app shows the thumbnail. Clicking the thumbnail opens the image viewer.

Actually pretty simple. And with this guide it seemed like it was a matter of copy and paste: https://developer.android.com/training/camera/photobasics.html. But the devil is in the details.

Currently, it does work, but performance is horrible because I create the thumbnails (in my actual app I show multiple thumbnails for each entry in a RecyclerView) on the fly. I hope there is a simple approach that I overlooked during searching through dozens of Stack Overlow questions.

Ideally, I'd like to fire my ACTION_IMAGE_CAPTURE intent, have the default camera app generate the thumbnail, store the thumbnail and the image in the system's content providers for thumbnails and images and finally get the respective content:// URIs back in onActivityResult(). That would be so nice...

Now, here are the problems I'm facing:

  • The URI I receive when invoking getData() on the resulting intent in onActivityResult() is always null whether or not I give a MediaStore.EXTRA_OUTPUT value along with the invoking intent
  • When omitting the MediaStore.EXTRA_OUTPUT extra I get the thumbnail in form of a bitmap and not as a content:// URI. So, I have to persist the thumbnail myself if I don't want to generate it next time I start my activity.
  • I don't understand why I don't get the thumbnail if I pass the camera a content:// URI to save the image to. I mean, the camera has the image loaded in memory and could easily generate the thumbnail. But instead, I have to load multiple MB from disk again just to generate the thumbnail. That seems like a huge waste even if I save the thumbnail for further usage afterwards.
  • I have read that some camera apps actually do create the thumbnail in any case and make it available to the gallery or something. But it seems not to be standardized.

So, I guess my wish two content:// URIs simply is not how it works. But before I proceed to generate (eventually duplicate) thumbnails myself and persist and cache them in my app I want to ask:

Is there some easy way I'm not aware of? Is it possible to retrieve both, image and thumbnail or do I have to generate the thumbnail myself?

Note: I want to make the photos taken with my app available to the gallery by letting Android add it to the media database. I can't imagine that every app that accesses that media database (like the gallery) creates it's own set of thumbnails, right?

Thanks in advance!

Landsman answered 15/2, 2018 at 12:48 Comment(0)
B
5

The URI I receive when invoking getData() on the resulting intent in onActivityResult() is always null whether or not I give a MediaStore.EXTRA_OUTPUT value along with the invoking intent

There is no Uri returned by ACTION_IMAGE_CAPTURE. If you supply EXTRA_OUTPUT, you know where the image is supposed to reside, so go look for it there.

When omitting the MediaStore.EXTRA_OUTPUT extra I get the thumbnail in form of a bitmap and not as a content:// URI.

Correct.

I don't understand why I don't get the thumbnail if I pass the camera a content:// URI to save the image to.

That's not the way the ACTION_IMAGE_CAPTURE protocol is documented. Either you get a full-size photo written to EXTRA_OUTPUT, or you get a thumbnail via the "data" extra, not both.

I mean, the camera has the image loaded in memory and could easily generate the thumbnail.

There is no single "the camera". There are hundreds of camera apps — both pre-installed and user-installed — that might respond to your ACTION_IMAGE_CAPTURE request, across the ~10,000 device models and ~2 billion devices.

Is it possible to retrieve both, image and thumbnail

Not via ACTION_IMAGE_CAPTURE.

do I have to generate the thumbnail myself?

Ask the MediaStore for a thumbnail, perhaps. I haven't played with retrieving images from MediaStore, but AFAIK it prepares thumbnails of images that indexes. However, bear in mind that your request to index (e.g., MediaScannerConnection.scanFile()) is asynchronous. You may need to temporarily manage thumbnails yourself for images that you capture during this run of the app, relying on the MediaStore for all other images.

I can't imagine that every app that accesses that media database (like the gallery) creates it's own set of thumbnails

I would imagine that many apps request the full-size images and let their image-loading library (Glide, Picasso, etc.) scale the image to the desired size.

Who would want to take a photo to only get the thumbnail?

The ACTION_IMAGE_CAPTURE protocol has been around for a decade. In 2008, everything mobile was expensive: CPU, memory, and bandwidth. Even in 2018, in many parts of the world, some of that stuff is expensive, relative to income levels. Just because you want both full-size and thumbnail images does not mean that everybody does.

Backslide answered 15/2, 2018 at 13:36 Comment(0)
E
0

you can generate thumbnail image from your actual image like this :

final int thumbSize = 64;

Bitmap thumbBitmap= ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(actualImagePath), 
                    thumbSize, thumbSize);
Electromotor answered 15/2, 2018 at 12:58 Comment(3)
I want to avoid generating the thumbnail myself if possible and use the one the camera creates.Landsman
Actually in onActivityResult Bitmap photo = (Bitmap) data.getExtras().get("data"); does not grab the image that was taken. It grabs a thumbnail of the image that was taken.Electromotor
Yes, unfortunately, the thumbnail bitmap is only bundled if I don't provide a URI to save my image to. But then, I cannot access my full size image. And that drives me nuts! Who would want to take a photo to only get the thumbnail? Why wouldn't the API designers return the image URI? ...Landsman

© 2022 - 2024 — McMap. All rights reserved.