JPEG saved with keep_rgb=True and dpi reopens with incorrect colors
メンテナーはふだん 1 日以内に返信
評価
調査の方向性
Start with the JPEG encoder path in src/libImaging/JpegEncode.c and the decoder’s color-space selection; the issue links both relevant code locations and cites libjpeg-turbo’s default selection. Compare JPEGs saved with and without DPI and keep_rgb=True, then run the reproducer in the issue. Done means both files reopen with approximately red pixels while retaining the requested DPI behavior; pull request #10345 is already open.
索引モデルが issue の本文から書いたものです。
説明
What did you do?
Saved the same RGB image to JPEG with keep_rgb=True, once with DPI and once without it, then reopened both files:
from io import BytesIO
from PIL import Image
image = Image.new("RGB", (16, 16), (255, 0, 0))
for dpi in (None, (72, 72)):
out = BytesIO()
options = {"keep_rgb": True, "quality": 100, "subsampling": 0}
if dpi is not None:
options["dpi"] = dpi
image.save(out, "JPEG", **options)
out.seek(0)
with Image.open(out) as reopened:
print(dpi, reopened.getpixel((0, 0)))
What did you expect to happen?
Both images should reopen approximately red. Setting DPI should not visibly change the colors.
What actually happened?
On both installations below, the output was:
None (255, 0, 0)
(72, 72) (76, 255, 28)
The DPI version contains both a JFIF APP0 marker and an Adobe APP14 marker with transform 0; the version without DPI contains only the Adobe marker. As a diagnostic, removing the JFIF marker from the generated bytes made Pillow reopen the pixel as (255, 0, 0), but also removed the DPI. I don't know whether the right fix is in the writer, the reader, or both.
FFmpeg 9.0.2 decodes both generated JPEGs as (255, 0, 0) on the same machine. This suggests a difference in decoding the DPI version; I have not isolated the responsible layer.
The generated file has component IDs R, G and B. As a diagnostic, forcing the low-level JPEG decoder input mode to RGB also restores the expected red in both Pillow versions.
Looking at libjpeg-turbo 3.2.0, its default color-space selection gives the JFIF marker precedence over Adobe APP14, selecting YCbCr when both are present. Pillow enables JFIF when both DPI values are positive.
#7679 notes that setting DPI forces JFIF even for non-JFIF color spaces. The JPEG encoder source is identical between the 13.0.0 tag and current main, although I haven't built main to reproduce this there.
What are your OS, Python and Pillow versions?
- Windows 11, Python 3.15.2, Pillow 13.0.0, libjpeg-turbo 3.2.0.
- Also reproduced with Python 3.12.14, Pillow 12.3.0, libjpeg-turbo 3.1.4.1.
Reproducer and investigation assisted by Codex.
- 主要言語
- Python
- スター
- 13.9k
- フォーク
- 2.6k
- 平均マージ
- 1日 3時間
- マージ済み PR(30日)
- 174
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
python-pillow/Pillow のほかの issue
-
Warn that pre-applying arabic_reshaper + python-bidi corrupts text on a Raqm build対応中かも @Syamjith-NK が 63 日前に担当しました。 オープンDocumentation Font Rendering PNG Third Party Framework
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
python-pillow/Pillow#9907 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
Image.putpixel incorrectly labels supported arguments in type annotations対応中かも @radarhere が 191 日前に担当しました。 オープンPNG
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
python-pillow/Pillow#9584 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
python-pillow/Pillow#10362 ·
メンテナーはふだん 1 日以内に返信
-
`ImageDraw.arc()` segfaults on a tuple subclass whose `__len__` is too large対応中かも @Parsiffall1 が 1 日前に担当しました。 オープン
難易度 4/5 1〜2日 初心者へのやさしさ 58/100
python-pillow/Pillow#10358 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
JPEG dpi read from EXIF uses XResolution for both axes再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープンAwaiting OP Action
難易度 2/5 1〜3時間 初心者へのやさしさ 20/100
python-pillow/Pillow#10331 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
python-pillow/Pillow の issue をすべて見る
似ている issue
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
NousResearch/hermes-agent#147104 ·
メンテナーはふだん 1 日以内に返信
-
premises-missing
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
WingedGuardian/GENesis-AGI#3801 ·
メンテナーはふだん 1 日以内に返信
-
[oblt-aw][autodoc] Document new required `shared-org-key` input for `obs-aw-dependency-review`対応中かも @github-actions が今日担当しました。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 90/100
メンテナーはふだん 1 日以内に返信
-
bot-triaged module: inductor oncall: pt2 topic: fuzzer triaged
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 4 日以内に返信