| 61 | _close_exclusive_fp_after_loading = False |
| 62 | |
| 63 | def _open(self) -> None: |
| 64 | assert self.fp is not None |
| 65 | read = self.fp.read |
| 66 | |
| 67 | # |
| 68 | # header |
| 69 | |
| 70 | s = read(26) |
| 71 | if not _accept(s) or i16(s, 4) != 1: |
| 72 | msg = "not a PSD file" |
| 73 | raise SyntaxError(msg) |
| 74 | |
| 75 | psd_bits = i16(s, 22) |
| 76 | psd_channels = i16(s, 12) |
| 77 | psd_mode = i16(s, 24) |
| 78 | |
| 79 | mode, channels = MODES[(psd_mode, psd_bits)] |
| 80 | |
| 81 | if channels > psd_channels: |
| 82 | msg = "not enough channels" |
| 83 | raise OSError(msg) |
| 84 | if mode == "RGB" and psd_channels == 4: |
| 85 | mode = "RGBA" |
| 86 | channels = 4 |
| 87 | |
| 88 | self._mode = mode |
| 89 | self._size = i32(s, 18), i32(s, 14) |
| 90 | |
| 91 | # |
| 92 | # color mode data |
| 93 | |
| 94 | size = i32(read(4)) |
| 95 | if size: |
| 96 | data = read(size) |
| 97 | if mode == "P" and size == 768: |
| 98 | self.palette = ImagePalette.raw("RGB;L", data) |
| 99 | |
| 100 | # |
| 101 | # image resources |
| 102 | |
| 103 | self.resources = [] |
| 104 | |
| 105 | size = i32(read(4)) |
| 106 | if size: |
| 107 | # load resources |
| 108 | end = self.fp.tell() + size |
| 109 | while self.fp.tell() < end: |
| 110 | read(4) # signature |
| 111 | id = i16(read(2)) |
| 112 | name = read(i8(read(1))) |
| 113 | if not (len(name) & 1): |
| 114 | read(1) # padding |
| 115 | data = read(i32(read(4))) |
| 116 | if len(data) & 1: |
| 117 | read(1) # padding |
| 118 | self.resources.append((id, name, data)) |
| 119 | if id == 1039: # ICC profile |
| 120 | self.info["icc_profile"] = data |