diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst
index e1138726f..469f89066 100644
--- a/docs/handbook/image-file-formats.rst
+++ b/docs/handbook/image-file-formats.rst
@@ -482,7 +482,7 @@ The :py:meth:`~PIL.Image.Image.open` method sets the following
 
     This key is omitted if the image is not a transparent palette image.
 
-``Open`` also sets ``Image.text`` to a list of the values of the
+``Open`` also sets ``Image.text`` to a dictionary of the values of the
 ``tEXt``, ``zTXt``, and ``iTXt`` chunks of the PNG image. Individual
 compressed chunks are limited to a decompressed size of
 ``PngImagePlugin.MAX_TEXT_CHUNK``, by default 1MB, to prevent
diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py
index f780f811a..dcd4b437f 100644
--- a/src/PIL/PngImagePlugin.py
+++ b/src/PIL/PngImagePlugin.py
@@ -579,7 +579,7 @@ class PngImageFile(ImageFile.ImageFile):
         self.mode = self.png.im_mode
         self._size = self.png.im_size
         self.info = self.png.im_info
-        self.text = self.png.im_text  # experimental
+        self._text = None
         self.tile = self.png.im_tile
 
         if self.png.im_palette:
@@ -588,6 +588,15 @@ class PngImageFile(ImageFile.ImageFile):
 
         self.__idat = length  # used by load_read()
 
+    @property
+    def text(self):
+        # experimental
+        if self._text is None:
+            # iTxt, tEXt and zTXt chunks may appear at the end of the file
+            # So load the file to ensure that they are read
+            self.load()
+        return self._text
+
     def verify(self):
         "Verify PNG file"
 
@@ -640,7 +649,22 @@ class PngImageFile(ImageFile.ImageFile):
 
     def load_end(self):
         "internal: finished reading image data"
+        while True:
+            self.fp.read(4)  # CRC
+
+            try:
+                cid, pos, length = self.png.read()
+            except (struct.error, SyntaxError):
+                break
+
+            if cid == b"IEND":
+                break
 
+            try:
+                self.png.call(cid, pos, length)
+            except UnicodeDecodeError:
+                break
+        self._text = self.png.im_text
         self.png.close()
         self.png = None
 

