Created
October 6, 2025 10:01
-
-
Save brayevalerien/93a0bb5f3e0604ade8e2a3c65f925c06 to your computer and use it in GitHub Desktop.
Tiny CLI for calling the Magnific creative upscaler from the Freepik API. Upscale images from your terminal in a matter of minutes!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import argparse | |
| import base64 | |
| import json | |
| import sys | |
| import time | |
| from pathlib import Path | |
| import requests | |
| def encode_image(image_path): | |
| """Encode image to base64 string.""" | |
| with open(image_path, 'rb') as f: | |
| return base64.b64encode(f.read()).decode('utf-8') | |
| def upscale_image(api_key, image_b64, scale_factor, prompt, creativity, hdr, | |
| resemblance, fractality, engine, optimized_for): | |
| """Submit upscaling job.""" | |
| url = 'https://api.freepik.com/v1/ai/image-upscaler' | |
| headers = { | |
| 'Content-Type': 'application/json', | |
| 'x-freepik-api-key': api_key | |
| } | |
| payload = { | |
| 'image': image_b64, | |
| 'scale_factor': scale_factor, | |
| 'creativity': creativity, | |
| 'hdr': hdr, | |
| 'resemblance': resemblance, | |
| 'fractality': fractality, | |
| 'engine': engine, | |
| 'optimized_for': optimized_for | |
| } | |
| if prompt: | |
| payload['prompt'] = prompt | |
| response = requests.post(url, headers=headers, json=payload) | |
| response.raise_for_status() | |
| return response.json()['data']['task_id'] | |
| def get_task_status(api_key, task_id): | |
| """Check task status.""" | |
| url = f'https://api.freepik.com/v1/ai/image-upscaler/{task_id}' | |
| headers = {'x-freepik-api-key': api_key} | |
| response = requests.get(url, headers=headers) | |
| response.raise_for_status() | |
| return response.json()['data'] | |
| def download_image(url, output_path): | |
| """Download the upscaled image.""" | |
| response = requests.get(url, stream=True) | |
| response.raise_for_status() | |
| with open(output_path, 'wb') as f: | |
| for chunk in response.iter_content(chunk_size=8192): | |
| f.write(chunk) | |
| def main(): | |
| parser = argparse.ArgumentParser( | |
| description='Freepik Magnific Upscaler CLI', | |
| formatter_class=argparse.RawDescriptionHelpFormatter, | |
| epilog=''' | |
| Examples: | |
| %(prog)s input.jpg -k YOUR_API_KEY | |
| %(prog)s input.jpg -k KEY -s 8x --engine magnific_sharpy | |
| %(prog)s photo.jpg -k KEY --optimized-for soft_portraits -r 5 -f 2 | |
| ''') | |
| parser.add_argument('input', help='Input image path') | |
| parser.add_argument('-o', '--output', | |
| help='Output image path (default: input_upscaled.jpg)') | |
| parser.add_argument('-k', '--api-key', required=True, | |
| help='Freepik API key') | |
| # Core parameters | |
| parser.add_argument('-s', '--scale', default='4x', | |
| choices=['2x', '4x', '8x', '16x'], | |
| help='Scale factor (default: 4x)') | |
| parser.add_argument('-p', '--prompt', | |
| help='Enhancement prompt to guide upscaling') | |
| # Quality parameters | |
| parser.add_argument('-c', '--creativity', type=int, default=2, | |
| help='Creativity level 0-10 (default: 2)') | |
| parser.add_argument('--hdr', type=int, default=1, | |
| help='HDR level 0-10 (default: 1)') | |
| parser.add_argument('-r', '--resemblance', type=int, default=0, | |
| help='Resemblance to original -10 to 10 (default: 0)') | |
| parser.add_argument('-f', '--fractality', type=int, default=0, | |
| help='Detail density -10 to 10 (default: 0)') | |
| # Engine selection | |
| parser.add_argument('-e', '--engine', default='automatic', | |
| choices=['automatic', 'magnific_illusio', | |
| 'magnific_sharpy', 'magnific_sparkle'], | |
| help='Upscaling engine (default: automatic)') | |
| # Optimization | |
| parser.add_argument('--optimized-for', default='standard', | |
| choices=['standard', 'soft_portraits', 'hard_portraits', | |
| 'art_n_illustration', 'videogame_assets', | |
| 'nature_n_landscapes', 'films_n_photography', | |
| '3d_renders', 'science_fiction_n_horror'], | |
| help='Optimize for image type (default: standard)') | |
| args = parser.parse_args() | |
| # Set default output path | |
| if not args.output: | |
| input_path = Path(args.input) | |
| args.output = input_path.stem + '_upscaled' + input_path.suffix | |
| try: | |
| # Encode image | |
| print(f"Encoding {args.input}...") | |
| image_b64 = encode_image(args.input) | |
| # Submit job | |
| print(f"Submitting upscale job ({args.scale})...") | |
| task_id = upscale_image( | |
| args.api_key, | |
| image_b64, | |
| args.scale, | |
| args.prompt, | |
| args.creativity, | |
| args.hdr, | |
| args.resemblance, | |
| args.fractality, | |
| args.engine, | |
| args.optimized_for | |
| ) | |
| print(f"Task ID: {task_id}") | |
| # Poll for completion | |
| print("Waiting for completion", end='', flush=True) | |
| while True: | |
| status_data = get_task_status(args.api_key, task_id) | |
| status = status_data['status'] | |
| if status == 'COMPLETED': | |
| print("\nCompleted!") | |
| image_url = status_data['generated'][0] | |
| break | |
| elif status == 'FAILED': | |
| print("\nFailed!") | |
| sys.exit(1) | |
| print('.', end='', flush=True) | |
| time.sleep(3) | |
| # Download result | |
| print(f"Downloading to {args.output}...") | |
| download_image(image_url, args.output) | |
| print("Done!") | |
| except requests.HTTPError as e: | |
| print(f"\nAPI Error: {e.response.status_code} - {e.response.text}", | |
| file=sys.stderr) | |
| sys.exit(1) | |
| except Exception as e: | |
| print(f"\nError: {e}", file=sys.stderr) | |
| sys.exit(1) | |
| if __name__ == '__main__': | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment