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:
gradio-pr-bot: All the demos for this PR have been deployed at https://huggingface.co/spaces/gradio-pr-deploys/pr-3091-all-demos
freddyaboulton: Looking good @dawoodkhan82 ! Thanks for the review! 🎉 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ad4e223b7..db0445848 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,17 @@
 # Upcoming Release
 
 ## New Features:
-No changes to highlight.
+
+### iOS image rotation fixed 🔄
+
+Previously photos uploaded via iOS would be rotated after processing. This has been fixed by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3089](https://github.com/gradio-app/gradio/pull/3091)
+
+#### Before
+![image](https://user-images.githubusercontent.com/41651716/215846507-a36e9d05-1ac2-4867-8ab3-ce045a9415d9.png)
+
+#### After
+![image](https://user-images.githubusercontent.com/41651716/215846554-e41773ed-70f0-491a-9952-6a18babf91ef.png)
+
 
 ## Bug Fixes:
 No changes to highlight.
diff --git a/gradio/processing_utils.py b/gradio/processing_utils.py
index 39ac6b5e7..c181a9bef 100644
--- 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
index 141bed35e..07c6851ea 100644
--- a/test/test_processing_utils.py
+++ b/test/test_processing_utils.py
@@ -73,6 +73,14 @@ class TestImagePreprocessing:
 
         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))