How to fix uploaded image auto rotate problem in java - java

I am using java and vaadin 14 as a web framework.
In vaadin i am using Vaadin Uploader component to upload an image from camera or image gallery on android phone .
When i choose an image from gallery then it's uploaded and shows normally. But when i am trying to upload an image from phone camera in particular device(samsung) then uploaded image rotated automatically That means, uploaded image shows in portrait if captured in landscape and if captured in portrait it shows landscape. how to solve it?
Note: It does not happen in all android devices. Only in samsung android devices like samsung s7.
here is my code-
import com.vaadin.flow.component.upload.SucceededEvent;
import com.vaadin.flow.component.upload.Upload;
private void fileUploaderInit() {
uploader = new Upload(buffer);
uploader.setMaxFiles(1);
uploader.setDropAllowed(false);
uploader.setAcceptedFileTypes("image/*");
uploader.getElement().removeProperty("capture");
uploader.setUploadButton(image);
uploader.addSucceededListener(event -> {
succeedEvent = event;
saveUploadedImage();
setUserImage();
});
uploader.getElement().addEventListener("file-abort", remove -> {
succeedEvent = null;
});
uploadLayout.add(uploader);
}
private void saveUploadedImage() {
if (succeedEvent != null && userEntity != null) {
addData();
succeedEvent = null;
Notification.show("Image saved successfully.",2000, Position.MIDDLE);
userEvent.fire(new UserEvent(userEntity,false));
}
uploader.getElement().setPropertyJson("files", Json.createArray());
}

