Fix: 圧縮#12
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Pull request overview
This PR updates the frontend uploader’s image preprocessing capabilities by expanding which image MIME types are considered “image-editable” and by adjusting the resolution limits used for image compression presets.
Changes:
- Expand
IMAGE_EDITING_SUPPORTED_TYPESto include AVIF/GIF/BMP/APNG. - Adjust compression preset max dimensions for levels 2–4 (e.g., level 2 up to 4096×4096).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 'image/avif', | ||
| 'image/gif', | ||
| 'image/bmp', | ||
| 'image/apng', |
There was a problem hiding this comment.
Adding image/gif/image/apng to IMAGE_EDITING_SUPPORTED_TYPES makes these files eligible for watermark/image-frame preprocessing and the edit menu. The watermark/frame pipeline renders via canvas and exports image/png, which will silently flatten animated images and change the file format; with a default watermark preset this can happen automatically on upload. Consider excluding animated formats from this list, or explicitly detect animation up-front and skip/disable watermark/frame/edit operations (or warn), and ensure uploadName/extension is updated when the output mime type changes.
| 'image/apng', |
| 'image/bmp', | ||
| 'image/apng', |
There was a problem hiding this comment.
image/bmp and image/apng are now treated as editable/preprocessed types, but they are not included in THUMBNAIL_SUPPORTED_TYPES, so newly added BMP/APNG uploads won’t get a preview thumbnail (thumbnail stays null) until they’re converted to a supported type. If previews are expected, add these mime types to THUMBNAIL_SUPPORTED_TYPES (or provide a fallback thumbnail strategy).
|
@codex レビューして |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fe39a14517
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| 'image/jpeg', | ||
| 'image/png', | ||
| 'image/webp', | ||
| 'image/avif', |
There was a problem hiding this comment.
Exclude AVIF from lossy image-editing path
Adding image/avif to IMAGE_EDITING_SUPPORTED_TYPES routes AVIF files through preprocessForImage, but the animation guard there relies on is-file-animated, which only detects GIF/PNG/WebP. For animated AVIF uploads (with non-zero compression, including the default level 1), the code will treat them as non-animated and re-encode from createImageBitmap, effectively uploading a single-frame still image and losing animation.
Useful? React with 👍 / 👎.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@codex レビューして |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 484f76ece3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // ISOBMFF の ftyp ボックスを読み、AVIF アニメーション用ブランド `avis` の有無で判定する。 | ||
| // is-file-animated は GIF/PNG/WebP しか判定できないため、AVIF を別途扱う必要がある。 | ||
| async function isAnimatedAvif(file: Blob): Promise<boolean> { | ||
| const headerSize = Math.min(file.size, 64); |
There was a problem hiding this comment.
Parse full
ftyp brands before classifying AVIF as static
The AVIF animation check only reads the first 64 bytes, so any valid file whose ftyp box is larger and places avis later in compatible_brands will be misclassified as non-animated. In that case use-uploader will still run watermark/frame/compression paths and collapse an animated AVIF into a single-frame image. Since boxSize is already parsed, this should read enough bytes to cover the whole ftyp box (or at least all declared brands) instead of hard-capping at 64 bytes.
Useful? React with 👍 / 👎.
64バイト固定読みでは compatible_brands に avis が後方にある場合に 誤判定するため、boxSize に基づいてボックス全体を読み直す。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| @@ -630,7 +636,7 @@ export function useUploader(options: { | |||
|
|
|||
| let preprocessedFile: Blob | File = item.file; | |||
|
|
|||
| const needsWatermark = item.watermarkLayers != null && IMAGE_EDITING_SUPPORTED_TYPES.includes(preprocessedFile.type) && $i.policies.watermarkAvailable; | |||
| const needsWatermark = item.watermarkLayers != null && IMAGE_EDITING_SUPPORTED_TYPES.includes(preprocessedFile.type) && $i.policies.watermarkAvailable && !(await isFileAnimated(preprocessedFile)); | |||
| 'image/gif', | ||
| 'image/bmp', | ||
| 'image/apng', |
| const headerBuffer = await file.slice(0, 8).arrayBuffer(); | ||
| const headerView = new DataView(headerBuffer); | ||
| const decoder = new TextDecoder('ascii'); | ||
|
|
||
| if (decoder.decode(new Uint8Array(headerBuffer, 4, 4)) !== 'ftyp') return false; | ||
|
|
||
| let boxSize = headerView.getUint32(0); | ||
| // boxSize === 0: ボックスがファイル末尾まで続く / boxSize === 1: 直後に 64bit largesize(ftyp ではまず存在しない) | ||
| if (boxSize === 0 || boxSize === 1) boxSize = file.size; | ||
| const readSize = Math.min(boxSize, file.size, FTYP_READ_CAP); | ||
| if (readSize < 12) return false; | ||
|
|
||
| const buffer = await file.slice(0, readSize).arrayBuffer(); | ||
| const bytes = new Uint8Array(buffer); | ||
|
|
||
| if (decoder.decode(bytes.subarray(8, 12)) === 'avis') return true; | ||
|
|
||
| for (let offset = 16; offset + 4 <= readSize; offset += 4) { |
| export async function isFileAnimated(file: Blob): Promise<boolean> { | ||
| if (file.type === 'image/avif') { | ||
| return isAnimatedAvif(file); | ||
| } | ||
| return isAnimated(file); | ||
| } |
|
@codex レビューして |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a059fbb74a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| 'image/png', | ||
| 'image/webp', | ||
| 'image/avif', | ||
| 'image/gif', |
There was a problem hiding this comment.
Exclude animated GIFs from image-editing type whitelist
Adding image/gif to IMAGE_EDITING_SUPPORTED_TYPES makes animated GIFs eligible for the generic edit menu (cropImageFile and image effector), but those flows render through canvas and output a single-frame blob, so animation is silently lost after editing. This is a regression from the previous behavior (GIFs were not in the editing whitelist) and will affect users who try to crop/effect animated GIF uploads.
Useful? React with 👍 / 👎.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
isFileAnimated を 3 回呼んでいた箇所を 1 回化。アニメ画像は createImageBitmap も含めて前処理を全スキップし、設定済みの watermarkLayers/imageFrameParams をクリアする。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
canvas 経由の処理は 1 フレーム化されるためアニメ画像では効果がない。 設定だけが残り適用されない混乱を避けるため、メニュー自体を出さない。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
boxSize === 1 のとき直後の 64bit largesize を読み、brands の オフセットを 16/24 起点に調整する。ftyp 範囲外を走査しなくなるため 無関係な領域に `avis` が現れた場合の誤判定を防ぐ。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
major_brand/compatible_brands の avis 検出、ftyp が 64 バイトを 超えるケース、64bit largesize、非 ftyp ヘッダー、短すぎる入力を カバーする。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
No description provided.