Skip to content

Commit 26f58e7

Browse files
committed
Optimise ImageMode.getmode
1 parent ef0b0d2 commit 26f58e7

1 file changed

Lines changed: 55 additions & 56 deletions

File tree

src/PIL/ImageMode.py

Lines changed: 55 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
from __future__ import annotations
1616

1717
import sys
18-
19-
# mode descriptor cache
20-
_modes = None
18+
from functools import lru_cache
2119

2220

2321
class ModeDescriptor:
@@ -41,58 +39,59 @@ def __str__(self) -> str:
4139
return self.mode
4240

4341

42+
@lru_cache
4443
def getmode(mode: str) -> ModeDescriptor:
4544
"""Gets a mode descriptor for the given mode."""
46-
global _modes
47-
if not _modes:
48-
# initialize mode cache
49-
modes = {}
50-
endian = "<" if sys.byteorder == "little" else ">"
51-
for m, (basemode, basetype, bands, typestr) in {
52-
# core modes
53-
# Bits need to be extended to bytes
54-
"1": ("L", "L", ("1",), "|b1"),
55-
"L": ("L", "L", ("L",), "|u1"),
56-
"I": ("L", "I", ("I",), endian + "i4"),
57-
"F": ("L", "F", ("F",), endian + "f4"),
58-
"P": ("P", "L", ("P",), "|u1"),
59-
"RGB": ("RGB", "L", ("R", "G", "B"), "|u1"),
60-
"RGBX": ("RGB", "L", ("R", "G", "B", "X"), "|u1"),
61-
"RGBA": ("RGB", "L", ("R", "G", "B", "A"), "|u1"),
62-
"CMYK": ("RGB", "L", ("C", "M", "Y", "K"), "|u1"),
63-
"YCbCr": ("RGB", "L", ("Y", "Cb", "Cr"), "|u1"),
64-
# UNDONE - unsigned |u1i1i1
65-
"LAB": ("RGB", "L", ("L", "A", "B"), "|u1"),
66-
"HSV": ("RGB", "L", ("H", "S", "V"), "|u1"),
67-
# extra experimental modes
68-
"RGBa": ("RGB", "L", ("R", "G", "B", "a"), "|u1"),
69-
"BGR;15": ("RGB", "L", ("B", "G", "R"), "|u1"),
70-
"BGR;16": ("RGB", "L", ("B", "G", "R"), "|u1"),
71-
"BGR;24": ("RGB", "L", ("B", "G", "R"), "|u1"),
72-
"LA": ("L", "L", ("L", "A"), "|u1"),
73-
"La": ("L", "L", ("L", "a"), "|u1"),
74-
"PA": ("RGB", "L", ("P", "A"), "|u1"),
75-
}.items():
76-
modes[m] = ModeDescriptor(m, bands, basemode, basetype, typestr)
77-
# mapping modes
78-
for i16mode, typestr in {
79-
# I;16 == I;16L, and I;32 == I;32L
80-
"I;16": "<u2",
81-
"I;16S": "<i2",
82-
"I;16L": "<u2",
83-
"I;16LS": "<i2",
84-
"I;16B": ">u2",
85-
"I;16BS": ">i2",
86-
"I;16N": endian + "u2",
87-
"I;16NS": endian + "i2",
88-
"I;32": "<u4",
89-
"I;32B": ">u4",
90-
"I;32L": "<u4",
91-
"I;32S": "<i4",
92-
"I;32BS": ">i4",
93-
"I;32LS": "<i4",
94-
}.items():
95-
modes[i16mode] = ModeDescriptor(i16mode, ("I",), "L", "L", typestr)
96-
# set global mode cache atomically
97-
_modes = modes
98-
return _modes[mode]
45+
# if not _modes:
46+
# initialize mode cache
47+
endian = "<" if sys.byteorder == "little" else ">"
48+
49+
modes = {
50+
# core modes
51+
# Bits need to be extended to bytes
52+
"1": ("L", "L", ("1",), "|b1"),
53+
"L": ("L", "L", ("L",), "|u1"),
54+
"I": ("L", "I", ("I",), endian + "i4"),
55+
"F": ("L", "F", ("F",), endian + "f4"),
56+
"P": ("P", "L", ("P",), "|u1"),
57+
"RGB": ("RGB", "L", ("R", "G", "B"), "|u1"),
58+
"RGBX": ("RGB", "L", ("R", "G", "B", "X"), "|u1"),
59+
"RGBA": ("RGB", "L", ("R", "G", "B", "A"), "|u1"),
60+
"CMYK": ("RGB", "L", ("C", "M", "Y", "K"), "|u1"),
61+
"YCbCr": ("RGB", "L", ("Y", "Cb", "Cr"), "|u1"),
62+
# UNDONE - unsigned |u1i1i1
63+
"LAB": ("RGB", "L", ("L", "A", "B"), "|u1"),
64+
"HSV": ("RGB", "L", ("H", "S", "V"), "|u1"),
65+
# extra experimental modes
66+
"RGBa": ("RGB", "L", ("R", "G", "B", "a"), "|u1"),
67+
"BGR;15": ("RGB", "L", ("B", "G", "R"), "|u1"),
68+
"BGR;16": ("RGB", "L", ("B", "G", "R"), "|u1"),
69+
"BGR;24": ("RGB", "L", ("B", "G", "R"), "|u1"),
70+
"LA": ("L", "L", ("L", "A"), "|u1"),
71+
"La": ("L", "L", ("L", "a"), "|u1"),
72+
"PA": ("RGB", "L", ("P", "A"), "|u1"),
73+
}
74+
if mode in modes:
75+
base_mode, base_type, bands, type_str = modes[mode]
76+
return ModeDescriptor(mode, bands, base_mode, base_type, type_str)
77+
78+
mapping_modes = {
79+
# I;16 == I;16L, and I;32 == I;32L
80+
"I;16": "<u2",
81+
"I;16S": "<i2",
82+
"I;16L": "<u2",
83+
"I;16LS": "<i2",
84+
"I;16B": ">u2",
85+
"I;16BS": ">i2",
86+
"I;16N": endian + "u2",
87+
"I;16NS": endian + "i2",
88+
"I;32": "<u4",
89+
"I;32B": ">u4",
90+
"I;32L": "<u4",
91+
"I;32S": "<i4",
92+
"I;32BS": ">i4",
93+
"I;32LS": "<i4",
94+
}
95+
96+
type_str = mapping_modes[mode]
97+
return ModeDescriptor(mode, ("I",), "L", "L", type_str)

0 commit comments

Comments
 (0)