Repository: gradio-app/gradio

Issue:
images rotated
### Describe the bug

When I upload an image on my iphone it gets rotated vs. uploading the same image on desktop. 

I assume this might have something to do with the iphone image upload being HEIC. 

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Reproduction

https://huggingface.co/spaces/krrishD/suitify_v1

### Screenshot

_No response_

### Logs

```shell
no debug output for this
```


### System Info

```shell
Using gradio on my iphone
```


### Severity

serious, I can't work around it


Discussion:
I've noticed this issue before, it seems to be a general problem with image uploading systems. @dawoodkhan82 would you be able to take a look at this?
I only run into this issue when I select the "Take Photo or Video" option:
![image](https://user-images.githubusercontent.com/128432/194161130-ffbc72d8-82c6-4ff9-a05d-b900a5431972.png)

This doesn't happen to me when uploading via an image component

![IMG_90E4581EA15E-1](https://user-images.githubusercontent.com/41651716/214410239-ff7bdc11-3749-4010-b93e-ec6939684d36.jpeg)


But it does happen to me when using UploadButton + Chatbot in https://huggingface.co/spaces/ysharma/InstructPix2Pix_Chatbot

![IMG_4496](https://user-images.githubusercontent.com/41651716/214412808-57942eb3-62c0-495f-ac61-6e91bcff4891.jpg)

Reproduced here: https://www.loom.com/share/d62c8614873f4294b6169fa637976b97

This is the space I used in the loom (its public): https://huggingface.co/spaces/lakshman111/imageprocessingdebugging

The space just echos the user's image back to them, and it comes back horizontal when I used an iPhone and took a vertical image.

@freddyaboulton it looks like the issue isn't happening on upload, but rather happening during pre or post processing

Resolving patch:
diff --git a/gradio/processing_utils.py b/gradio/processing_utils.py
--- a/gradio/processing_utils.py
+++ b/gradio/processing_utils.py
@@ -52,7 +52,12 @@ def to_binary(x: str | Dict) -> bytes:
 def decode_base64_to_image(encoding: str) -> Image.Image:
     content = encoding.split(";")[1]
     image_encoded = content.split(",")[1]
-    return Image.open(BytesIO(base64.b64decode(image_encoded)))
+    img = Image.open(BytesIO(base64.b64decode(image_encoded)))
+    exif = img.getexif()
+    # 274 is the code for image rotation and 1 means "correct orientation"
+    if exif.get(274, 1) != 1 and hasattr(ImageOps, "exif_transpose"):
+        img = ImageOps.exif_transpose(img)
+    return img
 
 
 def encode_url_or_file_to_base64(path: str | Path, encryption_key: bytes | None = None):


Test patch:
diff --git a/test/test_processing_utils.py b/test/test_processing_utils.py
--- a/test/test_processing_utils.py
+++ b/test/test_processing_utils.py
@@ -73,6 +73,14 @@ def test_encode_pil_to_base64_keeps_pnginfo(self):
 
         assert decoded_image.info == input_img.info
 
+    @patch("PIL.Image.Image.getexif", return_value={274: 3})
+    @patch("PIL.ImageOps.exif_transpose")
+    def test_base64_to_image_does_rotation(self, mock_rotate, mock_exif):
+        input_img = Image.open("gradio/test_data/test_image.png")
+        base64 = processing_utils.encode_pil_to_base64(input_img)
+        processing_utils.decode_base64_to_image(base64)
+        mock_rotate.assert_called_once()
+
     def test_resize_and_crop(self):
         img = Image.open("gradio/test_data/test_image.png")
         new_img = processing_utils.resize_and_crop(img, (20, 20))