14,962
edits
| Line 35: | Line 35: | ||
Or implement the file overwrite control directly in your PHP script logic. | Or implement the file overwrite control directly in your PHP script logic. | ||
== FFmpeg Fails to Decode Large JPEG Images == | |||
'''Error condition''': | |||
When processing high-resolution JPEG images, FFmpeg reports the image size as invalid and aborts decoding entirely. | |||
Original command: | |||
<pre> | |||
ffmpeg -i "image.jpg" -vf scale=2000:-1 output.jpg | |||
</pre> | |||
Error output: | |||
<pre> | |||
[mjpeg @ 0x...] [IMGUTILS @ 0x...] Picture size 25600x14400 is invalid | |||
[image2 @ 0x...] Could not find codec parameters for stream 0: unspecified size | |||
Conversion failed! | |||
</pre> | |||
Root cause: | |||
FFmpeg's internal function `av_image_check_size2()` (in `libavutil/imgutils.c`) validates image dimensions before decoding begins — before the pixel format (`pix_fmt`) is known. Without `pix_fmt`, FFmpeg assumes the worst-case bytes-per-pixel (bpp = 6), then checks: | |||
<pre> | |||
stride * (height + 128) >= INT_MAX // INT_MAX = 2,147,483,647 | |||
</pre> | |||
For a 25600×14400 image with bpp = 6: | |||
<pre> | |||
stride = 25600 × 6 = 153,600 | |||
result = 153,600 × (14400 + 128) = 2,231,500,800 → exceeds INT_MAX ✗ | |||
</pre> | |||
The actual pixel format of the image is `yuvj420p` (bpp = 1.5), which would pass the check: | |||
<pre> | |||
stride = 25600 × 1.5 = 38,400 | |||
result = 38,400 × (14400 + 128) = 557,875,200 → within INT_MAX ✓ | |||
</pre> | |||
FFmpeg cannot read `pix_fmt` before running the size check, so the image is incorrectly rejected. Passing `-vcodec mjpeg` or `-pix_fmt` does not help — the check runs before any codec parameters take effect. | |||
'''Solution''': | |||
Use ImageMagick instead of FFmpeg for large JPEG files: | |||
<pre> | |||
magick "image.jpg" -resize 2000x2000\> "output.jpg" | |||
</pre> | |||
The `\>` flag shrinks only — no enlargement if the image is already smaller than the target. | |||
Or use Pillow to pre-scale before passing to FFmpeg: | |||
<pre> | |||
python3 -c " | |||
from PIL import Image | |||
Image.MAX_IMAGE_PIXELS = None | |||
img = Image.open('image.jpg') | |||
img.thumbnail((4000, 4000)) | |||
img.save('temp.jpg', quality=90) | |||
" && ffmpeg -i temp.jpg -vf scale=2000:-1 output.jpg | |||
</pre> | |||
Note: `Image.MAX_IMAGE_PIXELS = None` disables Pillow's decompression bomb protection. Only use this for trusted image sources.<ref>[https://github.com/GyanD/codexffmpeg/issues/114 ffmpeg & ffprobe: large JPEG error (Picture size 14106x19746 is invalid) · Issue #114 · GyanD/codexffmpeg]</ref><ref>[https://trac.ffmpeg.org/ticket/8030 #8030 (IMGUTILS, failure handling big images) – FFmpeg]</ref> | |||
== Further readings == | == Further readings == | ||