openconvert 0.1.0__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,214 +0,0 @@
1
- """
2
- Image converter module for handling image format conversions.
3
- """
4
-
5
- import logging
6
- from pathlib import Path
7
- from typing import Union, Optional, Dict, Any
8
-
9
- logger = logging.getLogger(__name__)
10
-
11
- # Define supported conversions
12
- SUPPORTED_CONVERSIONS = {
13
- 'png': ['jpg', 'jpeg', 'bmp', 'tiff', 'gif', 'pdf', 'ico', 'svg', 'webp'],
14
- 'jpg': ['png', 'bmp', 'tiff', 'gif', 'pdf', 'ico', 'svg', 'webp'],
15
- 'jpeg': ['png', 'bmp', 'tiff', 'gif', 'pdf', 'ico', 'svg', 'webp'],
16
- 'bmp': ['png', 'jpg', 'tiff', 'gif', 'pdf', 'ico', 'webp'],
17
- 'gif': ['png', 'jpg', 'bmp', 'tiff', 'pdf', 'ico', 'webp'],
18
- 'tiff': ['png', 'jpg', 'bmp', 'gif', 'pdf', 'webp'],
19
- 'ico': ['png', 'jpg', 'bmp', 'tiff', 'gif', 'webp'],
20
- 'svg': ['png', 'jpg', 'bmp', 'tiff', 'pdf', 'webp'],
21
- 'webp': ['png', 'jpg', 'bmp', 'tiff', 'gif', 'pdf']
22
- }
23
-
24
- def convert(
25
- filepath: Union[str, Path],
26
- source_format: str,
27
- target_format: str,
28
- output_path: Union[str, Path],
29
- options: Optional[Dict[str, Any]] = None
30
- ) -> str:
31
- """
32
- Convert an image from one format to another.
33
-
34
- Args:
35
- filepath: Path to the source image file
36
- source_format: Source image format
37
- target_format: Target image format
38
- output_path: Path to save the converted image
39
- options: Additional conversion options
40
-
41
- Returns:
42
- Path to the converted image
43
-
44
- Raises:
45
- ValueError: If the conversion is not supported
46
- RuntimeError: If the conversion fails
47
- """
48
- if options is None:
49
- options = {}
50
-
51
- # Check if conversion is supported
52
- if target_format not in SUPPORTED_CONVERSIONS.get(source_format, []):
53
- raise ValueError(f"Conversion from {source_format} to {target_format} is not supported")
54
-
55
- filepath = Path(filepath)
56
- output_path = Path(output_path)
57
-
58
- try:
59
- # Use Pillow for most image conversions
60
- from PIL import Image
61
-
62
- # Special handling for SVG conversions
63
- if source_format == 'svg':
64
- if target_format in ['png', 'jpg', 'jpeg', 'bmp', 'tiff', 'webp']:
65
- return _convert_svg_to_raster(filepath, target_format, output_path, options)
66
- elif target_format == 'pdf':
67
- return _convert_svg_to_pdf(filepath, output_path, options)
68
-
69
- # Special handling for PDF output
70
- if target_format == 'pdf':
71
- return _convert_to_pdf(filepath, source_format, output_path, options)
72
-
73
- # Standard image conversion using Pillow
74
- with Image.open(filepath) as img:
75
- # Apply any image processing options
76
- if 'resize' in options:
77
- width, height = options['resize']
78
- img = img.resize((width, height), Image.LANCZOS)
79
-
80
- if 'rotate' in options:
81
- img = img.rotate(options['rotate'])
82
-
83
- # Convert palette mode (P) to RGB for formats that don't support it
84
- if img.mode == 'P' and target_format in ['jpg', 'jpeg']:
85
- img = img.convert('RGB')
86
-
87
- if 'quality' in options and target_format in ['jpg', 'jpeg', 'webp']:
88
- img.save(output_path, quality=options['quality'])
89
- else:
90
- img.save(output_path)
91
-
92
- logger.info(f"Successfully converted {filepath} to {output_path}")
93
- return str(output_path)
94
-
95
- except Exception as e:
96
- logger.error(f"Error converting {filepath} to {target_format}: {str(e)}")
97
- raise RuntimeError(f"Failed to convert {filepath} to {target_format}: {str(e)}")
98
-
99
- def _convert_svg_to_raster(
100
- filepath: Path,
101
- target_format: str,
102
- output_path: Path,
103
- options: Dict[str, Any]
104
- ) -> str:
105
- """Convert SVG to raster formats like PNG, JPG, etc."""
106
- try:
107
- # Try using cairosvg for SVG conversion
108
- import cairosvg
109
-
110
- width = options.get('width', 800)
111
- height = options.get('height', 600)
112
-
113
- if target_format == 'png':
114
- cairosvg.svg2png(url=str(filepath), write_to=str(output_path),
115
- width=width, height=height)
116
- elif target_format in ['jpg', 'jpeg']:
117
- # Convert to PNG first, then to JPG
118
- temp_png = output_path.with_suffix('.png')
119
- cairosvg.svg2png(url=str(filepath), write_to=str(temp_png),
120
- width=width, height=height)
121
-
122
- from PIL import Image
123
- with Image.open(temp_png) as img:
124
- img.convert('RGB').save(output_path, quality=options.get('quality', 90))
125
-
126
- # Remove temporary PNG
127
- temp_png.unlink()
128
- else:
129
- # For other formats, convert to PNG first, then use Pillow
130
- temp_png = output_path.with_suffix('.png')
131
- cairosvg.svg2png(url=str(filepath), write_to=str(temp_png),
132
- width=width, height=height)
133
-
134
- from PIL import Image
135
- with Image.open(temp_png) as img:
136
- img.save(output_path)
137
-
138
- # Remove temporary PNG
139
- temp_png.unlink()
140
-
141
- return str(output_path)
142
-
143
- except ImportError:
144
- logger.warning("cairosvg not installed. Trying alternative method...")
145
-
146
- # Try using Inkscape as a fallback
147
- try:
148
- import subprocess
149
-
150
- cmd = [
151
- 'inkscape',
152
- '--export-filename', str(output_path),
153
- str(filepath)
154
- ]
155
-
156
- subprocess.run(cmd, check=True)
157
- return str(output_path)
158
-
159
- except (ImportError, subprocess.SubprocessError) as e:
160
- raise RuntimeError(f"Failed to convert SVG: {str(e)}. Please install cairosvg or Inkscape.")
161
-
162
- def _convert_svg_to_pdf(
163
- filepath: Path,
164
- output_path: Path,
165
- options: Dict[str, Any]
166
- ) -> str:
167
- """Convert SVG to PDF."""
168
- try:
169
- # Try using cairosvg
170
- import cairosvg
171
- cairosvg.svg2pdf(url=str(filepath), write_to=str(output_path))
172
- return str(output_path)
173
-
174
- except ImportError:
175
- logger.warning("cairosvg not installed. Trying alternative method...")
176
-
177
- # Try using Inkscape as a fallback
178
- try:
179
- import subprocess
180
-
181
- cmd = [
182
- 'inkscape',
183
- '--export-filename', str(output_path),
184
- str(filepath)
185
- ]
186
-
187
- subprocess.run(cmd, check=True)
188
- return str(output_path)
189
-
190
- except (ImportError, subprocess.SubprocessError) as e:
191
- raise RuntimeError(f"Failed to convert SVG to PDF: {str(e)}. Please install cairosvg or Inkscape.")
192
-
193
- def _convert_to_pdf(
194
- filepath: Path,
195
- source_format: str,
196
- output_path: Path,
197
- options: Dict[str, Any]
198
- ) -> str:
199
- """Convert image to PDF."""
200
- from PIL import Image
201
-
202
- try:
203
- with Image.open(filepath) as img:
204
- # Convert to RGB if needed
205
- if img.mode == 'RGBA':
206
- img = img.convert('RGB')
207
-
208
- img.save(output_path, 'PDF', resolution=options.get('dpi', 100))
209
-
210
- return str(output_path)
211
-
212
- except Exception as e:
213
- logger.error(f"Error converting to PDF: {str(e)}")
214
- raise RuntimeError(f"Failed to convert to PDF: {str(e)}")
@@ -1,208 +0,0 @@
1
- """
2
- 3D model converter module for handling 3D model format conversions.
3
- """
4
-
5
- import logging
6
- import os
7
- import tempfile
8
- from pathlib import Path
9
- from typing import Union, Optional, Dict, Any
10
-
11
- logger = logging.getLogger(__name__)
12
-
13
- # Define supported conversions
14
- SUPPORTED_CONVERSIONS = {
15
- 'stl': ['obj', 'fbx', 'ply'],
16
- 'obj': ['stl', 'fbx', 'ply'],
17
- 'fbx': ['stl', 'obj', 'ply'],
18
- 'ply': ['stl', 'obj', 'fbx']
19
- }
20
-
21
- def convert(
22
- filepath: Union[str, Path],
23
- source_format: str,
24
- target_format: str,
25
- output_path: Union[str, Path],
26
- options: Optional[Dict[str, Any]] = None
27
- ) -> str:
28
- """
29
- Convert a 3D model from one format to another.
30
-
31
- Args:
32
- filepath: Path to the source model file
33
- source_format: Source model format
34
- target_format: Target model format
35
- output_path: Path to save the converted model
36
- options: Additional conversion options
37
-
38
- Returns:
39
- Path to the converted model
40
-
41
- Raises:
42
- ValueError: If the conversion is not supported
43
- RuntimeError: If the conversion fails
44
- """
45
- if options is None:
46
- options = {}
47
-
48
- # Check if conversion is supported
49
- if target_format not in SUPPORTED_CONVERSIONS.get(source_format, []):
50
- raise ValueError(f"Conversion from {source_format} to {target_format} is not supported")
51
-
52
- filepath = Path(filepath)
53
- output_path = Path(output_path)
54
-
55
- try:
56
- # Try using trimesh for model conversion
57
- return _convert_with_trimesh(filepath, source_format, target_format, output_path, options)
58
-
59
- except ImportError:
60
- logger.warning("trimesh not installed. Trying alternative method...")
61
-
62
- # Try using Blender for conversion
63
- return _convert_with_blender(filepath, source_format, target_format, output_path, options)
64
-
65
- def _convert_with_trimesh(
66
- filepath: Path,
67
- source_format: str,
68
- target_format: str,
69
- output_path: Path,
70
- options: Dict[str, Any]
71
- ) -> str:
72
- """Convert 3D model using trimesh library."""
73
- import trimesh
74
-
75
- # Load the model
76
- mesh = trimesh.load(str(filepath))
77
-
78
- # Apply transformations if specified
79
- if 'scale' in options:
80
- scale = options['scale']
81
- if isinstance(scale, (int, float)):
82
- # Uniform scaling
83
- mesh.apply_scale(scale)
84
- elif isinstance(scale, (list, tuple)) and len(scale) == 3:
85
- # Non-uniform scaling
86
- mesh.apply_scale(scale)
87
-
88
- if 'rotation' in options:
89
- # Rotation in degrees around x, y, z axes
90
- import numpy as np
91
- from scipy.spatial.transform import Rotation as R
92
-
93
- rotation = options['rotation']
94
- if isinstance(rotation, (list, tuple)) and len(rotation) == 3:
95
- # Convert degrees to radians
96
- rotation_rad = [np.radians(r) for r in rotation]
97
- r = R.from_euler('xyz', rotation_rad)
98
- mesh.apply_transform(np.eye(4))
99
- mesh.apply_transform(np.vstack((np.hstack((r.as_matrix(), np.zeros((3, 1)))), [0, 0, 0, 1])))
100
-
101
- if 'translation' in options:
102
- # Translation along x, y, z axes
103
- translation = options['translation']
104
- if isinstance(translation, (list, tuple)) and len(translation) == 3:
105
- mesh.apply_translation(translation)
106
-
107
- # Export to target format
108
- export_options = {}
109
-
110
- if target_format == 'stl' and 'ascii' in options:
111
- export_options['file_type'] = 'ascii' if options['ascii'] else 'binary'
112
-
113
- mesh.export(str(output_path), file_type=target_format, **export_options)
114
-
115
- return str(output_path)
116
-
117
- def _convert_with_blender(
118
- filepath: Path,
119
- source_format: str,
120
- target_format: str,
121
- output_path: Path,
122
- options: Dict[str, Any]
123
- ) -> str:
124
- """Convert 3D model using Blender."""
125
- import subprocess
126
- import tempfile
127
-
128
- # Create a temporary Python script for Blender
129
- with tempfile.NamedTemporaryFile(suffix='.py', mode='w', delete=False) as script_file:
130
- script_path = script_file.name
131
-
132
- # Write Blender Python script
133
- script_file.write(f"""
134
- import bpy
135
- import os
136
- import math
137
-
138
- # Clear existing objects
139
- bpy.ops.object.select_all(action='SELECT')
140
- bpy.ops.object.delete()
141
-
142
- # Import the model
143
- if '{source_format}' == 'stl':
144
- bpy.ops.import_mesh.stl(filepath='{filepath}')
145
- elif '{source_format}' == 'obj':
146
- bpy.ops.import_scene.obj(filepath='{filepath}')
147
- elif '{source_format}' == 'fbx':
148
- bpy.ops.import_scene.fbx(filepath='{filepath}')
149
- elif '{source_format}' == 'ply':
150
- bpy.ops.import_mesh.ply(filepath='{filepath}')
151
-
152
- # Select all objects
153
- bpy.ops.object.select_all(action='SELECT')
154
-
155
- # Apply transformations
156
- """)
157
-
158
- # Add transformation code if options are provided
159
- if 'scale' in options:
160
- scale = options['scale']
161
- if isinstance(scale, (int, float)):
162
- script_file.write(f"bpy.ops.transform.resize(value=({scale}, {scale}, {scale}))\n")
163
- elif isinstance(scale, (list, tuple)) and len(scale) == 3:
164
- script_file.write(f"bpy.ops.transform.resize(value=({scale[0]}, {scale[1]}, {scale[2]}))\n")
165
-
166
- if 'rotation' in options:
167
- rotation = options['rotation']
168
- if isinstance(rotation, (list, tuple)) and len(rotation) == 3:
169
- script_file.write(f"""
170
- bpy.ops.transform.rotate(value={math.radians(rotation[0])}, orient_axis='X')
171
- bpy.ops.transform.rotate(value={math.radians(rotation[1])}, orient_axis='Y')
172
- bpy.ops.transform.rotate(value={math.radians(rotation[2])}, orient_axis='Z')
173
- """)
174
-
175
- if 'translation' in options:
176
- translation = options['translation']
177
- if isinstance(translation, (list, tuple)) and len(translation) == 3:
178
- script_file.write(f"bpy.ops.transform.translate(value=({translation[0]}, {translation[1]}, {translation[2]}))\n")
179
-
180
- # Add export code
181
- script_file.write(f"""
182
- # Export the model
183
- if '{target_format}' == 'stl':
184
- bpy.ops.export_mesh.stl(filepath='{output_path}', {'ascii=True' if options.get('ascii', False) else ''})
185
- elif '{target_format}' == 'obj':
186
- bpy.ops.export_scene.obj(filepath='{output_path}')
187
- elif '{target_format}' == 'fbx':
188
- bpy.ops.export_scene.fbx(filepath='{output_path}')
189
- elif '{target_format}' == 'ply':
190
- bpy.ops.export_mesh.ply(filepath='{output_path}')
191
- """)
192
-
193
- try:
194
- # Run Blender with the script
195
- cmd = ['blender', '--background', '--python', script_path]
196
- subprocess.run(cmd, check=True, capture_output=True)
197
-
198
- # Clean up the temporary script
199
- os.unlink(script_path)
200
-
201
- return str(output_path)
202
-
203
- except subprocess.SubprocessError as e:
204
- # Clean up the temporary script
205
- os.unlink(script_path)
206
-
207
- logger.error(f"Error running Blender: {str(e)}")
208
- raise RuntimeError(f"Failed to convert model with Blender: {str(e)}. Please install Blender.")
@@ -1,259 +0,0 @@
1
- """
2
- Video converter module for handling video format conversions.
3
- """
4
-
5
- import logging
6
- import os
7
- import tempfile
8
- from pathlib import Path
9
- from typing import Union, Optional, Dict, Any
10
-
11
- logger = logging.getLogger(__name__)
12
-
13
- # Define supported conversions
14
- SUPPORTED_CONVERSIONS = {
15
- 'mp4': ['avi', 'mkv', 'mov', 'gif'],
16
- 'avi': ['mp4', 'mkv', 'mov', 'gif'],
17
- 'mkv': ['mp4', 'avi', 'mov'],
18
- 'mov': ['mp4', 'avi', 'mkv'],
19
- 'gif': ['mp4', 'avi']
20
- }
21
-
22
- def convert(
23
- filepath: Union[str, Path],
24
- source_format: str,
25
- target_format: str,
26
- output_path: Union[str, Path],
27
- options: Optional[Dict[str, Any]] = None
28
- ) -> str:
29
- """
30
- Convert a video file from one format to another.
31
-
32
- Args:
33
- filepath: Path to the source video file
34
- source_format: Source video format
35
- target_format: Target video format
36
- output_path: Path to save the converted video
37
- options: Additional conversion options
38
-
39
- Returns:
40
- Path to the converted video
41
-
42
- Raises:
43
- ValueError: If the conversion is not supported
44
- RuntimeError: If the conversion fails
45
- """
46
- if options is None:
47
- options = {}
48
-
49
- # Check if conversion is supported
50
- if target_format not in SUPPORTED_CONVERSIONS.get(source_format, []):
51
- raise ValueError(f"Conversion from {source_format} to {target_format} is not supported")
52
-
53
- filepath = Path(filepath)
54
- output_path = Path(output_path)
55
-
56
- try:
57
- # Use ffmpeg for video conversion
58
- return _convert_with_ffmpeg(filepath, source_format, target_format, output_path, options)
59
-
60
- except Exception as e:
61
- logger.error(f"Error converting {filepath} to {target_format}: {str(e)}")
62
- raise RuntimeError(f"Failed to convert {filepath} to {target_format}: {str(e)}")
63
-
64
- def extract_audio(
65
- filepath: Union[str, Path],
66
- output_path: Union[str, Path],
67
- options: Optional[Dict[str, Any]] = None
68
- ) -> str:
69
- """
70
- Extract audio from a video file.
71
-
72
- Args:
73
- filepath: Path to the source video file
74
- output_path: Path to save the extracted audio
75
- options: Additional extraction options
76
-
77
- Returns:
78
- Path to the extracted audio
79
-
80
- Raises:
81
- RuntimeError: If the extraction fails
82
- """
83
- if options is None:
84
- options = {}
85
-
86
- filepath = Path(filepath)
87
- output_path = Path(output_path)
88
-
89
- try:
90
- import subprocess
91
-
92
- # Basic ffmpeg command for audio extraction
93
- cmd = ['ffmpeg', '-i', str(filepath), '-vn'] # -vn means no video
94
-
95
- # Add audio options
96
- if 'audio_codec' in options:
97
- cmd.extend(['-acodec', options['audio_codec']])
98
- else:
99
- cmd.extend(['-acodec', 'libmp3lame']) # Default to MP3
100
-
101
- if 'bitrate' in options:
102
- cmd.extend(['-b:a', options['bitrate']])
103
- else:
104
- cmd.extend(['-b:a', '192k']) # Default bitrate
105
-
106
- if 'sample_rate' in options:
107
- cmd.extend(['-ar', str(options['sample_rate'])])
108
-
109
- if 'channels' in options:
110
- cmd.extend(['-ac', str(options['channels'])])
111
-
112
- # Add output file
113
- cmd.append(str(output_path))
114
-
115
- # Run ffmpeg
116
- subprocess.run(cmd, check=True, capture_output=True)
117
- return str(output_path)
118
-
119
- except Exception as e:
120
- logger.error(f"Error extracting audio: {str(e)}")
121
- raise RuntimeError(f"Failed to extract audio: {str(e)}")
122
-
123
- def extract_frames(
124
- filepath: Union[str, Path],
125
- target_format: str,
126
- output_path: Union[str, Path],
127
- options: Optional[Dict[str, Any]] = None
128
- ) -> str:
129
- """
130
- Extract frames from a video file.
131
-
132
- Args:
133
- filepath: Path to the source video file
134
- target_format: Target image format (png or jpg)
135
- output_path: Path to save the extracted frames
136
- options: Additional extraction options
137
-
138
- Returns:
139
- Path to the directory containing extracted frames
140
-
141
- Raises:
142
- ValueError: If the target format is not supported
143
- RuntimeError: If the extraction fails
144
- """
145
- if options is None:
146
- options = {}
147
-
148
- if target_format not in ['png', 'jpg', 'jpeg']:
149
- raise ValueError(f"Unsupported frame format: {target_format}")
150
-
151
- filepath = Path(filepath)
152
- output_path = Path(output_path)
153
-
154
- # If output_path is a file, use its parent directory and name as prefix
155
- if output_path.suffix:
156
- output_dir = output_path.parent
157
- output_prefix = output_path.stem
158
- else:
159
- # If output_path is a directory, use it as is
160
- output_dir = output_path
161
- output_prefix = 'frame'
162
-
163
- # Create output directory if it doesn't exist
164
- os.makedirs(output_dir, exist_ok=True)
165
-
166
- try:
167
- import subprocess
168
-
169
- # Get frame rate for extraction
170
- fps = options.get('fps', 1) # Default: 1 frame per second
171
-
172
- # Determine output pattern
173
- output_pattern = str(output_dir / f"{output_prefix}_%04d.{target_format}")
174
-
175
- # Basic ffmpeg command for frame extraction
176
- cmd = ['ffmpeg', '-i', str(filepath)]
177
-
178
- if 'start_time' in options:
179
- cmd.extend(['-ss', str(options['start_time'])])
180
-
181
- if 'duration' in options:
182
- cmd.extend(['-t', str(options['duration'])])
183
-
184
- # Set frame rate
185
- cmd.extend(['-vf', f'fps={fps}'])
186
-
187
- # Set quality
188
- if target_format in ['jpg', 'jpeg']:
189
- quality = options.get('quality', 95)
190
- cmd.extend(['-q:v', str(int(quality / 10))]) # ffmpeg uses 1-10 scale
191
-
192
- # Add output pattern
193
- cmd.append(output_pattern)
194
-
195
- # Run ffmpeg
196
- subprocess.run(cmd, check=True, capture_output=True)
197
- return str(output_dir)
198
-
199
- except Exception as e:
200
- logger.error(f"Error extracting frames: {str(e)}")
201
- raise RuntimeError(f"Failed to extract frames: {str(e)}")
202
-
203
- def _convert_with_ffmpeg(
204
- filepath: Path,
205
- source_format: str,
206
- target_format: str,
207
- output_path: Path,
208
- options: Dict[str, Any]
209
- ) -> str:
210
- """Convert video using ffmpeg."""
211
- import subprocess
212
-
213
- # Basic ffmpeg command
214
- cmd = ['ffmpeg', '-i', str(filepath)]
215
-
216
- # Special handling for GIF output
217
- if target_format == 'gif':
218
- # Optimize for GIF output
219
- scale = options.get('scale', 320)
220
- fps = options.get('fps', 10)
221
- cmd.extend([
222
- '-vf', f'fps={fps},scale={scale}:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse'
223
- ])
224
- else:
225
- # Add video options
226
- if 'video_codec' in options:
227
- cmd.extend(['-c:v', options['video_codec']])
228
-
229
- if 'audio_codec' in options:
230
- cmd.extend(['-c:a', options['audio_codec']])
231
-
232
- if 'bitrate' in options:
233
- cmd.extend(['-b:v', options['bitrate']])
234
-
235
- if 'resolution' in options:
236
- width, height = options['resolution']
237
- cmd.extend(['-s', f'{width}x{height}'])
238
-
239
- if 'framerate' in options:
240
- cmd.extend(['-r', str(options['framerate'])])
241
-
242
- if 'crf' in options:
243
- # Constant Rate Factor (quality)
244
- cmd.extend(['-crf', str(options['crf'])])
245
-
246
- if 'preset' in options:
247
- # Encoding preset (slower = better compression)
248
- cmd.extend(['-preset', options['preset']])
249
-
250
- # Add output file
251
- cmd.append(str(output_path))
252
-
253
- # Run ffmpeg
254
- try:
255
- subprocess.run(cmd, check=True, capture_output=True)
256
- return str(output_path)
257
- except subprocess.SubprocessError as e:
258
- logger.error(f"Error running ffmpeg: {str(e)}")
259
- raise RuntimeError(f"Failed to convert video with ffmpeg: {str(e)}")
openconvert/launcher.py DELETED
File without changes