# 圖片處理流程

本頁說明 `GET /c/img/{path}` 從收到請求到回應的每個步驟，以及各步驟失敗時的行為。

## 流程

| 步驟 | 行為 | 實作 |
|---|---|---|
| 1. 解析參數 | 讀取 `s`／`size`、`w`／`width`、`h`／`height`、`q`／`quality`、`o`／`origin`、`d`／`dark`、`t`／`type`；短名優先 | `GetFromPath.ts` |
| 2. 對應原檔 | `/c/img/` 換成 `storage/image/upload/`，去掉 query string | 同上 |
| 3. PDF／SVG | 副檔名為 `.pdf`／`.svg` 時直接串流原檔並結束 | `streamFile()` |
| 4. 正規化格式 | `type` 不在 `jpeg`／`jpg`／`png`／`avif`／`webp` 時改為 `webp`；`jpeg` 改為 `jpg` | 同上 |
| 5. 組快取路徑 | 依參數組成快取檔名，見 [快取層](/zh/caching#本機快取檔命名) | 同上 |
| 6. 原檔模式 | `o=1` 時串流原檔並結束 | `streamFile()` |
| 7. 快取命中 | 以 `readFileSync` 讀快取檔，成功即回傳 | 同上 |
| 8. 轉檔 | sharp 讀原檔與 metadata，依 [尺寸規則](/zh/api-reference-sizing) `resize()`，再依格式編碼 | sharp |
| 9. 回應與寫入 | 先送出回應，再以 `writeFileSync` 寫入快取檔 | 同上 |

## 編碼設定

| 格式 | sharp 呼叫 | 品質預設 | `Content-Type` |
|---|---|---|---|
| `webp` | `image.webp({ quality })` | `75` | `image/webp` |
| `avif` | `image.avif({ quality })` | `50` | `image/avif` |
| `jpg` | `image.jpeg({ quality })` | `75` | `image/jpeg` |
| `png` | `image.png()` | 不使用 | `image/png` |

品質值經 `parseInt` 後夾在 `0`–`100`。

## 串流原檔

`.pdf`、`.svg` 與 `o=1` 以 `createReadStream`（`highWaterMark` 8 KB）串流，並設 `Transfer-Encoding: chunked`。`o=1` 的 `Content-Type` 依副檔名決定：`.jpg`／`.jpeg` → `image/jpeg`、`.png` → `image/png`、`.webp` → `image/webp`，其他為 `application/octet-stream`。讀取失敗時回 `404` 空內容。

## 失敗處理

| 情境 | 回應 |
|---|---|
| 原檔不存在 | `storage/static/404-light.svg`（`d=1` 時為 `404-dark.svg`），HTTP 狀態 `200` |
| sharp 無法解碼或參數無效（如 `w=abc`） | 同上 |
| 回應標頭 | `Content-Type: image/svg+xml`、`Cache-Control: no-cache`、`Expires: -1`、`Pragma: no-cache` |

## 相關頁面

- 參數清單：[圖片參數](/zh/api-reference-image)