I usually use Retrofit for uploading image and files but it is not related uploading service.
It just is related to camera image processing.
Let me show you my code to fix rotation issue.
public Bitmap getImageFromPath(String photoPath) {
Bitmap bitmap = BitmapFactory.decodeFile(photoPath);
Bitmap rotatedBitmap = bitmap;
ExifInterface ei = null;
try {
ei = new ExifInterface(photoPath);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
switch(orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotatedBitmap = rotateImage(bitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotatedBitmap = rotateImage(bitmap, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotatedBitmap = rotateImage(bitmap, 270);
break;
case ExifInterface.ORIENTATION_NORMAL:
default:
rotatedBitmap = bitmap;
}
} catch (IOException e) {
e.printStackTrace();
}
return rotatedBitmap;
}
After taking image from Camera, you save it to android directory and you should detect its orientation and rotate like this code.
Good luck.

Related

Android - Activity orientation stuck after Camera Activity

In our application, the user presses a button which opens the Android default camera activity.
Snippet on how we start the camera activity:
Uri uri = FileProvider.getUriForFile(this, FILE_PROVIDER, image);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, 1);
The problem is if the Activity is in portrait mode, everything works fine, camera is in portrait mode, image gets saved in the correct orientation, etc.
In landscape mode though, the camera starts and after returning the activity is stuck in portrait mode and does not change by tilting the phone anymore.
Does anyone know a solution for this problem?
EDIT: code of onActivityResult(...)
EDIT2: resolved custom methods
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == CAMERA_ACTIVITY_CODE && resultCode == Activity.RESULT_OK) {
//returns Filehandler to image
File objektImage = getImageForObjekt(loadedObjekt);
correctImageRotation(objektImage);
//ImageView
this.imgObjekt.setImageDrawable(Drawable.createFromPath(objektImage.getAbsolutePath()));
}
}
This method corrects the image rotation - cameras on Samsung phones stored them in the wrong orientation which is corrected here:
public boolean correctImageRotation(File img) {
ExifInterface ei;
try {
ei = new ExifInterface(img.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
return false;
}
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
Log.d(this._LOGKEY, getLogPraefix()+" Store the new Objekt image to: " + img.getName());
Bitmap bm = BitmapFactory.decodeFile(img.getAbsolutePath());
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
bm = rotateImage(bm, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
bm = rotateImage(bm, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
bm = rotateImage(bm, 270);
break;
}
bm = ImageHelper.squarify(bm);
bm = ImageHelper.compress(bm, ImageHelper.Size.large);
try {
FileOutputStream stream = new FileOutputStream(img);
bm.compress(Bitmap.CompressFormat.JPEG, 90, stream);
stream.flush();
stream.close();
return true;
} catch (FileNotFoundException e) {
Log.e(_LOGKEY, getLogPraefix()+": file not found.");
return false;
} catch (IOException e) {
Log.e(_LOGKEY, getLogPraefix()+": IO problem.");
return false;
}
}
This method cuts the image s.t. it is square-shaped afterwards:
public static Bitmap squarify(Bitmap srcBmp) {
Bitmap dstBmp;
if (srcBmp.getWidth() >= srcBmp.getHeight()){
dstBmp = Bitmap.createBitmap(
srcBmp,
srcBmp.getWidth()/2 - srcBmp.getHeight()/2,
0,
srcBmp.getHeight(),
srcBmp.getHeight()
);
}else{
dstBmp = Bitmap.createBitmap(
srcBmp,
0,
srcBmp.getHeight()/2 - srcBmp.getWidth()/2,
srcBmp.getWidth(),
srcBmp.getWidth()
);
}
return dstBmp;
}
And finally this method compresses the image in one of three possible sizes:
public static Bitmap compress(Bitmap srcBmp, Size size) {
int side;
switch (size) {
default:
case small:
side = 200;
break;
case medium:
side = 400;
break;
case large:
side = 800;
break;
}
return Bitmap.createScaledBitmap(srcBmp, side, side, true);
}

FileNotFoundException when Using ExifInterface

I have been uploading images to FirebaseStorage, but often they are the wrong way around when displaying them. I have discovered the ExifInterface that can determined the orientation of the image and rotate and flip it if necessary.
When selecting the image from the gallery area on my phone I get this error.
I can select the image on my phone from the gallery and It can be displayed on the page.
The differences between the URI address and the data is one /
Data.getData() address : content://media/external/images/media/53331
uri.toString() address: content:/media/external/images/media/53331
I'm using the uri address as the images absolute path of the image to be able to rotate it if necessary. I pass this value into another method called modifyOrientation which then rotates it. Once it is passed into the method it reaches the line
ExifInterface ei = new ExifInterface(image_absolute_path);
and then returns to the catch as the file was not found.
Below is the entire error I'm getting as well as all my code. How can I fix this issue that I'm having. So when I pass the URI across into the next method it actually has the correct address.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
final FirebaseUser user = auth.getCurrentUser();
if (requestCode == GALLERY_INTENT && resultCode == RESULT_OK)
{
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Displaying Image...");
progressDialog.show();
//imageUri = data.getData();
//Picasso.get().load(imageUri).into(profileImage);
final Uri uri = data.getData();
File file = new File(uri.toString());
file.getAbsolutePath();
progressDialog.dismiss();
try
{
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), uri);
modifyOrientation(bitmap,file.getAbsolutePath());
profileImage.setImageBitmap(bitmap);
}
catch(IOException e)
{
e.getStackTrace();
}
}
}
public static Bitmap modifyOrientation(Bitmap bitmap, String image_absolute_path) throws IOException {
ExifInterface ei = new ExifInterface(image_absolute_path);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return rotate(bitmap, 90);
case ExifInterface.ORIENTATION_ROTATE_180:
return rotate(bitmap, 180);
case ExifInterface.ORIENTATION_ROTATE_270:
return rotate(bitmap, 270);
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
return flip(bitmap, true, false);
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
return flip(bitmap, false, true);
default:
return bitmap;
}
}
public static Bitmap rotate(Bitmap bitmap, float degrees) {
Matrix matrix = new Matrix();
matrix.postRotate(degrees);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
public static Bitmap flip(Bitmap bitmap, boolean horizontal, boolean vertical) {
Matrix matrix = new Matrix();
matrix.preScale(horizontal ? -1 : 1, vertical ? -1 : 1);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
A Uri is not a File.
Step #1: Delete File file = new File(uri.toString());
Step #2: Make sure that you are using the Support Library edition of ExifInterface
Step #3: Call getContentResolver() on your Activity to get a ContentResolver
Step #4: Call openInputStream() on the ContentResolver, passing in the Uri, to get an InputStream on the content pointed to by that Uri
Step #5: Pass that InputStream to the ExifInterface constructor
Step #6: Use that ExifInterface as you are presently, to determine the image orientation
Step #7: Once you get things working, move all of this I/O to a background thread

Auto Image Rotated from Portrait to Landscape

I am taking photo and storing it into SD Card , and later viewing it from SD Card into ImageView, but getting as rotated ...
I am capturing it in Portrait mode , but getting resultant image in Landscape mode...
Is there something which I am missing ?
ExifUtil.java class found here
/**
* Displaying captured image/video on the screen
* */
private void previewMedia(boolean isImage) {
// Checking whether captured media is image or video
if (isImage) {
imgPreview.setVisibility(View.VISIBLE);
final Bitmap bitmap = BitmapFactory.decodeFile(filePath);
Bitmap orientedBitmap = ExifUtil.rotateBitmap(filePath, bitmap);
imgPreview.setImageBitmap(orientedBitmap);
} else {
imgPreview.setVisibility(View.GONE);
}
}
but still showing rotated image in a ImageView ...
If the image(photo) were taken by a program made by you, you must set Parameters.setRotation with the correct rotation value.
This, depending of camera drive, rotates the image before save or save the rotation value to exif TAG_ORIENTATION.
Therefore, if TAG_ORIENTATION is null or zero, the image are in the correct orientation, otherwise you must rotate image according the value in TAG_ORIENTATION.
CODE
Get orientation from EXIF:
ExifInterface exif = null;
try {
exif = new ExifInterface(path);
} catch (IOException e) {
e.printStackTrace();
}
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
Get bitmap rotated:
Bitmap bmRotated = rotateBitmap(bitmap, orientation);
Method to rotate bitmap:
public static Bitmap rotateBitmap(Bitmap bitmap, int orientation) {
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
return bitmap;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
matrix.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(-90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-90);
break;
default:
return bitmap;
}
try {
Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
return bmRotated;
}
catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
}
}
Source - https://stackoverflow.com/a/20480741/3036759
You need to use EXIF with ORIENTATION_UNDEFINED to get right orientation.
ExifInterface exif = null;
try {
exif = new ExifInterface(path);
} catch (IOException e) {
e.printStackTrace();
}
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
And rotate the Bitmap :
Bitmap bmRotated = rotateBitmap(bitmap, orientation);
Reference link

