I've been trying to use the Android ACTION_IMAGE_CAPTURE intent and ACTION_GET_CONTENT intent to either take a photo or pick one. The problem I'm having is that when I when I try to take a photo using the Android photo intent in portrait mode, it saves it in landscape orientation.
I'm trying to save the Bitmap of the correctly orientated photo from a URI string.
I found this question: Android Camera Intent Saving Image Landscape When Taken Portrait, which is the exact same problem I'm having, but the answer is incomplete and didn't work for me. For example, what is the resizedBitmap, opts, and is file Uri.getPath()?
Well some cameras lock the landscape mode as default mode of camera(Samsung note 2) so if you take a picture in potrait mode the image is still saved in landscape mode. Most of the camera will add metadata into the image like the camera vendor, model,etc. Amongst various metadata that can be present the one we are intrested in is the rotation data. It specifies by what degrees the image is to be rotated. For knowing the rotation you can use ExifInterface class.
resizedBitmap Images are stored as bitmap objects in android. As an image can be large loading them whole into memory can lead to outofmemory error's and make your app consume more memory. So a bitmap is first resized to appropriate size and then loaded into memory.
opts By opts you must be referring to BitmapFactory.Options method. It is a class that provides methods to change the behaviour of bitmaps like making it mutable(is set to true you can apply effects like grayscale to this bitmap) , find its height and width in pixels without loading it to RAM,etc.
file Its a class used to perform CRUD operations in any file stored in the system.
Uri.getPath() this method returns the path where your image is stored or null.
Related
If I use standard camera via Intent to capture image:
Open Camera:
val takePicture = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (takePicture.resolveActivity(packageManager) != null) {
startActivityForResult(takePicture, TAKE_PICTURE)
}
Camera Preview
Result display on ImageView
If I use Camera2 API at: git: https://github.com/googlesamples/android-Camera2Basic
Result of Image not display portrait
Camera 2 Preview
Result display on ImageView
My code display Image:
val bitmap = BitmapFactory.decodeFile(file.toString())
imagePreview.setImageBitmap(bitmap)
}
How setting Camera2 API to display result the same standard camera?
In Camera2Basic example, the ImageSaver does not rotate the captured JPEG with regards to device orientation. Instead, Camera2BasicFragment.captureStillPicture() sets CaptureRequest.JPEG_ORIENTATION, which is only a recommendation for the camera firmware.
Camera devices may either encode this value into the JPEG EXIF header, or rotate the image data to match this orientation. When the image data is rotated, the thumbnail data will also be rotated.
Most often, this recommendation 'only' sets the header, but some devices miss even that. See a recent article on this feature and its reliability.
Please note that the EXIF orientation tag is not respected by all viewer software, therefore often the stock Camera applications do rotate the actual JPEG to default orientation.
Your code that loads the captured picture to ImageView currently ignores this tag. You can use ExifInterface.getAttributeInt(TAG_ORIENTATION) to extract the orientation from the file or input stream. Or, if you capture an image and immediately display it, you can get device orientation directly from the sensor. Now it's time to decide if the camera stored the image as portrait (i.e. width is smaller than height), or as landscape, in which case it's your duty to rotate it for display. Don't rotate the bitmap according to this orientation. Instead, you can call imagePreview.setImageMatrix() to display the image correctly.
By the way, please don't decode the JPEG to full-scale bitmap in memory if you only need it to be passed to your ImageView: this may consume too much RAM. The easiest one-liner is to call setImageURI() instead.
I'm trying to upload a captured photo to a WebView in Android after triggering the onShowFileChooser method of Android's WebChromeClient.
Everything works fine, except all images taken in portrait mode are rotated to landscape.
In onActivityResult, I can create a URI that represents the captured image's file location, which is then passed to ValueCallback.onReceiveValue(T value). However, I can't manipulate the image itself and change the ExifInterface Orientation tag to rotate the image back to portrait.
I could create a bitmap from the URI, rotate, then re-save that bitmap getting a new URI to pass back to the Webview. But that seems terribly expensive and non-performant. Any other suggestions before I go down that route?
I am building an app that relies on showing quite a few bitmap images taken from the camera. I want all of the images to show with a 90 degree (portrait) orientation, and I know how I can do this with the EXIF information provided with each image. Would it be a better idea for me to rotate the bitmap of an image to fit my needs right after it is taken and then send it to my server, or should I send the image to my server without rotating it and then whenever I pull it down, use the EXIF rotation provided with the image to rotate the image view I am displaying it in? I need a solution that is memory efficient and fast. Thanks.
Since bitmap is just a matrix with the some data in every cell it should have the same weight (in terms of mb) if it's portrait or landscape, in case you need the images to be in a 90 deg. tilt ALL the time I would probabley do it before sending it to the server since (by my logic) you would probabley pull it ALOT more than upload it (which will only happen once..) so saving it on the way you are going to display it will basically have no effect on it's weight consumption HOWEVER since you are going to display it alot (again, by my logic since you keep it in a server) saving it alreay rotated will probabley save some other clients the hassle from doing that themselves..
If I take a photo with my camera in android in portrait mode, and then load it as a bitmap and draw it to a canvas it appears rotated counter clockwise 90 degrees and in landscape orientation. I use BitmapFactory.decodeFile(imagePath); to load the image. Does anyone know why this would happen?
Please see the answer at Android: Photos force captured in Landscape mode.
The bottom line is, capture preserves the hardware camera orientation, which is landscape in most telephones. You have few ways to find the actual orientation of the device vs. the horizon when the picture was taken, e.g. the EXIF header of the JPEG file. Bitmap method that decodes such file does not respect the EXIF info, even if it is present. But you can choose one of the ways to apply rotation to the bitmap after it is loaded.
An alternative is to apply rotation to the captured JPEG file, as described in Lossless JPEG Rotate (90/180/270 degrees) in Java?. There is even an app on the PlayStore to do it: https://play.google.com/store/apps/details?id=com.lunohod.jpegtool.
Is it possible to programmatically take a picture in full/high resolution? I use the camera preview and surface with some custom overlay content. The problem is that the takePhoto function returns data only in preview size low resolutions.
Even if I check the getSupportedPictureSizes the resolutions that are listed are far from the 5Mpix that is the max supported resolution by the system camera. So the question is can I take a photo in max resolution and use custom camera preview or I have to call the system camera Intent to have a full res photo?
Yes you can, you should setPictureSize(), see https://github.com/alexcohn/JBcamera for example.
PS Thanks, Benjamin, for drawing my attention back to this question. if I understand correctly, the author was upset with the resolution of data array returned from IMAGE_CAPTURE intent. But this is only the thumbnail; the actual hi-rez imagis writn to file. You can find this Jpeg file and load it into your app, in onActivityResult()
By default I think it is set to a low resolution. To change this call MediaStore.EXTRA_OUTPUT in your intent. See here for more detail:
http://developer.android.com/reference/android/provider/MediaStore.html#ACTION_IMAGE_CAPTURE