Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/PIL/CurImagePlugin.py: 65%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

52 statements  

1# 

2# The Python Imaging Library. 

3# $Id$ 

4# 

5# Windows Cursor support for PIL 

6# 

7# notes: 

8# uses BmpImagePlugin.py to read the bitmap data. 

9# 

10# history: 

11# 96-05-27 fl Created 

12# 

13# Copyright (c) Secret Labs AB 1997. 

14# Copyright (c) Fredrik Lundh 1996. 

15# 

16# See the README file for information on usage and redistribution. 

17# 

18from __future__ import annotations 

19 

20from . import BmpImagePlugin, Image, ImageOps 

21from ._binary import i16le as i16 

22from ._binary import i32le as i32 

23 

24# 

25# -------------------------------------------------------------------- 

26 

27 

28def _accept(prefix: bytes) -> bool: 

29 return prefix.startswith(b"\0\0\2\0") 

30 

31 

32## 

33# Image plugin for Windows Cursor files. 

34 

35 

36class CurImageFile(BmpImagePlugin.BmpImageFile): 

37 format = "CUR" 

38 format_description = "Windows Cursor" 

39 

40 def _open(self) -> None: 

41 assert self.fp is not None 

42 offset = self.fp.tell() 

43 

44 # check magic 

45 s = self.fp.read(6) 

46 if not _accept(s): 

47 msg = "not a CUR file" 

48 raise SyntaxError(msg) 

49 

50 # pick the largest cursor in the file 

51 m = b"" 

52 for i in range(i16(s, 4)): 

53 s = self.fp.read(16) 

54 if not m: 

55 m = s 

56 elif s[0] > m[0] and s[1] > m[1]: 

57 m = s 

58 if not m: 

59 msg = "No cursors were found" 

60 raise TypeError(msg) 

61 

62 # load as bitmap 

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" 

68 

69 # patch up the bitmap height 

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 ) 

96 

97 

98# 

99# -------------------------------------------------------------------- 

100 

101Image.register_open(CurImageFile.format, CurImageFile, _accept) 

102 

103Image.register_extension(CurImageFile.format, ".cur")