|
17 | 17 | # |
18 | 18 | from __future__ import annotations |
19 | 19 |
|
20 | | -from . import BmpImagePlugin, Image |
| 20 | +from . import BmpImagePlugin, Image, ImageOps |
21 | 21 | from ._binary import i16le as i16 |
22 | 22 | from ._binary import i32le as i32 |
23 | 23 |
|
@@ -61,10 +61,38 @@ def _open(self) -> None: |
61 | 61 |
|
62 | 62 | # load as bitmap |
63 | 63 | self._bitmap(i32(m, 12) + offset) |
| 64 | + self._masked = self.mode in ("1", "L") |
| 65 | + if self._masked: |
| 66 | + self._rawmode = self.mode |
| 67 | + self._mode = "LA" |
64 | 68 |
|
65 | 69 | # patch up the bitmap height |
66 | | - self._size = self.size[0], self.size[1] // 2 |
67 | | - self.tile = [self.tile[0]._replace(extents=(0, 0) + self.size)] |
| 70 | + self._size = self.width, self.height // 2 |
| 71 | + if not self._masked: |
| 72 | + self.tile = [self.tile[0]._replace(extents=(0, 0) + self.size)] |
| 73 | + |
| 74 | + def load_prepare(self) -> None: |
| 75 | + if self._masked: |
| 76 | + self._mode = self._rawmode |
| 77 | + self._size = self.width, self.height * 2 |
| 78 | + super().load_prepare() |
| 79 | + |
| 80 | + def load_end(self) -> None: |
| 81 | + if not self._masked: |
| 82 | + return |
| 83 | + self._mode = "LA" |
| 84 | + new_height = self.height // 2 |
| 85 | + |
| 86 | + and_mask = self.im.crop((0, 0, self.width, new_height)) |
| 87 | + xor_mask = self.im.crop((0, new_height, self.width, self.height)) |
| 88 | + |
| 89 | + self._size = self.width, new_height |
| 90 | + self._im = Image.core.fill(self.mode, self.size) |
| 91 | + self._im.paste( |
| 92 | + xor_mask.convert(self.mode), |
| 93 | + (0, 0) + self.size, |
| 94 | + ImageOps.invert(Image.Image()._new(and_mask)).im, |
| 95 | + ) |
68 | 96 |
|
69 | 97 |
|
70 | 98 | # |
|
0 commit comments