Skip to content

Apply EXIF orientation when resolving local image dimensions#6514

Merged
gpunto merged 1 commit into
developfrom
fix/exif-orientation-local-image-dimensions
Jun 25, 2026
Merged

Apply EXIF orientation when resolving local image dimensions#6514
gpunto merged 1 commit into
developfrom
fix/exif-orientation-local-image-dimensions

Conversation

@gpunto

@gpunto gpunto commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Goal

EXIF-rotated images (camera and selfie portrait shots) get the wrong aspect ratio: AttachmentStorageHelper.resolveLocalDimensions reads raw BitmapFactory bounds and ignores EXIF orientation, so a portrait photo gets a landscape attachment box. The video branch already swaps width/height for rotation.

Note that there's a difference depending on the CDN:

  • On Stream CDN the bug only shows during upload, since the backend then returns corrected dimensions that replace the local ones
  • On a custom CDN the wrong box would persist

Closes AND-1258

Implementation

The image branch of resolveLocalDimensions now reads the EXIF orientation and swaps the decoded width/height for orientations that change the aspect ratio (ROTATE_90, ROTATE_270, TRANSPOSE, TRANSVERSE), mirroring the video branch's rotation handling.

UI Changes

Before After
Screen_recording_20260624_110325.webm
Screen_recording_20260624_110214.webm

Testing

  • New AttachmentStorageHelperExifTest (Robolectric) decodes a real landscape JPEG and asserts: normal orientation keeps 80x40; rotate-90, rotate-270, and transpose swap to 40x80.
  • Manual: pushed EXIF-rotated images to the sample app, confirmed portrait shots now get a portrait attachment box instead of a landscape one.

Summary by CodeRabbit

  • Bug Fixes
    • Improved image attachment handling so photo dimensions are now detected correctly when files include rotation metadata.
    • Fixed cases where some images could appear with swapped width and height after upload or attachment resolution.

@gpunto gpunto added the pr:bug Bug fix label Jun 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled, or the PR is bot-authored.
  • An issue is linked (Linear ticket or GitHub issue), or the PR is bot-authored.

🎉 Great job! This PR is ready for review.

@gpunto gpunto changed the title ui-common: Apply EXIF orientation when resolving local image dimensions Apply EXIF orientation when resolving local image dimensions Jun 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.90 MB 5.90 MB 0.00 MB 🟢
stream-chat-android-ui-components 11.15 MB 11.15 MB 0.00 MB 🟢
stream-chat-android-compose 12.61 MB 12.61 MB 0.00 MB 🟢

@gpunto gpunto force-pushed the fix/exif-orientation-local-image-dimensions branch from c39478b to c738704 Compare June 24, 2026 09:39
@sonarqubecloud

Copy link
Copy Markdown

@gpunto gpunto marked this pull request as ready for review June 24, 2026 10:27
@gpunto gpunto requested a review from a team as a code owner June 24, 2026 10:27
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 05147dca-496c-44d4-909d-f9212adee2a3

📥 Commits

Reviewing files that changed from the base of the PR and between 159e1ac and c738704.

📒 Files selected for processing (4)
  • gradle/libs.versions.toml
  • stream-chat-android-ui-common/build.gradle.kts
  • stream-chat-android-ui-common/src/main/kotlin/io/getstream/chat/android/ui/common/helper/internal/AttachmentStorageHelper.kt
  • stream-chat-android-ui-common/src/test/kotlin/io/getstream/chat/android/ui/common/helper/internal/AttachmentStorageHelperExifTest.kt

Walkthrough

Adds the androidx.exifinterface library to the version catalog and stream-chat-android-ui-common build, then updates AttachmentStorageHelper to read EXIF orientation from cached image files and swap width/height when the orientation implies rotated dimensions. A new parameterized Robolectric test validates the swap logic across multiple EXIF orientation values.

EXIF Orientation-Aware Image Dimensions

Layer / File(s) Summary
ExifInterface dependency declaration
gradle/libs.versions.toml, stream-chat-android-ui-common/build.gradle.kts
Registers androidxExifInterface in the version catalog and adds implementation(libs.androidx.exifinterface) to the ui-common module.
EXIF orientation swap in AttachmentStorageHelper
stream-chat-android-ui-common/src/main/kotlin/.../helper/internal/AttachmentStorageHelper.kt
Imports ExifInterface, changes the dimension return to swap width/height when hasSwappedExifDimensions returns true, and adds the private helper that reads EXIF orientation and returns false on any exception.
Parameterized EXIF orientation tests
stream-chat-android-ui-common/src/test/kotlin/.../helper/internal/AttachmentStorageHelperExifTest.kt
Robolectric parameterized test that writes a base64 JPEG with a given TAG_ORIENTATION, mocks StorageHelper to return that file, calls resolveAttachmentFiles, and asserts originalWidth/originalHeight are correctly swapped or preserved for each orientation case.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop hop, the image stood sideways one day,
Width was the height and height was astray!
ExifInterface peeked at the JPEG's true spin,
Swapped the dimensions and let the right ones win.
Now thumbnails stand tall — no more topsy display! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: applying EXIF orientation when resolving local image dimensions.
Description check ✅ Passed The description covers the goal, implementation, UI changes, and testing, with only non-critical template sections like the checklist and GIF missing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/exif-orientation-local-image-dimensions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gpunto gpunto merged commit 7313a21 into develop Jun 25, 2026
28 of 30 checks passed
@gpunto gpunto deleted the fix/exif-orientation-local-image-dimensions branch June 25, 2026 07:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants