Skip to content

fix: apply EXIF orientation to filmstrip thumbnails#136

Merged
amemya merged 9 commits into
mainfrom
fix/issue-135-thumbnail-orientation
Jul 8, 2026
Merged

fix: apply EXIF orientation to filmstrip thumbnails#136
amemya merged 9 commits into
mainfrom
fix/issue-135-thumbnail-orientation

Conversation

@amemya

@amemya amemya commented Jul 8, 2026

Copy link
Copy Markdown
Owner

fixed #135
縦画像でもサムネイルが横を向く問題を修正
追加ロジックに対するユニットテストを追加

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 95fd7065-85dd-4fec-adbe-37438df29612

📥 Commits

Reviewing files that changed from the base of the PR and between b3e6c5b and ee87a55.

📒 Files selected for processing (1)
  • handler.go

📝 Walkthrough

Summary by CodeRabbit

  • 新機能

    • サムネイル生成時に、EXIFの向き情報に合わせて画像を正しい向きで表示するようになりました。
    • EXIFサムネイルが使える場合も、必要に応じて回転した画像を返すようになりました。
  • 改善

    • サムネイル生成の処理順を見直し、ファイル保持時間を短縮しつつ、重い処理の同時実行を抑えるよう改善しました。

Walkthrough

handler.goにEXIF Orientationを反映する回転処理を追加し、EXIFサムネイル返却経路と高解像度からのサムネイル生成経路に適用した。rotate_test.goで回転結果のサイズと色を検証するテストも追加した。

Changes

サムネイル回転処理

Layer / File(s) Summary
rotateImageユーティリティの実装
handler.go
Orientation値に応じて画像を回転するrotateImage関数を追加し、3/6/8でRGBA画像を再構築して返す。
サムネイル生成経路への回転適用
handler.go
handleThumbでEXIF Orientationを取得し、JpegThumbnailは3/6/8のみ回転して再エンコードし、それ以外は無回転で返す。高解像度からの生成でも3/6/8のときだけ回転画像をJPEG化する。
回転処理のテスト追加
rotate_test.go
固定パターン画像に対して複数Orientationの回転後サイズと左上ピクセル色を検証するテーブル駆動テストを追加した。

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant handleThumb
  participant rotateImage
  participant JPEGEncoder
  participant fileOpenSem
  participant thumbProcessSem

  Client->>handleThumb: サムネイル取得リクエスト
  handleThumb->>handleThumb: EXIF Orientation取得
  alt JpegThumbnailあり
    alt Orientationが3/6/8
      handleThumb->>rotateImage: 回転画像を生成
      rotateImage-->>handleThumb: 回転後画像
      handleThumb->>JPEGEncoder: JPEGエンコード
      JPEGEncoder-->>handleThumb: 回転済みバイト列
      handleThumb-->>Client: 回転済みサムネイル
    else それ以外
      handleThumb-->>Client: 元のEXIFサムネイル
    end
  else JpegThumbnailなし
    handleThumb->>thumbProcessSem: 生成処理の許可を取得
    handleThumb->>fileOpenSem: ファイルオープンの許可を取得
    handleThumb->>rotateImage: 生成画像を回転
    rotateImage-->>handleThumb: 回転後画像
    handleThumb->>JPEGEncoder: JPEGエンコード
    JPEGEncoder-->>handleThumb: サムネイルバイト列
    handleThumb-->>Client: サムネイル
  end
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 主要な変更点であるEXIF Orientation をサムネイルに反映する修正を端的に表しています。
Description check ✅ Passed 縦画像のサムネイルの向き修正とユニットテスト追加を述べており、変更内容と一致しています。
Linked Issues check ✅ Passed #135 の縦画像サムネイルが横向きになる問題に対し、EXIF Orientation の反映とテスト追加で対応しています。
Out of Scope Changes check ✅ Passed 向き補正の実装と関連テストに加え、同一処理経路の並行制御整理が含まれており、逸脱は見当たりません。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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/issue-135-thumbnail-orientation

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.

