<!-- Generated by SpecStory -->

# 提取图片宽高时考虑竖拍 (2025-05-28 22:24:57)

_**User**_

提取 metadata 中的 width 和 height 时需要根据 exif 判断时候是竖拍的

---

_**Assistant**_

我需要查看代码中如何处理图片的方向信息，特别是EXIF中的Orientation字段，来确保width和height的提取考虑了图片的实际方向。

---

<details>
            <summary>Searched codebase "EXIF orientation metadata width height" • **25** results</summary>
        
| File | Lines |
|------|-------|
| `src/data/photos-manifest.json` | L2474-2545 |
| `src/components/ui/photo-viewer/ExifPanel.tsx` | L725-775 |
| `src/data/photos.ts` | L34-78 |
| `src/components/ui/photo-viewer/ExifPanel.tsx` | L775-817 |
| `src/data/photos-manifest.json` | L3027-3093 |
| `src/types/photo.ts` | L1-20 |
| `src/components/ui/photo-viewer/ExifPanel.tsx` | L666-725 |
| `src/modules/gallery/PhotoMasonryItem.tsx` | L1-80 |
| `src/data/photos-manifest.json` | L3140-3208 |
| `src/data/photos-manifest.json` | L1346-1417 |
| `src/data/photos-manifest.json` | L354-398 |
| `src/data/photos-manifest.json` | L2026-2097 |
| `src/data/photos-manifest.json` | L1106-1177 |
| `src/data/photos-manifest.json` | L986-1057 |
| `src/components/ui/photo-viewer/ExifPanel.tsx` | L481-528 |
| `src/data/photos-manifest.json` | L2907-2978 |
| `src/data/photos-manifest.json` | L2598-2639 |
| `src/components/ui/photo-viewer/ExifPanel.tsx` | L60-92 |
| `src/data/photos-manifest.json` | L1226-1297 |
| `src/data/photos-manifest.json` | L2146-2217 |
| `src/data/photos-manifest.json` | L1714-1746 |
| `src/data/photos-manifest.json` | L1626-1658 |
| `src/data/photos-manifest.json` | L1538-1570 |
| `src/data/photos-manifest.json` | L1466-1538 |
| `src/data/photos-manifest.json` | L1802-1834 |

</details>

---

从搜索结果中，我可以看到在EXIF数据中有`Orientation`字段，但代码中没有正确处理图片的方向信息。让我查看当前如何获取图片元数据的函数：

---

Read file: scripts/build-manifest.ts

---

现在让我查看当前是如何使用这些元数据的：

---