Image.open not populating Image.text attribute for PNG files
[Documentation for the PNG file format](http://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html#png) states that the `Image.open()` function populates the `text` attribute of the image object with strings from the tEXt, zTxT, and other chunks (it says as a 'list' but it seems to be a 'dict').  This does not actually happen: the `text` attribute is empty.

Here is a test case which creates a simple png file, uses ImageMagick's `convert` utility to add tEXt key, value pairs then uses PIL to read in that png file.  Even though the tEXt key value pairs are there and can be displayed by the ImageMagick `identify` utility and the Python pypng package, PIL displays an empty dict for the `text` attribute.

```python
from subprocess import call
from PIL import Image
import numpy as np

pixels = np.array([[[255, 0, 0], [0, 255, 0]], [[0, 0, 255], [255, 255, 0]]])
im = Image.fromarray(pixels.astype('uint8'), 'RGB')
im.save("test.png")

call(["convert", "test.png", "-set", "newkey", "newval", "test2.png"])
i = Image.open('test2.png')
print(i.text)
```
This is with Python 2.7.8 and pillow 4.3.0
diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py
index ca7d3c039..1a2602957 100644
--- a/Tests/test_file_png.py
+++ b/Tests/test_file_png.py
@@ -557,6 +557,28 @@ class TestFilePng(PillowTestCase):
         chunks = PngImagePlugin.getchunks(im)
         self.assertEqual(len(chunks), 3)
 
+    def test_textual_chunks_after_idat(self):
+        im = Image.open("Tests/images/hopper.png")
+        self.assertIn('comment', im.text.keys())
+        for k, v in {
+            'date:create': '2014-09-04T09:37:08+03:00',
+            'date:modify': '2014-09-04T09:37:08+03:00',
+        }.items():
+            self.assertEqual(im.text[k], v)
+
+        # Raises a SyntaxError in load_end
+        im = Image.open("Tests/images/broken_data_stream.png")
+        with self.assertRaises(IOError):
+            self.assertIsInstance(im.text, dict)
+
+        # Raises a UnicodeDecodeError in load_end
+        im = Image.open("Tests/images/truncated_image.png")
+        # The file is truncated
+        self.assertRaises(IOError, lambda: im.text)
+        ImageFile.LOAD_TRUNCATED_IMAGES = True
+        self.assertIsInstance(im.text, dict)
+        ImageFile.LOAD_TRUNCATED_IMAGES = False
+
 
 @unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or macOS")
 class TestTruncatedPngPLeaks(PillowLeakTestCase):

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
blessed==1.20.0
build==1.2.2.post1
certifi==2025.1.31
charset-normalizer==3.4.1
check-manifest==0.50
cov-core==1.15.0
coverage==7.8.0
coveralls==4.0.1
docopt==0.6.2
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
olefile==0.47
packaging==24.2
-e git+https://github.com/python-pillow/Pillow.git@9dd0348be2751beb2c617e32ff9985aa2f92ae5f#egg=Pillow
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
pytz==2025.2
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
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
      - blessed==1.20.0
      - build==1.2.2.post1
      - certifi==2025.1.31
      - charset-normalizer==3.4.1
      - check-manifest==0.50
      - cov-core==1.15.0
      - coverage==7.8.0
      - coveralls==4.0.1
      - docopt==0.6.2
      - 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
      - olefile==0.47
      - packaging==24.2
      - 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
      - pytz==2025.2
      - 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
      - urllib3==2.3.0
      - wcwidth==0.2.13
      - zipp==3.21.0
prefix: /opt/conda/envs/Pillow

Tests/test_file_png.py::TestFilePng::test_textual_chunks_after_idat Tests/test_file_png.py::TestFilePng::test_trns_null Tests/test_file_png.py::TestFilePng::test_trns_p Tests/test_file_png.py::TestFilePng::test_trns_rgb Tests/test_file_png.py::TestFilePng::test_unicode_text Tests/test_file_png.py::TestFilePng::test_verify_ignores_crc_error Tests/test_file_png.py::TestFilePng::test_verify_not_ignores_crc_error_in_required_chunk Tests/test_file_png.py::TestFilePng::test_verify_struct_error Tests/test_file_png.py::TestTruncatedPngPLeaks::test_leak_load
Tests/test_file_png.py::TestFilePng::test_bad_itxt Tests/test_file_png.py::TestFilePng::test_bad_text Tests/test_file_png.py::TestFilePng::test_bad_ztxt Tests/test_file_png.py::TestFilePng::test_broken Tests/test_file_png.py::TestFilePng::test_chunk_order Tests/test_file_png.py::TestFilePng::test_discard_icc_profile Tests/test_file_png.py::TestFilePng::test_getchunks Tests/test_file_png.py::TestFilePng::test_interlace Tests/test_file_png.py::TestFilePng::test_invalid_file Tests/test_file_png.py::TestFilePng::test_load_transparent_p Tests/test_file_png.py::TestFilePng::test_load_transparent_rgb Tests/test_file_png.py::TestFilePng::test_load_verify Tests/test_file_png.py::TestFilePng::test_nonunicode_text Tests/test_file_png.py::TestFilePng::test_repr_png Tests/test_file_png.py::TestFilePng::test_roundtrip_dpi Tests/test_file_png.py::TestFilePng::test_roundtrip_icc_profile Tests/test_file_png.py::TestFilePng::test_roundtrip_itxt Tests/test_file_png.py::TestFilePng::test_roundtrip_no_icc_profile Tests/test_file_png.py::TestFilePng::test_roundtrip_text Tests/test_file_png.py::TestFilePng::test_sanity Tests/test_file_png.py::TestFilePng::test_save_icc_profile Tests/test_file_png.py::TestFilePng::test_save_l_transparency Tests/test_file_png.py::TestFilePng::test_save_p_single_transparency Tests/test_file_png.py::TestFilePng::test_save_p_transparent_black Tests/test_file_png.py::TestFilePng::test_save_p_transparent_palette Tests/test_file_png.py::TestFilePng::test_save_rgb_single_transparency Tests/test_file_png.py::TestFilePng::test_scary
docs/handbook/image-file-formats.rst src/PIL/PngImagePlugin.py
docs/handbook/image-file-formats.rst src/PIL/PngImagePlugin.py