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

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

53 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 

20__lazy_modules__ = {"PIL._binary"} 

21 

22from . import BmpImagePlugin, Image, ImageOps 

23from ._binary import i16le as i16 

24from ._binary import i32le as i32 

25 

26# 

27# -------------------------------------------------------------------- 

28 

29 

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

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

32 

33 

34## 

35# Image plugin for Windows Cursor files. 

36 

37 

38class CurImageFile(BmpImagePlugin.BmpImageFile): 

39 format = "CUR" 

40 format_description = "Windows Cursor" 

41 

42 def _open(self) -> None: 

43 assert self.fp is not None 

44 offset = self.fp.tell() 

45 

46 # check magic 

47 s = self.fp.read(6) 

48 if not _accept(s): 

49 msg = "not a CUR file" 

50 raise SyntaxError(msg) 

51 

52 # pick the largest cursor in the file 

53 m = b"" 

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

55 s = self.fp.read(16) 

56 if not m: 

57 m = s 

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

59 m = s 

60 if not m: 

61 msg = "No cursors were found" 

62 raise TypeError(msg) 

63 

64 # load as bitmap 

65 self._bitmap(i32(m, 12) + offset) 

66 self._masked = self.mode in ("1", "L") 

67 if self._masked: 

68 self._rawmode = self.mode 

69 self._mode = "LA" 

70 

71 # patch up the bitmap height 

72 self._size = self.width, self.height // 2 

73 if not self._masked: 

74 self.tile = [self.tile[0]._replace(extents=None)] 

75 

76 def load_prepare(self) -> None: 

77 if self._masked: 

78 self._mode = self._rawmode 

79 self._size = self.width, self.height * 2 

80 super().load_prepare() 

81 

82 def load_end(self) -> None: 

83 if not self._masked: 

84 return 

85 self._mode = "LA" 

86 new_height = self.height // 2 

87 

88 and_mask = self.im.crop((0, 0, self.width, new_height)) 

89 xor_mask = self.im.crop((0, new_height, self.width, self.height)) 

90 

91 self._size = self.width, new_height 

92 self._im = Image.core.fill(self.mode, self.size) 

93 self._im.paste( 

94 xor_mask.convert(self.mode), 

95 (0, 0, *self.size), 

96 ImageOps.invert(Image.Image()._new(and_mask)).im, 

97 ) 

98 

99 

100# 

101# -------------------------------------------------------------------- 

102 

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

104 

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