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?
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.
Picasso.with(mContext).load(lPreviewData.getImage()).into(holder.lPreviewIV);
This is how I am rendering the image url to ImageView. Unfortunately when i render an image it was showing in landscape mode but the actual image is in portrait.
This is a problem with exif rotation handling in Picasso. You should either rotate the image in code or fix the source image to have the correct orientation without using exif rotation.
I should also mention that this problem only affects images retrieved via url.
I'm using the Dropbox Core API to download and display photos. Downloading them and writing to a FileOutputStream is easy enough with:
DropboxAPI.getFile(filePath, null, fos, null);
But the downloaded image is always rotated. If I view the image in my web browser, it displays as upright. But the image written to the FileOutputStream is rotated. Any suggestions as to why this occurs? I can't find anything provided by the metadata that describes how an image should be orientated, but possibly I'm missing something there?
It seems like it would be a mistake to simply check if the image's width is greater than it's height, and to rotate it to portrait orientation based on that?
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.
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.