Search code examples
androidfirebaserotationpicasso

Rotate image from uri address, using Picasso


I have successfully upload a Users profile image to the Firebase storage area under their UserID.

From there I have put the file path to that image in the Firebase database under the usersID

Firebase Database Structure, Showing he profileImage uri that is linked to the firebase storage area

When I am displaying the image on the page the image is rotated the wrong way around. The photo on my phone is portrait, but it is saving in the Firebase storage area as landscape.

Image Stored In Landscape orientation in Firebase Storage, but was taken in portrait orientation

The image rendered on my phone in the wrong orientation

What I want to be able to do is let the user select an image from the gallery, then display the image on a page.Then I want to be able to let the user rotate the image themselves, left or right using two buttons.

When I press the rotate buttons. The image successfully rotates once. Then when I press the Save Profile Image button it sends the original image from the gallery to the Firebase Storage area. It is storing and sending the wrong image to the Storage. Essentially, it is saving the original, unrotated image to the storage.

Is there a way that I can fix this?

Here is my code:

private FirebaseAuth auth;
private DatabaseReference myRef;
private FirebaseDatabase database;
private StorageReference storageReference;
private FirebaseUser user;

private ImageView profileImage;
private Uri imageUri;

private static final int GALLERY_INTENT = 2;

private ProgressDialog progressDialog;

/*
Skip irrelevant code
*/

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
    {

        View view = inflater.inflate(R.layout.fragment_upload_image, container, false);

        // Creating firebase links etc
        database = FirebaseDatabase.getInstance();
        myRef = FirebaseDatabase.getInstance().getReference();
        auth = FirebaseAuth.getInstance();
        storageReference = FirebaseStorage.getInstance().getReference();
        user = auth.getCurrentUser();

        // Setting buttons
        profileImage = (ImageView) view.findViewById(R.id.imageViewProfileImage);
        ImageView rotateLeft = (ImageView) view.findViewById(R.id.imageRotateLeft);
        ImageView rotateRight = (ImageView) view.findViewById(R.id.imageRotateRight);
        Button uploadProfileImage = (Button) view.findViewById(R.id.buttonUploadProfileImage);
        Button saveProfileImage = (Button) view.findViewById(R.id.buttonSaveProfileImage);

        // Rotate Left is a button
        rotateLeft.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                if(profileImage != null)
                {
                    // Rotate image 90
                    Picasso.get().load(imageUri).rotate(90).into(profileImage);
                }
            }
        });

        // Rotate Right is a button
        rotateRight.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                if(profileImage != null)
                {
                    // Rotate image -90
                    Picasso.get().load(imageUri).rotate(-90).into(profileImage);
                }
            }
        });

        uploadProfileImage.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                // Send user to gallery
                Intent intent = new Intent(Intent.ACTION_PICK);
                intent.setType("image/*");
                startActivityForResult(intent, GALLERY_INTENT);
            }
        });

        // Save image to storage area
        saveProfileImage.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                progressDialog.setMessage("Uploading Image Please Wait...");
                progressDialog.show();

                final StorageReference filePath = storageReference.child("Images").child(user.getUid()).child(imageUri.getLastPathSegment());
                filePath.putFile(imageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>()
                {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot)
                    {
                        Toast.makeText(getActivity(), "Uploaded Successfully!", Toast.LENGTH_SHORT).show();
                        Uri downloadUri = taskSnapshot.getDownloadUrl();

                        // Save image uri in the Firebase database under the usersID
                        myRef.child("Users").child(user.getUid()).child("profileImage").setValue(downloadUri.toString());
                        progressDialog.dismiss();
                    }
                }).addOnFailureListener(new OnFailureListener()
                {
                    @Override
                    public void onFailure(@NonNull Exception e)
                    {
                        progressDialog.dismiss();
                        Toast.makeText(getActivity(), "Failed To Upload!", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });

        return view;
    }

    // Get image data and display on page
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);

        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);

            progressDialog.dismiss();
        }
    }

Solution

  • You can try downloading image as a Bitmap, then rotating it and then saving. Here is the code you can use to do that with Picasso:

    int rotationAngle; // You set this angle before calling the method
    Target target = new Target() {
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            Matrix matrix = new Matrix();
            matrix.postRotate(rotationAngle);
            Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
                    matrix, true);
    
            // Save the rotatedBitmap elsewhere
        }
        @Override
        public void onBitmapFailed(Drawable errorDrawable) {}
        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {}
    };
    void downloadImageRotateAndSave() {
        Picasso.with(getContext()).load(imageUri).into(target);
    }