Coverage for src/rtflite/figure.py: 97%

29 statements  

« prev     ^ index     » next       coverage.py v7.10.3, created at 2025-08-14 16:35 +0000

1"""RTF Figure handling utilities. 

2 

3This module provides functions for reading and processing images 

4for embedding in RTF documents. 

5""" 

6 

7import mimetypes 

8from pathlib import Path 

9 

10 

11def rtf_read_figure( 

12 file_paths: str | Path | list[str | Path], 

13) -> tuple[list[bytes], list[str]]: 

14 """Read image files and return their binary data with format information. 

15 

16 This function reads image files from disk and prepares them for embedding 

17 in RTF documents. It supports PNG, JPEG, and EMF formats. 

18 

19 Args: 

20 file_paths: Single file path or list of file paths to image files 

21 

22 Returns: 

23 Tuple of (figure_data, figure_formats) where: 

24 - figure_data: List of image binary data as bytes 

25 - figure_formats: List of format strings ('png', 'jpeg', 'emf') 

26 

27 Raises: 

28 FileNotFoundError: If any image file cannot be found 

29 ValueError: If image format is not supported 

30 """ 

31 # Ensure file_paths is a list 

32 if isinstance(file_paths, (str, Path)): 

33 file_paths = [file_paths] 

34 

35 figure_data = [] 

36 figure_formats = [] 

37 

38 for file_path in file_paths: 

39 path = Path(file_path) 

40 

41 # Check if file exists 

42 if not path.exists(): 

43 raise FileNotFoundError(f"Image file not found: {file_path}") 

44 

45 # Determine format and read data 

46 img_format = _determine_image_format(path) 

47 data = _read_image_data(path) 

48 

49 figure_data.append(data) 

50 figure_formats.append(img_format) 

51 

52 return figure_data, figure_formats 

53 

54 

55def _determine_image_format(path: Path) -> str: 

56 """Determine image format from file extension or MIME type.""" 

57 extension = path.suffix.lower() 

58 format_map = {".png": "png", ".jpg": "jpeg", ".jpeg": "jpeg", ".emf": "emf"} 

59 

60 if extension in format_map: 

61 return format_map[extension] 

62 

63 # Fallback to MIME type detection 

64 mime_type, _ = mimetypes.guess_type(str(path)) 

65 mime_to_format = {"image/png": "png", "image/jpeg": "jpeg", "image/jpg": "jpeg"} 

66 

67 if mime_type in mime_to_format: 

68 return mime_to_format[mime_type] 

69 

70 raise ValueError( 

71 f"Unsupported image format: {extension}. Supported formats: PNG, JPEG, EMF" 

72 ) 

73 

74 

75def _read_image_data(path: Path) -> bytes: 

76 """Read binary data from image file.""" 

77 with open(path, "rb") as f: 

78 return f.read()