We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
DdsImagePlugin fails when dxgi_format == DXGI_FORMAT_BC7_UNORM_SRGB
https://github.com/python-pillow/Pillow/blob/84fed4d213a50b359188aa59f99ed06ba1249c14/src/PIL/DdsImagePlugin.py#L156-L159

At `self.im_info["gamma"] = 1 / 2.2`, `self.im_info` has never been initialized and so trying to set `self.im_info["gamma"]` fails with:
```
AttributeError: 'DdsImageFile' object has no attribute 'im_info'
```
As far as I can tell, this is the only place `im_info` is ever referenced in this or the ancestor classes.

A possible solution would be to change this section to:
```python
                elif dxgi_format == DXGI_FORMAT_BC7_UNORM_SRGB:
                    self.pixel_format = "BC7"
                    if not hasattr(self, 'im_info'):
                        self.im_info = {}
                    self.im_info["gamma"] = 1 / 2.2
                    n = 7
```

An alternate solution would be to initialize `im_info` earlier in the loader method.

--- 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/DdsImagePlugin.py`
Content:
```
1 """
2 A Pillow loader for .dds files (S3TC-compressed aka DXTC)
3 Jerome Leclanche <jerome@leclan.ch>
4 
5 Documentation:
6   https://web.archive.org/web/20170802060935/http://oss.sgi.com/projects/ogl-sample/registry/EXT/texture_compression_s3tc.txt
7 
8 The contents of this file are hereby released in the public domain (CC0)
9 Full text of the CC0 license:
10   https://creativecommons.org/publicdomain/zero/1.0/
11 """
12 
13 import struct
14 from io import BytesIO
15 
16 from . import Image, ImageFile
17 
18 # Magic ("DDS ")
19 DDS_MAGIC = 0x20534444
20 
21 # DDS flags
22 DDSD_CAPS = 0x1
23 DDSD_HEIGHT = 0x2
24 DDSD_WIDTH = 0x4
25 DDSD_PITCH = 0x8
26 DDSD_PIXELFORMAT = 0x1000
27 DDSD_MIPMAPCOUNT = 0x20000
28 DDSD_LINEARSIZE = 0x80000
29 DDSD_DEPTH = 0x800000
30 
31 # DDS caps
32 DDSCAPS_COMPLEX = 0x8
33 DDSCAPS_TEXTURE = 0x1000
34 DDSCAPS_MIPMAP = 0x400000
35 
36 DDSCAPS2_CUBEMAP = 0x200
37 DDSCAPS2_CUBEMAP_POSITIVEX = 0x400
38 DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800
39 DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000
40 DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000
41 DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000
42 DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000
43 DDSCAPS2_VOLUME = 0x200000
44 
45 # Pixel Format
46 DDPF_ALPHAPIXELS = 0x1
47 DDPF_ALPHA = 0x2
48 DDPF_FOURCC = 0x4
49 DDPF_PALETTEINDEXED8 = 0x20
50 DDPF_RGB = 0x40
51 DDPF_LUMINANCE = 0x20000
52 
53 
54 # dds.h
55 
56 DDS_FOURCC = DDPF_FOURCC
57 DDS_RGB = DDPF_RGB
58 DDS_RGBA = DDPF_RGB | DDPF_ALPHAPIXELS
59 DDS_LUMINANCE = DDPF_LUMINANCE
60 DDS_LUMINANCEA = DDPF_LUMINANCE | DDPF_ALPHAPIXELS
61 DDS_ALPHA = DDPF_ALPHA
62 DDS_PAL8 = DDPF_PALETTEINDEXED8
63 
64 DDS_HEADER_FLAGS_TEXTURE = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
65 DDS_HEADER_FLAGS_MIPMAP = DDSD_MIPMAPCOUNT
66 DDS_HEADER_FLAGS_VOLUME = DDSD_DEPTH
67 DDS_HEADER_FLAGS_PITCH = DDSD_PITCH
68 DDS_HEADER_FLAGS_LINEARSIZE = DDSD_LINEARSIZE
69 
70 DDS_HEIGHT = DDSD_HEIGHT
71 DDS_WIDTH = DDSD_WIDTH
72 
73 DDS_SURFACE_FLAGS_TEXTURE = DDSCAPS_TEXTURE
74 DDS_SURFACE_FLAGS_MIPMAP = DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
75 DDS_SURFACE_FLAGS_CUBEMAP = DDSCAPS_COMPLEX
76 
77 DDS_CUBEMAP_POSITIVEX = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
78 DDS_CUBEMAP_NEGATIVEX = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
79 DDS_CUBEMAP_POSITIVEY = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
80 DDS_CUBEMAP_NEGATIVEY = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
81 DDS_CUBEMAP_POSITIVEZ = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
82 DDS_CUBEMAP_NEGATIVEZ = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
83 
84 
85 # DXT1
86 DXT1_FOURCC = 0x31545844
87 
88 # DXT3
89 DXT3_FOURCC = 0x33545844
90 
91 # DXT5
92 DXT5_FOURCC = 0x35545844
93 
94 
95 # dxgiformat.h
96 
97 DXGI_FORMAT_BC7_TYPELESS = 97
98 DXGI_FORMAT_BC7_UNORM = 98
99 DXGI_FORMAT_BC7_UNORM_SRGB = 99
100 
101 
102 class DdsImageFile(ImageFile.ImageFile):
103     format = "DDS"
104     format_description = "DirectDraw Surface"
105 
106     def _open(self):
107         magic, header_size = struct.unpack("<II", self.fp.read(8))
108         if header_size != 124:
109             raise IOError("Unsupported header size %r" % (header_size))
110         header_bytes = self.fp.read(header_size - 4)
111         if len(header_bytes) != 120:
112             raise IOError("Incomplete header: %s bytes" % len(header_bytes))
113         header = BytesIO(header_bytes)
114 
115         flags, height, width = struct.unpack("<3I", header.read(12))
116         self._size = (width, height)
117         self.mode = "RGBA"
118 
119         pitch, depth, mipmaps = struct.unpack("<3I", header.read(12))
120         struct.unpack("<11I", header.read(44))  # reserved
121 
122         # pixel format
123         pfsize, pfflags = struct.unpack("<2I", header.read(8))
124         fourcc = header.read(4)
125         (bitcount,) = struct.unpack("<I", header.read(4))
126         masks = struct.unpack("<4I", header.read(16))
127         if pfflags & 0x40:
128             # DDPF_RGB - Texture contains uncompressed RGB data
129             masks = {mask: ["R", "G", "B", "A"][i] for i, mask in enumerate(masks)}
130             rawmode = ""
131             if bitcount == 32:
132                 rawmode += masks[0xFF000000]
133             rawmode += masks[0xFF0000] + masks[0xFF00] + masks[0xFF]
134 
135             self.tile = [("raw", (0, 0) + self.size, 0, (rawmode, 0, 1))]
136         else:
137             data_start = header_size + 4
138             n = 0
139             if fourcc == b"DXT1":
140                 self.pixel_format = "DXT1"
141                 n = 1
142             elif fourcc == b"DXT3":
143                 self.pixel_format = "DXT3"
144                 n = 2
145             elif fourcc == b"DXT5":
146                 self.pixel_format = "DXT5"
147                 n = 3
148             elif fourcc == b"DX10":
149                 data_start += 20
150                 # ignoring flags which pertain to volume textures and cubemaps
151                 dxt10 = BytesIO(self.fp.read(20))
152                 dxgi_format, dimension = struct.unpack("<II", dxt10.read(8))
153                 if dxgi_format in (DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM):
154                     self.pixel_format = "BC7"
155                     n = 7
156                 elif dxgi_format == DXGI_FORMAT_BC7_UNORM_SRGB:
157                     self.pixel_format = "BC7"
158                     self.im_info["gamma"] = 1 / 2.2
159                     n = 7
160                 else:
161                     raise NotImplementedError(
162                         "Unimplemented DXGI format %d" % (dxgi_format)
163                     )
164             else:
165                 raise NotImplementedError("Unimplemented pixel format %r" % (fourcc))
166 
167             self.tile = [("bcn", (0, 0) + self.size, data_start, (n))]
168 
169     def load_seek(self, pos):
170         pass
171 
172 
173 def _validate(prefix):
174     return prefix[:4] == b"DDS "
175 
176 
177 Image.register_open(DdsImageFile.format, DdsImageFile, _validate)
178 Image.register_extension(DdsImageFile.format, ".dds")
179
```
--- 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/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py
--- a/src/PIL/DdsImagePlugin.py
+++ b/src/PIL/DdsImagePlugin.py
@@ -155,7 +155,7 @@
                     n = 7
                 elif dxgi_format == DXGI_FORMAT_BC7_UNORM_SRGB:
                     self.pixel_format = "BC7"
-                    self.im_info["gamma"] = 1 / 2.2
+                    self.info["gamma"] = 1 / 2.2
                     n = 7
                 else:
                     raise NotImplementedError(

{"golden_diff": "diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py\n--- a/src/PIL/DdsImagePlugin.py\n+++ b/src/PIL/DdsImagePlugin.py\n@@ -155,7 +155,7 @@\n                     n = 7\n                 elif dxgi_format == DXGI_FORMAT_BC7_UNORM_SRGB:\n                     self.pixel_format = \"BC7\"\n-                    self.im_info[\"gamma\"] = 1 / 2.2\n+                    self.info[\"gamma\"] = 1 / 2.2\n                     n = 7\n                 else:\n                     raise NotImplementedError(\n", "issue": "DdsImagePlugin fails when dxgi_format == DXGI_FORMAT_BC7_UNORM_SRGB\nhttps://github.com/python-pillow/Pillow/blob/84fed4d213a50b359188aa59f99ed06ba1249c14/src/PIL/DdsImagePlugin.py#L156-L159\r\n\r\nAt `self.im_info[\"gamma\"] = 1 / 2.2`, `self.im_info` has never been initialized and so trying to set `self.im_info[\"gamma\"]` fails with:\r\n```\r\nAttributeError: 'DdsImageFile' object has no attribute 'im_info'\r\n```\r\nAs far as I can tell, this is the only place `im_info` is ever referenced in this or the ancestor classes.\r\n\r\nA possible solution would be to change this section to:\r\n```python\r\n                elif dxgi_format == DXGI_FORMAT_BC7_UNORM_SRGB:\r\n                    self.pixel_format = \"BC7\"\r\n                    if not hasattr(self, 'im_info'):\r\n                        self.im_info = {}\r\n                    self.im_info[\"gamma\"] = 1 / 2.2\r\n                    n = 7\r\n```\r\n\r\nAn alternate solution would be to initialize `im_info` earlier in the loader method.\n", "before_files": [{"content": "\"\"\"\nA Pillow loader for .dds files (S3TC-compressed aka DXTC)\nJerome Leclanche <jerome@leclan.ch>\n\nDocumentation:\n  https://web.archive.org/web/20170802060935/http://oss.sgi.com/projects/ogl-sample/registry/EXT/texture_compression_s3tc.txt\n\nThe contents of this file are hereby released in the public domain (CC0)\nFull text of the CC0 license:\n  https://creativecommons.org/publicdomain/zero/1.0/\n\"\"\"\n\nimport struct\nfrom io import BytesIO\n\nfrom . import Image, ImageFile\n\n# Magic (\"DDS \")\nDDS_MAGIC = 0x20534444\n\n# DDS flags\nDDSD_CAPS = 0x1\nDDSD_HEIGHT = 0x2\nDDSD_WIDTH = 0x4\nDDSD_PITCH = 0x8\nDDSD_PIXELFORMAT = 0x1000\nDDSD_MIPMAPCOUNT = 0x20000\nDDSD_LINEARSIZE = 0x80000\nDDSD_DEPTH = 0x800000\n\n# DDS caps\nDDSCAPS_COMPLEX = 0x8\nDDSCAPS_TEXTURE = 0x1000\nDDSCAPS_MIPMAP = 0x400000\n\nDDSCAPS2_CUBEMAP = 0x200\nDDSCAPS2_CUBEMAP_POSITIVEX = 0x400\nDDSCAPS2_CUBEMAP_NEGATIVEX = 0x800\nDDSCAPS2_CUBEMAP_POSITIVEY = 0x1000\nDDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000\nDDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000\nDDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000\nDDSCAPS2_VOLUME = 0x200000\n\n# Pixel Format\nDDPF_ALPHAPIXELS = 0x1\nDDPF_ALPHA = 0x2\nDDPF_FOURCC = 0x4\nDDPF_PALETTEINDEXED8 = 0x20\nDDPF_RGB = 0x40\nDDPF_LUMINANCE = 0x20000\n\n\n# dds.h\n\nDDS_FOURCC = DDPF_FOURCC\nDDS_RGB = DDPF_RGB\nDDS_RGBA = DDPF_RGB | DDPF_ALPHAPIXELS\nDDS_LUMINANCE = DDPF_LUMINANCE\nDDS_LUMINANCEA = DDPF_LUMINANCE | DDPF_ALPHAPIXELS\nDDS_ALPHA = DDPF_ALPHA\nDDS_PAL8 = DDPF_PALETTEINDEXED8\n\nDDS_HEADER_FLAGS_TEXTURE = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT\nDDS_HEADER_FLAGS_MIPMAP = DDSD_MIPMAPCOUNT\nDDS_HEADER_FLAGS_VOLUME = DDSD_DEPTH\nDDS_HEADER_FLAGS_PITCH = DDSD_PITCH\nDDS_HEADER_FLAGS_LINEARSIZE = DDSD_LINEARSIZE\n\nDDS_HEIGHT = DDSD_HEIGHT\nDDS_WIDTH = DDSD_WIDTH\n\nDDS_SURFACE_FLAGS_TEXTURE = DDSCAPS_TEXTURE\nDDS_SURFACE_FLAGS_MIPMAP = DDSCAPS_COMPLEX | DDSCAPS_MIPMAP\nDDS_SURFACE_FLAGS_CUBEMAP = DDSCAPS_COMPLEX\n\nDDS_CUBEMAP_POSITIVEX = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX\nDDS_CUBEMAP_NEGATIVEX = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX\nDDS_CUBEMAP_POSITIVEY = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY\nDDS_CUBEMAP_NEGATIVEY = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY\nDDS_CUBEMAP_POSITIVEZ = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ\nDDS_CUBEMAP_NEGATIVEZ = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ\n\n\n# DXT1\nDXT1_FOURCC = 0x31545844\n\n# DXT3\nDXT3_FOURCC = 0x33545844\n\n# DXT5\nDXT5_FOURCC = 0x35545844\n\n\n# dxgiformat.h\n\nDXGI_FORMAT_BC7_TYPELESS = 97\nDXGI_FORMAT_BC7_UNORM = 98\nDXGI_FORMAT_BC7_UNORM_SRGB = 99\n\n\nclass DdsImageFile(ImageFile.ImageFile):\n    format = \"DDS\"\n    format_description = \"DirectDraw Surface\"\n\n    def _open(self):\n        magic, header_size = struct.unpack(\"<II\", self.fp.read(8))\n        if header_size != 124:\n            raise IOError(\"Unsupported header size %r\" % (header_size))\n        header_bytes = self.fp.read(header_size - 4)\n        if len(header_bytes) != 120:\n            raise IOError(\"Incomplete header: %s bytes\" % len(header_bytes))\n        header = BytesIO(header_bytes)\n\n        flags, height, width = struct.unpack(\"<3I\", header.read(12))\n        self._size = (width, height)\n        self.mode = \"RGBA\"\n\n        pitch, depth, mipmaps = struct.unpack(\"<3I\", header.read(12))\n        struct.unpack(\"<11I\", header.read(44))  # reserved\n\n        # pixel format\n        pfsize, pfflags = struct.unpack(\"<2I\", header.read(8))\n        fourcc = header.read(4)\n        (bitcount,) = struct.unpack(\"<I\", header.read(4))\n        masks = struct.unpack(\"<4I\", header.read(16))\n        if pfflags & 0x40:\n            # DDPF_RGB - Texture contains uncompressed RGB data\n            masks = {mask: [\"R\", \"G\", \"B\", \"A\"][i] for i, mask in enumerate(masks)}\n            rawmode = \"\"\n            if bitcount == 32:\n                rawmode += masks[0xFF000000]\n            rawmode += masks[0xFF0000] + masks[0xFF00] + masks[0xFF]\n\n            self.tile = [(\"raw\", (0, 0) + self.size, 0, (rawmode, 0, 1))]\n        else:\n            data_start = header_size + 4\n            n = 0\n            if fourcc == b\"DXT1\":\n                self.pixel_format = \"DXT1\"\n                n = 1\n            elif fourcc == b\"DXT3\":\n                self.pixel_format = \"DXT3\"\n                n = 2\n            elif fourcc == b\"DXT5\":\n                self.pixel_format = \"DXT5\"\n                n = 3\n            elif fourcc == b\"DX10\":\n                data_start += 20\n                # ignoring flags which pertain to volume textures and cubemaps\n                dxt10 = BytesIO(self.fp.read(20))\n                dxgi_format, dimension = struct.unpack(\"<II\", dxt10.read(8))\n                if dxgi_format in (DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM):\n                    self.pixel_format = \"BC7\"\n                    n = 7\n                elif dxgi_format == DXGI_FORMAT_BC7_UNORM_SRGB:\n                    self.pixel_format = \"BC7\"\n                    self.im_info[\"gamma\"] = 1 / 2.2\n                    n = 7\n                else:\n                    raise NotImplementedError(\n                        \"Unimplemented DXGI format %d\" % (dxgi_format)\n                    )\n            else:\n                raise NotImplementedError(\"Unimplemented pixel format %r\" % (fourcc))\n\n            self.tile = [(\"bcn\", (0, 0) + self.size, data_start, (n))]\n\n    def load_seek(self, pos):\n        pass\n\n\ndef _validate(prefix):\n    return prefix[:4] == b\"DDS \"\n\n\nImage.register_open(DdsImageFile.format, DdsImageFile, _validate)\nImage.register_extension(DdsImageFile.format, \".dds\")\n", "path": "src/PIL/DdsImagePlugin.py"}], "after_files": [{"content": "\"\"\"\nA Pillow loader for .dds files (S3TC-compressed aka DXTC)\nJerome Leclanche <jerome@leclan.ch>\n\nDocumentation:\n  https://web.archive.org/web/20170802060935/http://oss.sgi.com/projects/ogl-sample/registry/EXT/texture_compression_s3tc.txt\n\nThe contents of this file are hereby released in the public domain (CC0)\nFull text of the CC0 license:\n  https://creativecommons.org/publicdomain/zero/1.0/\n\"\"\"\n\nimport struct\nfrom io import BytesIO\n\nfrom . import Image, ImageFile\n\n# Magic (\"DDS \")\nDDS_MAGIC = 0x20534444\n\n# DDS flags\nDDSD_CAPS = 0x1\nDDSD_HEIGHT = 0x2\nDDSD_WIDTH = 0x4\nDDSD_PITCH = 0x8\nDDSD_PIXELFORMAT = 0x1000\nDDSD_MIPMAPCOUNT = 0x20000\nDDSD_LINEARSIZE = 0x80000\nDDSD_DEPTH = 0x800000\n\n# DDS caps\nDDSCAPS_COMPLEX = 0x8\nDDSCAPS_TEXTURE = 0x1000\nDDSCAPS_MIPMAP = 0x400000\n\nDDSCAPS2_CUBEMAP = 0x200\nDDSCAPS2_CUBEMAP_POSITIVEX = 0x400\nDDSCAPS2_CUBEMAP_NEGATIVEX = 0x800\nDDSCAPS2_CUBEMAP_POSITIVEY = 0x1000\nDDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000\nDDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000\nDDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000\nDDSCAPS2_VOLUME = 0x200000\n\n# Pixel Format\nDDPF_ALPHAPIXELS = 0x1\nDDPF_ALPHA = 0x2\nDDPF_FOURCC = 0x4\nDDPF_PALETTEINDEXED8 = 0x20\nDDPF_RGB = 0x40\nDDPF_LUMINANCE = 0x20000\n\n\n# dds.h\n\nDDS_FOURCC = DDPF_FOURCC\nDDS_RGB = DDPF_RGB\nDDS_RGBA = DDPF_RGB | DDPF_ALPHAPIXELS\nDDS_LUMINANCE = DDPF_LUMINANCE\nDDS_LUMINANCEA = DDPF_LUMINANCE | DDPF_ALPHAPIXELS\nDDS_ALPHA = DDPF_ALPHA\nDDS_PAL8 = DDPF_PALETTEINDEXED8\n\nDDS_HEADER_FLAGS_TEXTURE = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT\nDDS_HEADER_FLAGS_MIPMAP = DDSD_MIPMAPCOUNT\nDDS_HEADER_FLAGS_VOLUME = DDSD_DEPTH\nDDS_HEADER_FLAGS_PITCH = DDSD_PITCH\nDDS_HEADER_FLAGS_LINEARSIZE = DDSD_LINEARSIZE\n\nDDS_HEIGHT = DDSD_HEIGHT\nDDS_WIDTH = DDSD_WIDTH\n\nDDS_SURFACE_FLAGS_TEXTURE = DDSCAPS_TEXTURE\nDDS_SURFACE_FLAGS_MIPMAP = DDSCAPS_COMPLEX | DDSCAPS_MIPMAP\nDDS_SURFACE_FLAGS_CUBEMAP = DDSCAPS_COMPLEX\n\nDDS_CUBEMAP_POSITIVEX = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX\nDDS_CUBEMAP_NEGATIVEX = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX\nDDS_CUBEMAP_POSITIVEY = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY\nDDS_CUBEMAP_NEGATIVEY = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY\nDDS_CUBEMAP_POSITIVEZ = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ\nDDS_CUBEMAP_NEGATIVEZ = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ\n\n\n# DXT1\nDXT1_FOURCC = 0x31545844\n\n# DXT3\nDXT3_FOURCC = 0x33545844\n\n# DXT5\nDXT5_FOURCC = 0x35545844\n\n\n# dxgiformat.h\n\nDXGI_FORMAT_BC7_TYPELESS = 97\nDXGI_FORMAT_BC7_UNORM = 98\nDXGI_FORMAT_BC7_UNORM_SRGB = 99\n\n\nclass DdsImageFile(ImageFile.ImageFile):\n    format = \"DDS\"\n    format_description = \"DirectDraw Surface\"\n\n    def _open(self):\n        magic, header_size = struct.unpack(\"<II\", self.fp.read(8))\n        if header_size != 124:\n            raise IOError(\"Unsupported header size %r\" % (header_size))\n        header_bytes = self.fp.read(header_size - 4)\n        if len(header_bytes) != 120:\n            raise IOError(\"Incomplete header: %s bytes\" % len(header_bytes))\n        header = BytesIO(header_bytes)\n\n        flags, height, width = struct.unpack(\"<3I\", header.read(12))\n        self._size = (width, height)\n        self.mode = \"RGBA\"\n\n        pitch, depth, mipmaps = struct.unpack(\"<3I\", header.read(12))\n        struct.unpack(\"<11I\", header.read(44))  # reserved\n\n        # pixel format\n        pfsize, pfflags = struct.unpack(\"<2I\", header.read(8))\n        fourcc = header.read(4)\n        (bitcount,) = struct.unpack(\"<I\", header.read(4))\n        masks = struct.unpack(\"<4I\", header.read(16))\n        if pfflags & 0x40:\n            # DDPF_RGB - Texture contains uncompressed RGB data\n            masks = {mask: [\"R\", \"G\", \"B\", \"A\"][i] for i, mask in enumerate(masks)}\n            rawmode = \"\"\n            if bitcount == 32:\n                rawmode += masks[0xFF000000]\n            rawmode += masks[0xFF0000] + masks[0xFF00] + masks[0xFF]\n\n            self.tile = [(\"raw\", (0, 0) + self.size, 0, (rawmode, 0, 1))]\n        else:\n            data_start = header_size + 4\n            n = 0\n            if fourcc == b\"DXT1\":\n                self.pixel_format = \"DXT1\"\n                n = 1\n            elif fourcc == b\"DXT3\":\n                self.pixel_format = \"DXT3\"\n                n = 2\n            elif fourcc == b\"DXT5\":\n                self.pixel_format = \"DXT5\"\n                n = 3\n            elif fourcc == b\"DX10\":\n                data_start += 20\n                # ignoring flags which pertain to volume textures and cubemaps\n                dxt10 = BytesIO(self.fp.read(20))\n                dxgi_format, dimension = struct.unpack(\"<II\", dxt10.read(8))\n                if dxgi_format in (DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM):\n                    self.pixel_format = \"BC7\"\n                    n = 7\n                elif dxgi_format == DXGI_FORMAT_BC7_UNORM_SRGB:\n                    self.pixel_format = \"BC7\"\n                    self.info[\"gamma\"] = 1 / 2.2\n                    n = 7\n                else:\n                    raise NotImplementedError(\n                        \"Unimplemented DXGI format %d\" % (dxgi_format)\n                    )\n            else:\n                raise NotImplementedError(\"Unimplemented pixel format %r\" % (fourcc))\n\n            self.tile = [(\"bcn\", (0, 0) + self.size, data_start, (n))]\n\n    def load_seek(self, pos):\n        pass\n\n\ndef _validate(prefix):\n    return prefix[:4] == b\"DDS \"\n\n\nImage.register_open(DdsImageFile.format, DdsImageFile, _validate)\nImage.register_extension(DdsImageFile.format, \".dds\")\n", "path": "src/PIL/DdsImagePlugin.py"}]}