Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.10/site-packages/django/core/files/images.py: 20%

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

51 statements  

1""" 

2Utility functions for handling images. 

3 

4Requires Pillow as you might imagine. 

5""" 

6 

7import struct 

8import zlib 

9 

10from django.core.files import File 

11 

12 

13class ImageFile(File): 

14 """ 

15 A mixin for use alongside django.core.files.base.File, which provides 

16 additional features for dealing with images. 

17 """ 

18 

19 @property 

20 def width(self): 

21 return self._get_image_dimensions()[0] 

22 

23 @property 

24 def height(self): 

25 return self._get_image_dimensions()[1] 

26 

27 def _get_image_dimensions(self): 

28 if not hasattr(self, "_dimensions_cache"): 

29 close = self.closed 

30 self.open() 

31 self._dimensions_cache = get_image_dimensions(self, close=close) 

32 return self._dimensions_cache 

33 

34 

35def get_image_dimensions(file_or_path, close=False): 

36 """ 

37 Return the (width, height) of an image, given an open file or a path. Set 

38 'close' to True to close the file at the end if it is initially in an open 

39 state. 

40 """ 

41 from PIL import ImageFile as PillowImageFile 

42 

43 p = PillowImageFile.Parser() 

44 if hasattr(file_or_path, "read"): 

45 file = file_or_path 

46 file_pos = file.tell() 

47 file.seek(0) 

48 else: 

49 try: 

50 file = open(file_or_path, "rb") 

51 except OSError: 

52 return (None, None) 

53 close = True 

54 try: 

55 # Most of the time Pillow only needs a small chunk to parse the image 

56 # and get the dimensions, but with some TIFF files Pillow needs to 

57 # parse the whole file. 

58 chunk_size = 1024 

59 while 1: 

60 data = file.read(chunk_size) 

61 if not data: 

62 break 

63 try: 

64 p.feed(data) 

65 except zlib.error as e: 

66 # ignore zlib complaining on truncated stream, just feed more 

67 # data to parser (ticket #19457). 

68 if e.args[0].startswith("Error -5"): 

69 pass 

70 else: 

71 raise 

72 except struct.error: 

73 # Ignore PIL failing on a too short buffer when reads return 

74 # less bytes than expected. Skip and feed more data to the 

75 # parser (ticket #24544). 

76 pass 

77 except RuntimeError: 

78 # e.g. "RuntimeError: could not create decoder object" for 

79 # WebP files. A different chunk_size may work. 

80 pass 

81 if p.image: 

82 return p.image.size 

83 chunk_size *= 2 

84 return (None, None) 

85 finally: 

86 if close: 

87 file.close() 

88 else: 

89 file.seek(file_pos)