<details>
            <summary>Grep search for "getImageMetadata" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/scripts/build-manifest.ts` | L270 | `async function getImageMetadata(` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/scripts/build-manifest.ts` | L618 | `const metadata = await getImageMetadata(imageBuffer)` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/scripts/build-manifest.ts` | L270 | `async function getImageMetadata(` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/scripts/build-manifest.ts` | L618 | `const metadata = await getImageMetadata(imageBuffer)` |

</details>

---

现在我需要修改`getImageMetadata`函数，使其能够根据EXIF中的Orientation信息正确处理图片的宽度和高度。让我查看更多相关代码：

---

Read file: scripts/build-manifest.ts

---

现在我理解了代码的结构。问题在于`getImageMetadata`函数只是简单地返回了Sharp库提供的原始宽高数据，没有考虑EXIF中的Orientation信息。我需要修改这个函数，让它能够根据EXIF的Orientation字段正确处理图片的宽高。

让我修改这个函数：

---

```diff
        return null
      }
+ 
+     let width = metadata.width
+     let height = metadata.height
+ 
+     // 根据 EXIF Orientation 信息调整宽高
+     // Orientation 值说明：
+     // 1: 正常 (0°)
+     // 2: 水平翻转
+     // 3: 旋转 180°
+     // 4: 垂直翻转
+     // 5: 水平翻转 + 逆时针旋转 90°
+     // 6: 顺时针旋转 90° (竖拍)
+     // 7: 水平翻转 + 顺时针旋转 90°
+     // 8: 逆时针旋转 90° (竖拍)
+     const orientation = metadata.orientation
+     if (orientation === 6 || orientation === 8) {
+       // 对于竖拍的图片，需要交换宽高
+       [width, height] = [height, width]
+       console.info(`检测到竖拍图片 (orientation: ${orientation})，交换宽高: ${width}x${height}`)
+     }
  
      return {
-       width: metadata.width,
-       height: metadata.height,
+       width,
+       height,
        format: metadata.format,
      }
```

---

现在我还需要确保在处理图片时，Sharp库也能正确处理orientation信息。我需要检查一下在图片处理流程中是否有其他地方需要应用同样的逻辑，特别是在生成缩略图和blurhash的地方：

---

Read file: scripts/build-manifest.ts

---

我看到在`generateBlurhash`和`generateThumbnail`函数中已经使用了`.rotate()`方法，这个方法会自动根据EXIF的Orientation信息旋转图片，这很好。

但是还有一个问题，我需要确保也有考虑到orientation为5和7的情况，这些也会导致宽高交换。让我更新一下代码：

---

```diff
      // 3: 旋转 180°
      // 4: 垂直翻转
-     // 5: 水平翻转 + 逆时针旋转 90°
-     // 6: 顺时针旋转 90° (竖拍)
-     // 7: 水平翻转 + 顺时针旋转 90°
-     // 8: 逆时针旋转 90° (竖拍)
+     // 5: 水平翻转 + 逆时针旋转 90° (宽高交换)
+     // 6: 顺时针旋转 90° (竖拍，宽高交换)
+     // 7: 水平翻转 + 顺时针旋转 90° (宽高交换)
+     // 8: 逆时针旋转 90° (竖拍，宽高交换)
      const { orientation } = metadata
-     if (orientation === 6 || orientation === 8) {
-       // 对于竖拍的图片，需要交换宽高
+     if (orientation === 5 || orientation === 6 || orientation === 7 || orientation === 8) {
+       // 对于需要旋转90°的图片，需要交换宽高
        ;[width, height] = [height, width]
        console.info(
-         `检测到竖拍图片 (orientation: ${orientation})，交换宽高: ${width}x${height}`,
+         `检测到需要旋转90°的图片 (orientation: ${orientation})，交换宽高: ${width}x${height}`,
        )
      }
```

---

现在，修改已经完成。让我检查一下修改是否正确应用了：

---

Read file: scripts/build-manifest.ts

---

完美！修改已经成功应用。现在`getImageMetadata`函数会正确处理EXIF中的Orientation信息，对于需要旋转90度的图片（orientation值为5、6、7、8），会自动交换宽度和高度的值。

让我总结一下所做的修改：

## 修改总结

我成功修改了`scripts/build-manifest.ts`文件中的`getImageMetadata`函数，使其能够根据EXIF中的Orientation信息正确处理图片的宽高：

### 主要改动：

1. **添加了Orientation处理逻辑**：
   - 读取图片的EXIF Orientation信息
   - 对于orientation值为5、6、7、8的图片（这些值表示图片需要旋转90°），会交换宽度和高度的值
   - 添加了详细的注释说明每个orientation值的含义

2. **具体的Orientation值含义**：
   - 1: 正常 (0°)
   - 2: 水平翻转
   - 3: 旋转 180°
   - 4: 垂直翻转
   - 5: 水平翻转 + 逆时针旋转 90° (宽高交换)
   - 6: 顺时针旋转 90° (竖拍，宽高交换)
   - 7: 水平翻转 + 顺时针旋转 90° (宽高交换)
   - 8: 逆时针旋转 90° (竖拍，宽高交换)

3. **保持了与现有代码的兼容性**：
   - `generateBlurhash`和`generateThumbnail`函数已经使用了`.rotate()`方法，可以自动处理orientation
   - 新的逻辑只是确保在manifest中记录的宽高值是正确的

### 效果：

现在当处理竖拍的照片时，manifest文件中记录的宽高值会正确反映图片的实际显示尺寸，而不是原始的文件尺寸。这样可以确保在前端显示时能够正确计算宽高比和布局。

---

