1#
2# The Python Imaging Library.
3# $Id$
4#
5# Microsoft Image Composer support for PIL
6#
7# Notes:
8# uses TiffImagePlugin.py to read the actual image streams
9#
10# History:
11# 97-01-20 fl Created
12#
13# Copyright (c) Secret Labs AB 1997.
14# Copyright (c) Fredrik Lundh 1997.
15#
16# See the README file for information on usage and redistribution.
17#
18from __future__ import annotations
19
20import olefile
21
22from . import Image, TiffImagePlugin
23
24#
25# --------------------------------------------------------------------
26
27
28def _accept(prefix: bytes) -> bool:
29 return prefix.startswith(olefile.MAGIC)
30
31
32##
33# Image plugin for Microsoft's Image Composer file format.
34
35
36class MicImageFile(TiffImagePlugin.TiffImageFile):
37 format = "MIC"
38 format_description = "Microsoft Image Composer"
39 _close_exclusive_fp_after_loading = False
40
41 def _open(self) -> None:
42 # read the OLE directory and see if this is a likely
43 # to be a Microsoft Image Composer file
44
45 try:
46 self.ole = olefile.OleFileIO(self.fp)
47 except OSError as e:
48 msg = "not an MIC file; invalid OLE file"
49 raise SyntaxError(msg) from e
50
51 # find ACI subfiles with Image members (maybe not the
52 # best way to identify MIC files, but what the... ;-)
53
54 self.images = [
55 path
56 for path in self.ole.listdir()
57 if path[1:] and path[0].endswith(".ACI") and path[1] == "Image"
58 ]
59
60 # if we didn't find any images, this is probably not
61 # an MIC file.
62 if not self.images:
63 msg = "not an MIC file; no image entries"
64 raise SyntaxError(msg)
65
66 self.frame = -1
67 self._n_frames = len(self.images)
68 self.is_animated = self._n_frames > 1
69
70 self.__fp = self.fp
71 self.seek(0)
72
73 def seek(self, frame: int) -> None:
74 if not self._seek_check(frame):
75 return
76 filename = self.images[frame]
77 self.fp = self.ole.openstream(filename)
78
79 TiffImagePlugin.TiffImageFile._open(self)
80
81 self.frame = frame
82
83 def tell(self) -> int:
84 return self.frame
85
86 def close(self) -> None:
87 self.__fp.close()
88 self.ole.close()
89 super().close()
90
91 def __exit__(self, *args: object) -> None:
92 self.__fp.close()
93 self.ole.close()
94 super().__exit__()
95
96
97#
98# --------------------------------------------------------------------
99
100Image.register_open(MicImageFile.format, MicImageFile, _accept)
101
102Image.register_extension(MicImageFile.format, ".mic")