codecov[bot]: # [Codecov](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=h1) Report
> Merging [#4455](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=desc) into [master](https://codecov.io/gh/python-pillow/Pillow/commit/1c1ad65a9646f73d80ce8f77894a447b03f203a6?src=pr&el=desc) will **decrease** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/python-pillow/Pillow/pull/4455/graphs/tree.svg?width=650&token=OstRzgUJ8y&height=150&src=pr)](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #4455      +/-   ##
==========================================
- Coverage   89.47%   89.46%   -0.01%     
==========================================
  Files         324      325       +1     
  Lines       39995    39999       +4     
  Branches     3198     3198              
==========================================
+ Hits        35785    35787       +2     
- Misses       4207     4209       +2     
  Partials        3        3
```

| Flag | Coverage Δ | |
|---|---|---|
| #AppVeyor | `89.29% <100%> (+0.45%)` | :arrow_up: |
| #GHA_Docker | `85.79% <100%> (-0.07%)` | :arrow_down: |
| #GHA_Ubuntu | `87.86% <100%> (-0.05%)` | :arrow_down: |
| #GHA_Windows | `89.92% <100%> (-0.94%)` | :arrow_down: |
| #GHA_macOS | `86.82% <100%> (-0.05%)` | :arrow_down: |
| #TravisCI | `85.85% <100%> (ø)` | :arrow_up: |

| [Impacted Files](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/PIL/JpegImagePlugin.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9KcGVnSW1hZ2VQbHVnaW4ucHk=) | `90.32% <100%> (+0.02%)` | :arrow_up: |
| [Tests/test\_file\_jpeg.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-VGVzdHMvdGVzdF9maWxlX2pwZWcucHk=) | `100% <100%> (ø)` | :arrow_up: |
| [src/\_webp.c](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL193ZWJwLmM=) | `74.43% <0%> (-4.02%)` | :arrow_down: |
| [src/PIL/\_\_main\_\_.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9fX21haW5fXy5weQ==) | `100% <0%> (ø)` | |
| [src/PIL/WebPImagePlugin.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9XZWJQSW1hZ2VQbHVnaW4ucHk=) | `94.73% <0%> (+0.95%)` | :arrow_up: |
| [Tests/test\_file\_icns.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-VGVzdHMvdGVzdF9maWxlX2ljbnMucHk=) | `100% <0%> (+1.25%)` | :arrow_up: |
| [src/PIL/ImageFont.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9JbWFnZUZvbnQucHk=) | `96.09% <0%> (+1.46%)` | :arrow_up: |
| [Tests/test\_file\_webp.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-VGVzdHMvdGVzdF9maWxlX3dlYnAucHk=) | `100% <0%> (+2%)` | :arrow_up: |
| [src/PIL/features.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9mZWF0dXJlcy5weQ==) | `97.7% <0%> (+2.29%)` | :arrow_up: |
| [Tests/test\_features.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-VGVzdHMvdGVzdF9mZWF0dXJlcy5weQ==) | `100% <0%> (+3.33%)` | :arrow_up: |
| ... and [1 more](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=footer). Last update [1c1ad65...84e37f7](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

codecov[bot]: # [Codecov](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=h1) Report
> Merging [#4455](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=desc) into [master](https://codecov.io/gh/python-pillow/Pillow/commit/e9a6149839ca9d33b01350a5549b46c5fba86d0b?src=pr&el=desc) will **increase** coverage by `0.2%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/python-pillow/Pillow/pull/4455/graphs/tree.svg?width=650&token=OstRzgUJ8y&height=150&src=pr)](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=tree)

```diff
@@            Coverage Diff            @@
##           master    #4455     +/-   ##
=========================================
+ Coverage   89.26%   89.46%   +0.2%     
=========================================
  Files         324      325      +1     
  Lines       39924    39999     +75     
  Branches        0     3198   +3198     
=========================================
+ Hits        35640    35787    +147     
+ Misses       4284     4209     -75     
- Partials        0        3      +3
```