How to download image in android?

I have an image to the right and a button "download" to the left. the image is from my drawable. now,when i try to click the download i want to put the image to my sdcard downloads. Please help me i only see about download in url. is there other solution for this . Thanks
public class ImageDownloader {
public void download(String url, ImageView imageView) {
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
task.execute(url);
}
}
/* class BitmapDownloaderTask, see below */
}
First, you need to get your Bitmap. You can already have it as an object Bitmap, or you can try to get it from the ImageView such as:
BitmapDrawable drawable = (BitmapDrawable) ImageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
Then you must get to directory (a File object) from SD Card such as:
File sdCardDirectory = Environment.getExternalStorageDirectory();
Next, create your specific file for image storage:
File image = new File(sdCardDirectory, "test.png");
After that, you just have to write the Bitmap such as:
boolean success = false;
// Encode the file as a PNG image.
FileOutputStream outStream;
try {
outStream = new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
/* 100 to keep full quality of the image */
outStream.flush();
outStream.close();
success = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Finally, just deal with the boolean result if needed. Such as:
if (success) {
Toast.makeText(getApplicationContext(), "Image saved with success",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
"Error during image saving", Toast.LENGTH_LONG).show();
}
Don't forget to add the following permission in your Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Bitmap is to large to be uploaded into a texture

I have a app that uploads a picture made by the camera and upload it to a server.
But when i try to get it from the server into my imageview it says that the bitmap is to large ( in pixels )
How can i fix this?
new DownloadImageTask(imgProfile)
.execute("http://api.nl/local/index.php?action=get_user_profile_picture&username="
+ SaveSharedPreferences.user.getUsername()
+ "&password="
+ SaveSharedPreferences.user.getPassword()
+ "&user_number="
+ SaveSharedPreferences.user.getUserNumber());
This is my code that i use to process the image to the imageview:
class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
try{
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch(OutOfMemoryError e){
}
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
What you are seeing is the effect of hardware acceleration. The system tries to load an extremely huge bitmap into an image view. If you have hardware acceleration turned on (e.g. via the Manifest) android will try to put the bitmap into an openGL texture, and your image is too big for this. It does not matter if you use JPEG or bitmaps for this, as the final openGL texture will have raw data and thus be a bitmap either way (each pixel is represented as it's own float values).
The only chance you have is to either download the image a lot smaller or resize it on the device. I'd go with the smaller download because it will also save the users's bandwith (and therefore costs)
BitmapFactory.Options options = null;
options = new BitmapFactory.Options();
options.outHeight = IMAGE_WIDTH_HEIGHT;//give some value
options.outWidth = IMAGE_WIDTH_HEIGHT;//which is suitable for your app image size
BitmapFactory.decodeStream(is, outPadding, options); //try this

Categories