We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
PSD incorrectly loaded
### What did you do?
I opened the TIFF in Pillow and converted it to JPG.
### What did you expect to happen?
The JPG image to look the same as the original TIFF.
### What actually happened?
The converted JPG looks malformed and has messed up colors.
### What are your OS, Python and Pillow versions?

* OS: Linux
* Python: 3.10.5
* Pillow: 9.1.1 (also tested -git)

```python
>>> img = Image.open("3662b8bd397337482862ab1a06bf3366-OA_535_161_17_F_TE.tif")
>>> out_img = img.convert("RGB")
>>> out_img.save("converted.jpg", quality=95)
```
[original image](https://api.collectie.gent/storage/v1/download/3662b8bd397337482862ab1a06bf3366-OA_535_161_17_F_TE.tif) (beware, 274MB)
[converted image](https://api.collectie.gent/storage/v1/download/3a029a4f48b480211286486a6a1f0f0b-transcode-OA_535_161_17_F_TE.jpg)

Is it okay to report this here or should I report this to the appropriate library (libtiff, jpeg-turbo, ?)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/PIL/PsdImagePlugin.py`
Content:
```
1 #
2 # The Python Imaging Library
3 # $Id$
4 #
5 # Adobe PSD 2.5/3.0 file handling
6 #
7 # History:
8 # 1995-09-01 fl   Created
9 # 1997-01-03 fl   Read most PSD images
10 # 1997-01-18 fl   Fixed P and CMYK support
11 # 2001-10-21 fl   Added seek/tell support (for layers)
12 #
13 # Copyright (c) 1997-2001 by Secret Labs AB.
14 # Copyright (c) 1995-2001 by Fredrik Lundh
15 #
16 # See the README file for information on usage and redistribution.
17 #
18 
19 import io
20 
21 from . import Image, ImageFile, ImagePalette
22 from ._binary import i8
23 from ._binary import i16be as i16
24 from ._binary import i32be as i32
25 from ._binary import si16be as si16
26 
27 MODES = {
28     # (photoshop mode, bits) -> (pil mode, required channels)
29     (0, 1): ("1", 1),
30     (0, 8): ("L", 1),
31     (1, 8): ("L", 1),
32     (2, 8): ("P", 1),
33     (3, 8): ("RGB", 3),
34     (4, 8): ("CMYK", 4),
35     (7, 8): ("L", 1),  # FIXME: multilayer
36     (8, 8): ("L", 1),  # duotone
37     (9, 8): ("LAB", 3),
38 }
39 
40 
41 # --------------------------------------------------------------------.
42 # read PSD images
43 
44 
45 def _accept(prefix):
46     return prefix[:4] == b"8BPS"
47 
48 
49 ##
50 # Image plugin for Photoshop images.
51 
52 
53 class PsdImageFile(ImageFile.ImageFile):
54 
55     format = "PSD"
56     format_description = "Adobe Photoshop"
57     _close_exclusive_fp_after_loading = False
58 
59     def _open(self):
60 
61         read = self.fp.read
62 
63         #
64         # header
65 
66         s = read(26)
67         if not _accept(s) or i16(s, 4) != 1:
68             raise SyntaxError("not a PSD file")
69 
70         psd_bits = i16(s, 22)
71         psd_channels = i16(s, 12)
72         psd_mode = i16(s, 24)
73 
74         mode, channels = MODES[(psd_mode, psd_bits)]
75 
76         if channels > psd_channels:
77             raise OSError("not enough channels")
78 
79         self.mode = mode
80         self._size = i32(s, 18), i32(s, 14)
81 
82         #
83         # color mode data
84 
85         size = i32(read(4))
86         if size:
87             data = read(size)
88             if mode == "P" and size == 768:
89                 self.palette = ImagePalette.raw("RGB;L", data)
90 
91         #
92         # image resources
93 
94         self.resources = []
95 
96         size = i32(read(4))
97         if size:
98             # load resources
99             end = self.fp.tell() + size
100             while self.fp.tell() < end:
101                 read(4)  # signature
102                 id = i16(read(2))
103                 name = read(i8(read(1)))
104                 if not (len(name) & 1):
105                     read(1)  # padding
106                 data = read(i32(read(4)))
107                 if len(data) & 1:
108                     read(1)  # padding
109                 self.resources.append((id, name, data))
110                 if id == 1039:  # ICC profile
111                     self.info["icc_profile"] = data
112 
113         #
114         # layer and mask information
115 
116         self.layers = []
117 
118         size = i32(read(4))
119         if size:
120             end = self.fp.tell() + size
121             size = i32(read(4))
122             if size:
123                 _layer_data = io.BytesIO(ImageFile._safe_read(self.fp, size))
124                 self.layers = _layerinfo(_layer_data, size)
125             self.fp.seek(end)
126         self.n_frames = len(self.layers)
127         self.is_animated = self.n_frames > 1
128 
129         #
130         # image descriptor
131 
132         self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)
133 
134         # keep the file open
135         self._fp = self.fp
136         self.frame = 1
137         self._min_frame = 1
138 
139     def seek(self, layer):
140         if not self._seek_check(layer):
141             return
142 
143         # seek to given layer (1..max)
144         try:
145             name, mode, bbox, tile = self.layers[layer - 1]
146             self.mode = mode
147             self.tile = tile
148             self.frame = layer
149             self.fp = self._fp
150             return name, bbox
151         except IndexError as e:
152             raise EOFError("no such layer") from e
153 
154     def tell(self):
155         # return layer number (0=image, 1..max=layers)
156         return self.frame
157 
158 
159 def _layerinfo(fp, ct_bytes):
160     # read layerinfo block
161     layers = []
162 
163     def read(size):
164         return ImageFile._safe_read(fp, size)
165 
166     ct = si16(read(2))
167 
168     # sanity check
169     if ct_bytes < (abs(ct) * 20):
170         raise SyntaxError("Layer block too short for number of layers requested")
171 
172     for _ in range(abs(ct)):
173 
174         # bounding box
175         y0 = i32(read(4))
176         x0 = i32(read(4))
177         y1 = i32(read(4))
178         x1 = i32(read(4))
179 
180         # image info
181         mode = []
182         ct_types = i16(read(2))
183         types = list(range(ct_types))
184         if len(types) > 4:
185             continue
186 
187         for _ in types:
188             type = i16(read(2))
189 
190             if type == 65535:
191                 m = "A"
192             else:
193                 m = "RGBA"[type]
194 
195             mode.append(m)
196             read(4)  # size
197 
198         # figure out the image mode
199         mode.sort()
200         if mode == ["R"]:
201             mode = "L"
202         elif mode == ["B", "G", "R"]:
203             mode = "RGB"
204         elif mode == ["A", "B", "G", "R"]:
205             mode = "RGBA"
206         else:
207             mode = None  # unknown
208 
209         # skip over blend flags and extra information
210         read(12)  # filler
211         name = ""
212         size = i32(read(4))  # length of the extra data field
213         if size:
214             data_end = fp.tell() + size
215 
216             length = i32(read(4))
217             if length:
218                 fp.seek(length - 16, io.SEEK_CUR)
219 
220             length = i32(read(4))
221             if length:
222                 fp.seek(length, io.SEEK_CUR)
223 
224             length = i8(read(1))
225             if length:
226                 # Don't know the proper encoding,
227                 # Latin-1 should be a good guess
228                 name = read(length).decode("latin-1", "replace")
229 
230             fp.seek(data_end)
231         layers.append((name, mode, (x0, y0, x1, y1)))
232 
233     # get tiles
234     i = 0
235     for name, mode, bbox in layers:
236         tile = []
237         for m in mode:
238             t = _maketile(fp, m, bbox, 1)
239             if t:
240                 tile.extend(t)
241         layers[i] = name, mode, bbox, tile
242         i += 1
243 
244     return layers
245 
246 
247 def _maketile(file, mode, bbox, channels):
248 
249     tile = None
250     read = file.read
251 
252     compression = i16(read(2))
253 
254     xsize = bbox[2] - bbox[0]
255     ysize = bbox[3] - bbox[1]
256 
257     offset = file.tell()
258 
259     if compression == 0:
260         #
261         # raw compression
262         tile = []
263         for channel in range(channels):
264             layer = mode[channel]
265             if mode == "CMYK":
266                 layer += ";I"
267             tile.append(("raw", bbox, offset, layer))
268             offset = offset + xsize * ysize
269 
270     elif compression == 1:
271         #
272         # packbits compression
273         i = 0
274         tile = []
275         bytecount = read(channels * ysize * 2)
276         offset = file.tell()
277         for channel in range(channels):
278             layer = mode[channel]
279             if mode == "CMYK":
280                 layer += ";I"
281             tile.append(("packbits", bbox, offset, layer))
282             for y in range(ysize):
283                 offset = offset + i16(bytecount, i)
284                 i += 2
285 
286     file.seek(offset)
287 
288     if offset & 1:
289         read(1)  # padding
290 
291     return tile
292 
293 
294 # --------------------------------------------------------------------
295 # registry
296 
297 
298 Image.register_open(PsdImageFile.format, PsdImageFile, _accept)
299 
300 Image.register_extension(PsdImageFile.format, ".psd")
301 
302 Image.register_mime(PsdImageFile.format, "image/vnd.adobe.photoshop")
303
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py
--- a/src/PIL/PsdImagePlugin.py
+++ b/src/PIL/PsdImagePlugin.py
@@ -75,6 +75,9 @@
 
         if channels > psd_channels:
             raise OSError("not enough channels")
+        if mode == "RGB" and psd_channels == 4:
+            mode = "RGBA"
+            channels = 4
 
         self.mode = mode
         self._size = i32(s, 18), i32(s, 14)

{"golden_diff": "diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py\n--- a/src/PIL/PsdImagePlugin.py\n+++ b/src/PIL/PsdImagePlugin.py\n@@ -75,6 +75,9 @@\n \n         if channels > psd_channels:\n             raise OSError(\"not enough channels\")\n+        if mode == \"RGB\" and psd_channels == 4:\n+            mode = \"RGBA\"\n+            channels = 4\n \n         self.mode = mode\n         self._size = i32(s, 18), i32(s, 14)\n", "issue": "PSD incorrectly loaded\n### What did you do?\r\nI opened the TIFF in Pillow and converted it to JPG.\r\n### What did you expect to happen?\r\nThe JPG image to look the same as the original TIFF.\r\n### What actually happened?\r\nThe converted JPG looks malformed and has messed up colors.\r\n### What are your OS, Python and Pillow versions?\r\n\r\n* OS: Linux\r\n* Python: 3.10.5\r\n* Pillow: 9.1.1 (also tested -git)\r\n\r\n```python\r\n>>> img = Image.open(\"3662b8bd397337482862ab1a06bf3366-OA_535_161_17_F_TE.tif\")\r\n>>> out_img = img.convert(\"RGB\")\r\n>>> out_img.save(\"converted.jpg\", quality=95)\r\n```\r\n[original image](https://api.collectie.gent/storage/v1/download/3662b8bd397337482862ab1a06bf3366-OA_535_161_17_F_TE.tif) (beware, 274MB)\r\n[converted image](https://api.collectie.gent/storage/v1/download/3a029a4f48b480211286486a6a1f0f0b-transcode-OA_535_161_17_F_TE.jpg)\r\n\r\nIs it okay to report this here or should I report this to the appropriate library (libtiff, jpeg-turbo, ?)\n", "before_files": [{"content": "#\n# The Python Imaging Library\n# $Id$\n#\n# Adobe PSD 2.5/3.0 file handling\n#\n# History:\n# 1995-09-01 fl   Created\n# 1997-01-03 fl   Read most PSD images\n# 1997-01-18 fl   Fixed P and CMYK support\n# 2001-10-21 fl   Added seek/tell support (for layers)\n#\n# Copyright (c) 1997-2001 by Secret Labs AB.\n# Copyright (c) 1995-2001 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\nimport io\n\nfrom . import Image, ImageFile, ImagePalette\nfrom ._binary import i8\nfrom ._binary import i16be as i16\nfrom ._binary import i32be as i32\nfrom ._binary import si16be as si16\n\nMODES = {\n    # (photoshop mode, bits) -> (pil mode, required channels)\n    (0, 1): (\"1\", 1),\n    (0, 8): (\"L\", 1),\n    (1, 8): (\"L\", 1),\n    (2, 8): (\"P\", 1),\n    (3, 8): (\"RGB\", 3),\n    (4, 8): (\"CMYK\", 4),\n    (7, 8): (\"L\", 1),  # FIXME: multilayer\n    (8, 8): (\"L\", 1),  # duotone\n    (9, 8): (\"LAB\", 3),\n}\n\n\n# --------------------------------------------------------------------.\n# read PSD images\n\n\ndef _accept(prefix):\n    return prefix[:4] == b\"8BPS\"\n\n\n##\n# Image plugin for Photoshop images.\n\n\nclass PsdImageFile(ImageFile.ImageFile):\n\n    format = \"PSD\"\n    format_description = \"Adobe Photoshop\"\n    _close_exclusive_fp_after_loading = False\n\n    def _open(self):\n\n        read = self.fp.read\n\n        #\n        # header\n\n        s = read(26)\n        if not _accept(s) or i16(s, 4) != 1:\n            raise SyntaxError(\"not a PSD file\")\n\n        psd_bits = i16(s, 22)\n        psd_channels = i16(s, 12)\n        psd_mode = i16(s, 24)\n\n        mode, channels = MODES[(psd_mode, psd_bits)]\n\n        if channels > psd_channels:\n            raise OSError(\"not enough channels\")\n\n        self.mode = mode\n        self._size = i32(s, 18), i32(s, 14)\n\n        #\n        # color mode data\n\n        size = i32(read(4))\n        if size:\n            data = read(size)\n            if mode == \"P\" and size == 768:\n                self.palette = ImagePalette.raw(\"RGB;L\", data)\n\n        #\n        # image resources\n\n        self.resources = []\n\n        size = i32(read(4))\n        if size:\n            # load resources\n            end = self.fp.tell() + size\n            while self.fp.tell() < end:\n                read(4)  # signature\n                id = i16(read(2))\n                name = read(i8(read(1)))\n                if not (len(name) & 1):\n                    read(1)  # padding\n                data = read(i32(read(4)))\n                if len(data) & 1:\n                    read(1)  # padding\n                self.resources.append((id, name, data))\n                if id == 1039:  # ICC profile\n                    self.info[\"icc_profile\"] = data\n\n        #\n        # layer and mask information\n\n        self.layers = []\n\n        size = i32(read(4))\n        if size:\n            end = self.fp.tell() + size\n            size = i32(read(4))\n            if size:\n                _layer_data = io.BytesIO(ImageFile._safe_read(self.fp, size))\n                self.layers = _layerinfo(_layer_data, size)\n            self.fp.seek(end)\n        self.n_frames = len(self.layers)\n        self.is_animated = self.n_frames > 1\n\n        #\n        # image descriptor\n\n        self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)\n\n        # keep the file open\n        self._fp = self.fp\n        self.frame = 1\n        self._min_frame = 1\n\n    def seek(self, layer):\n        if not self._seek_check(layer):\n            return\n\n        # seek to given layer (1..max)\n        try:\n            name, mode, bbox, tile = self.layers[layer - 1]\n            self.mode = mode\n            self.tile = tile\n            self.frame = layer\n            self.fp = self._fp\n            return name, bbox\n        except IndexError as e:\n            raise EOFError(\"no such layer\") from e\n\n    def tell(self):\n        # return layer number (0=image, 1..max=layers)\n        return self.frame\n\n\ndef _layerinfo(fp, ct_bytes):\n    # read layerinfo block\n    layers = []\n\n    def read(size):\n        return ImageFile._safe_read(fp, size)\n\n    ct = si16(read(2))\n\n    # sanity check\n    if ct_bytes < (abs(ct) * 20):\n        raise SyntaxError(\"Layer block too short for number of layers requested\")\n\n    for _ in range(abs(ct)):\n\n        # bounding box\n        y0 = i32(read(4))\n        x0 = i32(read(4))\n        y1 = i32(read(4))\n        x1 = i32(read(4))\n\n        # image info\n        mode = []\n        ct_types = i16(read(2))\n        types = list(range(ct_types))\n        if len(types) > 4:\n            continue\n\n        for _ in types:\n            type = i16(read(2))\n\n            if type == 65535:\n                m = \"A\"\n            else:\n                m = \"RGBA\"[type]\n\n            mode.append(m)\n            read(4)  # size\n\n        # figure out the image mode\n        mode.sort()\n        if mode == [\"R\"]:\n            mode = \"L\"\n        elif mode == [\"B\", \"G\", \"R\"]:\n            mode = \"RGB\"\n        elif mode == [\"A\", \"B\", \"G\", \"R\"]:\n            mode = \"RGBA\"\n        else:\n            mode = None  # unknown\n\n        # skip over blend flags and extra information\n        read(12)  # filler\n        name = \"\"\n        size = i32(read(4))  # length of the extra data field\n        if size:\n            data_end = fp.tell() + size\n\n            length = i32(read(4))\n            if length:\n                fp.seek(length - 16, io.SEEK_CUR)\n\n            length = i32(read(4))\n            if length:\n                fp.seek(length, io.SEEK_CUR)\n\n            length = i8(read(1))\n            if length:\n                # Don't know the proper encoding,\n                # Latin-1 should be a good guess\n                name = read(length).decode(\"latin-1\", \"replace\")\n\n            fp.seek(data_end)\n        layers.append((name, mode, (x0, y0, x1, y1)))\n\n    # get tiles\n    i = 0\n    for name, mode, bbox in layers:\n        tile = []\n        for m in mode:\n            t = _maketile(fp, m, bbox, 1)\n            if t:\n                tile.extend(t)\n        layers[i] = name, mode, bbox, tile\n        i += 1\n\n    return layers\n\n\ndef _maketile(file, mode, bbox, channels):\n\n    tile = None\n    read = file.read\n\n    compression = i16(read(2))\n\n    xsize = bbox[2] - bbox[0]\n    ysize = bbox[3] - bbox[1]\n\n    offset = file.tell()\n\n    if compression == 0:\n        #\n        # raw compression\n        tile = []\n        for channel in range(channels):\n            layer = mode[channel]\n            if mode == \"CMYK\":\n                layer += \";I\"\n            tile.append((\"raw\", bbox, offset, layer))\n            offset = offset + xsize * ysize\n\n    elif compression == 1:\n        #\n        # packbits compression\n        i = 0\n        tile = []\n        bytecount = read(channels * ysize * 2)\n        offset = file.tell()\n        for channel in range(channels):\n            layer = mode[channel]\n            if mode == \"CMYK\":\n                layer += \";I\"\n            tile.append((\"packbits\", bbox, offset, layer))\n            for y in range(ysize):\n                offset = offset + i16(bytecount, i)\n                i += 2\n\n    file.seek(offset)\n\n    if offset & 1:\n        read(1)  # padding\n\n    return tile\n\n\n# --------------------------------------------------------------------\n# registry\n\n\nImage.register_open(PsdImageFile.format, PsdImageFile, _accept)\n\nImage.register_extension(PsdImageFile.format, \".psd\")\n\nImage.register_mime(PsdImageFile.format, \"image/vnd.adobe.photoshop\")\n", "path": "src/PIL/PsdImagePlugin.py"}], "after_files": [{"content": "#\n# The Python Imaging Library\n# $Id$\n#\n# Adobe PSD 2.5/3.0 file handling\n#\n# History:\n# 1995-09-01 fl   Created\n# 1997-01-03 fl   Read most PSD images\n# 1997-01-18 fl   Fixed P and CMYK support\n# 2001-10-21 fl   Added seek/tell support (for layers)\n#\n# Copyright (c) 1997-2001 by Secret Labs AB.\n# Copyright (c) 1995-2001 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\nimport io\n\nfrom . import Image, ImageFile, ImagePalette\nfrom ._binary import i8\nfrom ._binary import i16be as i16\nfrom ._binary import i32be as i32\nfrom ._binary import si16be as si16\n\nMODES = {\n    # (photoshop mode, bits) -> (pil mode, required channels)\n    (0, 1): (\"1\", 1),\n    (0, 8): (\"L\", 1),\n    (1, 8): (\"L\", 1),\n    (2, 8): (\"P\", 1),\n    (3, 8): (\"RGB\", 3),\n    (4, 8): (\"CMYK\", 4),\n    (7, 8): (\"L\", 1),  # FIXME: multilayer\n    (8, 8): (\"L\", 1),  # duotone\n    (9, 8): (\"LAB\", 3),\n}\n\n\n# --------------------------------------------------------------------.\n# read PSD images\n\n\ndef _accept(prefix):\n    return prefix[:4] == b\"8BPS\"\n\n\n##\n# Image plugin for Photoshop images.\n\n\nclass PsdImageFile(ImageFile.ImageFile):\n\n    format = \"PSD\"\n    format_description = \"Adobe Photoshop\"\n    _close_exclusive_fp_after_loading = False\n\n    def _open(self):\n\n        read = self.fp.read\n\n        #\n        # header\n\n        s = read(26)\n        if not _accept(s) or i16(s, 4) != 1:\n            raise SyntaxError(\"not a PSD file\")\n\n        psd_bits = i16(s, 22)\n        psd_channels = i16(s, 12)\n        psd_mode = i16(s, 24)\n\n        mode, channels = MODES[(psd_mode, psd_bits)]\n\n        if channels > psd_channels:\n            raise OSError(\"not enough channels\")\n        if mode == \"RGB\" and psd_channels == 4:\n            mode = \"RGBA\"\n            channels = 4\n\n        self.mode = mode\n        self._size = i32(s, 18), i32(s, 14)\n\n        #\n        # color mode data\n\n        size = i32(read(4))\n        if size:\n            data = read(size)\n            if mode == \"P\" and size == 768:\n                self.palette = ImagePalette.raw(\"RGB;L\", data)\n\n        #\n        # image resources\n\n        self.resources = []\n\n        size = i32(read(4))\n        if size:\n            # load resources\n            end = self.fp.tell() + size\n            while self.fp.tell() < end:\n                read(4)  # signature\n                id = i16(read(2))\n                name = read(i8(read(1)))\n                if not (len(name) & 1):\n                    read(1)  # padding\n                data = read(i32(read(4)))\n                if len(data) & 1:\n                    read(1)  # padding\n                self.resources.append((id, name, data))\n                if id == 1039:  # ICC profile\n                    self.info[\"icc_profile\"] = data\n\n        #\n        # layer and mask information\n\n        self.layers = []\n\n        size = i32(read(4))\n        if size:\n            end = self.fp.tell() + size\n            size = i32(read(4))\n            if size:\n                _layer_data = io.BytesIO(ImageFile._safe_read(self.fp, size))\n                self.layers = _layerinfo(_layer_data, size)\n            self.fp.seek(end)\n        self.n_frames = len(self.layers)\n        self.is_animated = self.n_frames > 1\n\n        #\n        # image descriptor\n\n        self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)\n\n        # keep the file open\n        self._fp = self.fp\n        self.frame = 1\n        self._min_frame = 1\n\n    def seek(self, layer):\n        if not self._seek_check(layer):\n            return\n\n        # seek to given layer (1..max)\n        try:\n            name, mode, bbox, tile = self.layers[layer - 1]\n            self.mode = mode\n            self.tile = tile\n            self.frame = layer\n            self.fp = self._fp\n            return name, bbox\n        except IndexError as e:\n            raise EOFError(\"no such layer\") from e\n\n    def tell(self):\n        # return layer number (0=image, 1..max=layers)\n        return self.frame\n\n\ndef _layerinfo(fp, ct_bytes):\n    # read layerinfo block\n    layers = []\n\n    def read(size):\n        return ImageFile._safe_read(fp, size)\n\n    ct = si16(read(2))\n\n    # sanity check\n    if ct_bytes < (abs(ct) * 20):\n        raise SyntaxError(\"Layer block too short for number of layers requested\")\n\n    for _ in range(abs(ct)):\n\n        # bounding box\n        y0 = i32(read(4))\n        x0 = i32(read(4))\n        y1 = i32(read(4))\n        x1 = i32(read(4))\n\n        # image info\n        mode = []\n        ct_types = i16(read(2))\n        types = list(range(ct_types))\n        if len(types) > 4:\n            continue\n\n        for _ in types:\n            type = i16(read(2))\n\n            if type == 65535:\n                m = \"A\"\n            else:\n                m = \"RGBA\"[type]\n\n            mode.append(m)\n            read(4)  # size\n\n        # figure out the image mode\n        mode.sort()\n        if mode == [\"R\"]:\n            mode = \"L\"\n        elif mode == [\"B\", \"G\", \"R\"]:\n            mode = \"RGB\"\n        elif mode == [\"A\", \"B\", \"G\", \"R\"]:\n            mode = \"RGBA\"\n        else:\n            mode = None  # unknown\n\n        # skip over blend flags and extra information\n        read(12)  # filler\n        name = \"\"\n        size = i32(read(4))  # length of the extra data field\n        if size:\n            data_end = fp.tell() + size\n\n            length = i32(read(4))\n            if length:\n                fp.seek(length - 16, io.SEEK_CUR)\n\n            length = i32(read(4))\n            if length:\n                fp.seek(length, io.SEEK_CUR)\n\n            length = i8(read(1))\n            if length:\n                # Don't know the proper encoding,\n                # Latin-1 should be a good guess\n                name = read(length).decode(\"latin-1\", \"replace\")\n\n            fp.seek(data_end)\n        layers.append((name, mode, (x0, y0, x1, y1)))\n\n    # get tiles\n    i = 0\n    for name, mode, bbox in layers:\n        tile = []\n        for m in mode:\n            t = _maketile(fp, m, bbox, 1)\n            if t:\n                tile.extend(t)\n        layers[i] = name, mode, bbox, tile\n        i += 1\n\n    return layers\n\n\ndef _maketile(file, mode, bbox, channels):\n\n    tile = None\n    read = file.read\n\n    compression = i16(read(2))\n\n    xsize = bbox[2] - bbox[0]\n    ysize = bbox[3] - bbox[1]\n\n    offset = file.tell()\n\n    if compression == 0:\n        #\n        # raw compression\n        tile = []\n        for channel in range(channels):\n            layer = mode[channel]\n            if mode == \"CMYK\":\n                layer += \";I\"\n            tile.append((\"raw\", bbox, offset, layer))\n            offset = offset + xsize * ysize\n\n    elif compression == 1:\n        #\n        # packbits compression\n        i = 0\n        tile = []\n        bytecount = read(channels * ysize * 2)\n        offset = file.tell()\n        for channel in range(channels):\n            layer = mode[channel]\n            if mode == \"CMYK\":\n                layer += \";I\"\n            tile.append((\"packbits\", bbox, offset, layer))\n            for y in range(ysize):\n                offset = offset + i16(bytecount, i)\n                i += 2\n\n    file.seek(offset)\n\n    if offset & 1:\n        read(1)  # padding\n\n    return tile\n\n\n# --------------------------------------------------------------------\n# registry\n\n\nImage.register_open(PsdImageFile.format, PsdImageFile, _accept)\n\nImage.register_extension(PsdImageFile.format, \".psd\")\n\nImage.register_mime(PsdImageFile.format, \"image/vnd.adobe.photoshop\")\n", "path": "src/PIL/PsdImagePlugin.py"}]}