| Flag | Coverage Δ | |
|---|---|---|
| #AppVeyor | `89.29% <100%> (?)` | |
| #GHA_Docker | `85.79% <100%> (-0.07%)` | :arrow_down: |
| #GHA_Ubuntu | `87.86% <100%> (-0.05%)` | :arrow_down: |
| #GHA_Windows | `89.92% <100%> (-0.94%)` | :arrow_down: |
| #GHA_macOS | `86.82% <100%> (-0.05%)` | :arrow_down: |
| #TravisCI | `85.85% <100%> (?)` | |

| [Impacted Files](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/PIL/JpegImagePlugin.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9KcGVnSW1hZ2VQbHVnaW4ucHk=) | `90.32% <100%> (-1.12%)` | :arrow_down: |
| [Tests/test\_file\_jpeg.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-VGVzdHMvdGVzdF9maWxlX2pwZWcucHk=) | `100% <100%> (ø)` | :arrow_up: |
| [src/\_webp.c](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL193ZWJwLmM=) | `74.43% <0%> (-4.61%)` | :arrow_down: |
| [src/PIL/BmpImagePlugin.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9CbXBJbWFnZVBsdWdpbi5weQ==) | `94.52% <0%> (-3.36%)` | :arrow_down: |
| [src/PIL/ImImagePlugin.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9JbUltYWdlUGx1Z2luLnB5) | `80.44% <0%> (-1.84%)` | :arrow_down: |
| [Tests/test\_bmp\_reference.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-VGVzdHMvdGVzdF9ibXBfcmVmZXJlbmNlLnB5) | `94% <0%> (-1.84%)` | :arrow_down: |
| [src/PIL/GifImagePlugin.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9HaWZJbWFnZVBsdWdpbi5weQ==) | `96.06% <0%> (-1.71%)` | :arrow_down: |
| [src/PIL/PsdImagePlugin.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9Qc2RJbWFnZVBsdWdpbi5weQ==) | `91.84% <0%> (-1.53%)` | :arrow_down: |
| [src/PIL/IcoImagePlugin.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9JY29JbWFnZVBsdWdpbi5weQ==) | `97.14% <0%> (-1.41%)` | :arrow_down: |
| [src/PIL/ImageFile.py](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree#diff-c3JjL1BJTC9JbWFnZUZpbGUucHk=) | `91.78% <0%> (-1.37%)` | :arrow_down: |
| ... and [63 more](https://codecov.io/gh/python-pillow/Pillow/pull/4455/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=footer). Last update [e9a6149...51b3708](https://codecov.io/gh/python-pillow/Pillow/pull/4455?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst
index 7ce685ed2..18f547a49 100644
--- a/docs/handbook/image-file-formats.rst
+++ b/docs/handbook/image-file-formats.rst
@@ -298,6 +298,11 @@ The :py:meth:`~PIL.Image.Image.open` method may set the following
 **exif**
     Raw EXIF data from the image.
 
+**comment**
+    A comment about the image.
+
+    .. versionadded:: 7.1.0
+
 
 The :py:meth:`~PIL.Image.Image.save` method supports the following options:
 
diff --git a/docs/releasenotes/7.1.0.rst b/docs/releasenotes/7.1.0.rst
index 1369177d2..e3bc107dd 100644
--- a/docs/releasenotes/7.1.0.rst
+++ b/docs/releasenotes/7.1.0.rst
@@ -18,6 +18,15 @@ been resolved.
     im = Image.open("hopper.jpg")
     im.save("out.jpg", quality=0)
 
+API Additions
+=============
+
+Reading JPEG comments
+^^^^^^^^^^^^^^^^^^^^^
+
+When opening a JPEG image, the comment may now be read into
+:py:attr:`~PIL.Image.Image.info`.
+
 Other Changes
 =============
 
diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py
index 229eac214..2aa029efb 100644
--- a/src/PIL/JpegImagePlugin.py
+++ b/src/PIL/JpegImagePlugin.py
@@ -176,6 +176,7 @@ def COM(self, marker):
     n = i16(self.fp.read(2)) - 2
     s = ImageFile._safe_read(self.fp, n)
 
+    self.info["comment"] = s
     self.app["COM"] = s  # compatibility
     self.applist.append(("COM", s))
 

PIL cannot read JPEG comment
### What did you do?
I want PIL to read the JPEG comment (marker: 0xFF 0xFE).  
  
I took an image with an attached JPEG comment - verified with exiftools & IrfanView to exist.

```python
from PIL import Image, JpegImagePlugin
pic = Image.open(<path_to_pic_with_JPEG_comment>)
print(pic.info)
```

### What did you expect to happen?
Show the JPEG comment in the dict.

### What actually happened?
> {'jfif': 257, 'jfif_version': (1, 1), 'dpi': (96, 96), 'jfif_unit': 1, 'jfif_density': (96, 96), 'exif': b'...'}


### What are your OS, Python and Pillow versions?

* OS: W7x64
* Python: Python 3.8.1 x64
* Pillow: Pillow           7.0.0

I cannot attach an image via github ("Something went really wrong, ..."), so here is the file (5.61 KiB) (I downloaded it and verified it's byte-identical to the uploaded one): [![jpeg-comment-test.jpg](https://i.postimg.cc/nrz1xV1r/jpeg-comment-test.jpg)](https://postimg.cc/BLrFc0kf)
diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py
index f13536d58..330451228 100644
--- a/Tests/test_file_jpeg.py
+++ b/Tests/test_file_jpeg.py
@@ -60,6 +60,8 @@ class TestFileJpeg:
             )
             assert len(im.applist) == 2
 
+            assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0\x00"
+
     def test_cmyk(self):
         # Test CMYK handling.  Thanks to Tim and Charlie for test data,
         # Michael for getting me to look one more time.

pip install -e .[dev]
parse_log_pytest
requirements.txt
apt-get update apt-get install -y gcc libjpeg-dev zlib1g-dev libtiff5-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev libharfbuzz-dev libfribidi-dev libxcb1-dev
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.16
babel==2.17.0
black==25.1.0
blessed==1.20.0
build==1.2.2.post1
certifi==2025.1.31
charset-normalizer==3.4.1
check-manifest==0.50
click==8.1.8
coverage==7.8.0
docutils==0.21.2
exceptiongroup==1.2.2
idna==3.10
imagesize==1.4.1
importlib_metadata==8.6.1
iniconfig==2.1.0
jarn.viewdoc==2.7
Jinja2==3.1.6
MarkupSafe==3.0.2
mypy-extensions==1.0.0
olefile==0.47
packaging==24.2
pathspec==0.12.1
-e git+https://github.com/python-pillow/Pillow.git@e9a6149839ca9d33b01350a5549b46c5fba86d0b#egg=Pillow
platformdirs==4.3.7
pluggy==1.5.0
pycodestyle==2.13.0
pyflakes==3.3.1
Pygments==2.19.1
pyproject_hooks==1.2.0
pyroma==4.2
pytest==8.3.5
pytest-cov==6.0.0
requests==2.32.3
six==1.17.0
snowballstemmer==2.2.0
Sphinx==7.4.7
sphinx-rtd-theme==3.0.2
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
tomli==2.2.1
trove-classifiers==2025.3.19.19
typing_extensions==4.13.0
urllib3==2.3.0
wcwidth==0.2.13
zipp==3.21.0

name: Pillow
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.16
      - babel==2.17.0
      - black==25.1.0
      - blessed==1.20.0
      - build==1.2.2.post1
      - certifi==2025.1.31
      - charset-normalizer==3.4.1
      - check-manifest==0.50
      - click==8.1.8
      - coverage==7.8.0
      - docutils==0.21.2
      - exceptiongroup==1.2.2
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - jarn-viewdoc==2.7
      - jinja2==3.1.6
      - markupsafe==3.0.2
      - mypy-extensions==1.0.0
      - olefile==0.47
      - packaging==24.2
      - pathspec==0.12.1
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pyflakes==3.3.1
      - pygments==2.19.1
      - pyproject-hooks==1.2.0
      - pyroma==4.2
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - requests==2.32.3
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==7.4.7
      - sphinx-rtd-theme==3.0.2
      - sphinxcontrib-applehelp==2.0.0
      - sphinxcontrib-devhelp==2.0.0
      - sphinxcontrib-htmlhelp==2.1.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==2.0.0
      - sphinxcontrib-serializinghtml==2.0.0
      - tomli==2.2.1
      - trove-classifiers==2025.3.19.19
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - wcwidth==0.2.13
      - zipp==3.21.0
prefix: /opt/conda/envs/Pillow

Tests/test_file_jpeg.py::TestFileJpeg::test_app
Tests/test_file_jpeg.py::TestFileJpeg::test_sanity Tests/test_file_jpeg.py::TestFileJpeg::test_cmyk Tests/test_file_jpeg.py::TestFileJpeg::test_dpi Tests/test_file_jpeg.py::TestFileJpeg::test_icc Tests/test_file_jpeg.py::TestFileJpeg::test_icc_big Tests/test_file_jpeg.py::TestFileJpeg::test_large_icc_meta Tests/test_file_jpeg.py::TestFileJpeg::test_optimize Tests/test_file_jpeg.py::TestFileJpeg::test_optimize_large_buffer Tests/test_file_jpeg.py::TestFileJpeg::test_progressive Tests/test_file_jpeg.py::TestFileJpeg::test_progressive_large_buffer Tests/test_file_jpeg.py::TestFileJpeg::test_progressive_large_buffer_highest_quality Tests/test_file_jpeg.py::TestFileJpeg::test_progressive_cmyk_buffer Tests/test_file_jpeg.py::TestFileJpeg::test_large_exif Tests/test_file_jpeg.py::TestFileJpeg::test_exif_typeerror Tests/test_file_jpeg.py::TestFileJpeg::test_exif_gps Tests/test_file_jpeg.py::TestFileJpeg::test_exif_rollback Tests/test_file_jpeg.py::TestFileJpeg::test_exif_gps_typeerror Tests/test_file_jpeg.py::TestFileJpeg::test_progressive_compat Tests/test_file_jpeg.py::TestFileJpeg::test_quality Tests/test_file_jpeg.py::TestFileJpeg::test_smooth Tests/test_file_jpeg.py::TestFileJpeg::test_subsampling Tests/test_file_jpeg.py::TestFileJpeg::test_exif Tests/test_file_jpeg.py::TestFileJpeg::test_mp Tests/test_file_jpeg.py::TestFileJpeg::test_quality_keep Tests/test_file_jpeg.py::TestFileJpeg::test_junk_jpeg_header Tests/test_file_jpeg.py::TestFileJpeg::test_ff00_jpeg_header Tests/test_file_jpeg.py::TestFileJpeg::test_truncated_jpeg_should_read_all_the_data Tests/test_file_jpeg.py::TestFileJpeg::test_truncated_jpeg_throws_IOError Tests/test_file_jpeg.py::TestFileJpeg::test_qtables Tests/test_file_jpeg.py::TestFileJpeg::test_no_duplicate_0x1001_tag Tests/test_file_jpeg.py::TestFileJpeg::test_MAXBLOCK_scaling Tests/test_file_jpeg.py::TestFileJpeg::test_bad_mpo_header Tests/test_file_jpeg.py::TestFileJpeg::test_save_correct_modes Tests/test_file_jpeg.py::TestFileJpeg::test_save_wrong_modes Tests/test_file_jpeg.py::TestFileJpeg::test_save_tiff_with_dpi Tests/test_file_jpeg.py::TestFileJpeg::test_load_dpi_rounding Tests/test_file_jpeg.py::TestFileJpeg::test_save_dpi_rounding Tests/test_file_jpeg.py::TestFileJpeg::test_dpi_tuple_from_exif Tests/test_file_jpeg.py::TestFileJpeg::test_dpi_int_from_exif Tests/test_file_jpeg.py::TestFileJpeg::test_dpi_from_dpcm_exif Tests/test_file_jpeg.py::TestFileJpeg::test_dpi_exif_zero_division Tests/test_file_jpeg.py::TestFileJpeg::test_no_dpi_in_exif Tests/test_file_jpeg.py::TestFileJpeg::test_invalid_exif Tests/test_file_jpeg.py::TestFileJpeg::test_invalid_exif_x_resolution Tests/test_file_jpeg.py::TestFileJpeg::test_ifd_offset_exif Tests/test_file_jpeg.py::TestFileJpeg::test_photoshop Tests/test_file_jpeg.py::TestFileJpeg::test_photoshop_malformed_and_multiple
docs/releasenotes/7.1.0.rst docs/handbook/image-file-formats.rst src/PIL/JpegImagePlugin.py
docs/releasenotes/7.1.0.rst docs/handbook/image-file-formats.rst src/PIL/JpegImagePlugin.py