@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 52.17391% with 44 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
handler.go 52.17% 31 Missing and 13 partials ⚠️

📢 Thoughts on this report? Let us know!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses Issue #135 by applying EXIF Orientation when serving filmstrip thumbnails via /api/thumb, so portrait images no longer appear sideways. It introduces a small rotation helper and adds a unit test validating the rotation logic.

Changes:

  • Add rotateImage helper to apply common EXIF rotations (3/6/8).
  • Read EXIF Orientation in handleThumb and rotate both embedded EXIF thumbnails and generated thumbnails accordingly.
  • Add unit tests for the rotation helper.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
handler.go Reads EXIF Orientation and rotates thumbnails (embedded and generated) using a new rotateImage helper.
rotate_test.go Adds unit test coverage for rotateImage across several orientation values.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread handler.go Outdated
Comment thread handler.go Outdated
Comment thread rotate_test.go
Comment on lines +73 to +77
if bounds.Dx() != tt.wantW || bounds.Dy() != tt.wantH {
t.Errorf("rotateImage() bounds = %dx%d, want %dx%d", bounds.Dx(), bounds.Dy(), tt.wantW, tt.wantH)
}

r, g, b, a := rotated.At(0, 0).RGBA()
Comment thread handler.go Outdated
Comment on lines +209 to +213
thumbProcessSem <- struct{}{}
defer func() { <-thumbProcessSem }()

if thumbImg, _, err := image.Decode(bytes.NewReader(pic)); err == nil {
rotatedThumb := rotateImage(thumbImg, orientation)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@handler.go`:
- Around line 190-232: Add integration coverage for the handleThumb EXIF
rotation path, since rotateImage is already unit-tested but the end-to-end
decode/rotate/re-encode flow is not. In handler_test.go, extend or add a helper
alongside createTestJPEG to generate JPEGs with EXIF Orientation metadata, then
add tests that exercise handleThumb with orientation != 1 and verify the rotated
thumbnail is returned correctly. Also add a case for the fallback path when
rotation or re-encoding fails, asserting the original unrotated thumbnail is
served.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c821397d-68d7-4fd2-95bf-a28f790eeb3a

📥 Commits

Reviewing files that changed from the base of the PR and between 3dde3df and d084bdb.

📒 Files selected for processing (2)
  • handler.go
  • rotate_test.go

Comment thread handler.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread handler.go Outdated
Comment on lines +207 to +211
// Needs rotation, protect with semaphore to prevent CPU exhaustion
rotatedBytes := func() []byte {
thumbProcessSem <- struct{}{}
defer func() { <-thumbProcessSem }()

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@amemya

amemya commented Jul 8, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@handler.go`:
- Around line 201-234: The passthrough thumbnail path in the closure around
x.JpegThumbnail is writing the response with w.Write(pic) while fileOpenSem is
still held, unlike the EXIF-rotation path that defers writing until after the
semaphore is released. Move the passthrough write out of the file-open critical
section so both the non-rotated and rotated thumbnail flows return the bytes and
let the outer handler write the response after releasing fileOpenSem, preserving
the starvation-avoidance behavior without re-encoding.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9adc33b4-a841-4a4c-b8a7-4163237aba46

📥 Commits

Reviewing files that changed from the base of the PR and between d084bdb and b3e6c5b.

📒 Files selected for processing (2)
  • handler.go
  • rotate_test.go

Comment thread handler.go
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • handler.go

Commit: 99aabb482bc98dc298c0870b18e8b8524b4f61b5

The changes have been pushed to the fix/issue-135-thumbnail-orientation branch.

Time taken: 5m 58s

Fixed 1 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment thread handler.go Outdated
Comment thread handler.go
Comment thread handler.go
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
amemya and others added 2 commits July 9, 2026 02:47
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@amemya

amemya commented Jul 8, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@amemya amemya merged commit 0f0982d into main Jul 8, 2026
5 checks passed
@amemya amemya deleted the fix/issue-135-thumbnail-orientation branch July 8, 2026 18:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

縦画像でもフィルムストリップで横に表示される

2 participants