Download extras/ImageGenClient.py from jongyf/Z-Image-Turbo-Text-Encoder-Heretic-NVFP4: direct link, hf CLI and curl.
- Browser
- Download file 6.24 kB
-
https://huggingface.co/jongyf/Z-Image-Turbo-Text-Encoder-Heretic-NVFP4/resolve/main/extras/ImageGenClient.py
- Command line
-
hf download hf://jongyf/Z-Image-Turbo-Text-Encoder-Heretic-NVFP4/extras/ImageGenClient.py
-
curl -L -o ImageGenClient.py https://huggingface.co/jongyf/Z-Image-Turbo-Text-Encoder-Heretic-NVFP4/resolve/main/extras/ImageGenClient.py
6.24 kB
| import argparse | |
| import sys | |
| import os | |
| import base64 | |
| import time | |
| import io | |
| import requests | |
| from PIL import Image | |
| # Oh, hello there! Nikola here, ready to help this little client talk to the big server! | |
| # It's like sending a messenger bird from our village to the capital! | |
| def main(): | |
| # Peeking at the arguments... gotta make sure we have all our supplies for the journey! | |
| parser = argparse.ArgumentParser(description="ImageGen Client - A little seeker tool!") | |
| parser.add_argument("--host", type=str, default="localhost", help="Where the server lives (Host)") | |
| parser.add_argument("--port", type=int, default=8000, help="The door to knock on (Port)") | |
| parser.add_argument("--num_images", type=int, default=1, help="How many pictures to paint?") | |
| parser.add_argument("--image_folder", type=str, default="generated_images", help="Where to keep our treasures") | |
| # Changing defaults to None so we can use input image size if needed! | |
| parser.add_argument("--width", type=int, default=None, help="Canvas width (default: 1024 or input image size)") | |
| parser.add_argument("--height", type=int, default=None, help="Canvas height (default: 1024 or input image size)") | |
| # New shiny tools for our quest! | |
| parser.add_argument("--input", type=str, default=None, help="Path to an input image (for image-to-image magic!)") | |
| parser.add_argument("--max-size", type=int, default=1024, help="Max size for the input image (we don't want it to get too heavy for the bird!)") | |
| args = parser.parse_args() | |
| # Reading the prompt from the spirits... I mean, stdin! | |
| # "What do you desire to see?" *sparkle* | |
| print("Waiting for a prompt from stdin... (Type something and press Ctrl+D!)") | |
| try: | |
| prompt = sys.stdin.read().strip() | |
| except Exception as e: | |
| print(f"Oh no! The spirits were silent (stdin error): {e}") | |
| return | |
| if not prompt: | |
| print("Aww, the prompt was empty! The canvas remains blank.") | |
| return | |
| print(f"Yay! We got a prompt: '{prompt}'") | |
| # Restoring the canvas size variables from the journey's start! | |
| final_width = args.width | |
| final_height = args.height | |
| # Prepare prompt and payload | |
| url_gen = f"http://{args.host}:{args.port}/v1/images/generations" | |
| url_edit = f"http://{args.host}:{args.port}/v1/images/edits" | |
| try: | |
| if args.input: | |
| print(f"Oh! You brought a reference image: {args.input}. Let's go to the Editing Shrine!") | |
| # Prepare for multipart upload | |
| # We need to open the image file effectively | |
| if not os.path.exists(args.input): | |
| print(f"Eek! I can't find the image at {args.input}") | |
| return | |
| # Open image to ensure it's valid and memory-friendly resize if needed | |
| with Image.open(args.input) as img: | |
| img = img.convert("RGB") | |
| w, h = img.size | |
| max_dim = max(w, h) | |
| if max_dim > args.max_size: | |
| scale = args.max_size / max_dim | |
| new_w = int(w * scale) | |
| new_h = int(h * scale) | |
| print(f"Resizing big image from {w}x{h} to {new_w}x{new_h}. Compact and cute!") | |
| img = img.resize((new_w, new_h), Image.LANCZOS) | |
| if final_width is None: final_width = img.width | |
| if final_height is None: final_height = img.height | |
| # Save to buffer for upload | |
| buffered = io.BytesIO() | |
| img.save(buffered, format="PNG") | |
| buffered.seek(0) | |
| image_bytes = buffered.getvalue() | |
| # Construct multipart payload | |
| files = { | |
| 'image': ('input.png', image_bytes, 'image/png') | |
| } | |
| data = { | |
| 'prompt': prompt, | |
| 'n': args.num_images, | |
| 'size': f"{final_width}x{final_height}", | |
| 'response_format': 'b64_json', | |
| 'guidance_scale': 2.5 # Default specific to edit/kontext if needed | |
| } | |
| print(f"Sending input image to {url_edit}... *whoosh*") | |
| response = requests.post(url_edit, files=files, data=data) | |
| else: | |
| # Standard Generation | |
| print("Just a prompt? Off to the Creation Forge!") | |
| if final_width is None: final_width = 1024 | |
| if final_height is None: final_height = 1024 | |
| payload = { | |
| "prompt": prompt, | |
| "n": args.num_images, | |
| "size": f"{final_width}x{final_height}", | |
| "response_format": "b64_json" | |
| } | |
| print(f"Sending prompt to {url_gen}... *sparkle*") | |
| response = requests.post(url_gen, json=payload) | |
| response.raise_for_status() | |
| data = response.json() | |
| # Making sure we have a chest for our treasures | |
| if not os.path.exists(args.image_folder): | |
| print(f"Creating a new treasure chest at {args.image_folder}...") | |
| os.makedirs(args.image_folder) | |
| # Unpacking the magic | |
| images = data.get("data", []) | |
| print(f"Ooh! The server sent back {len(images)} masterpieces!") | |
| for i, img_data in enumerate(images): | |
| # Decoding the spell | |
| img_bytes = base64.b64decode(img_data["b64_json"]) | |
| timestamp = int(time.time()) | |
| filename = f"image_{timestamp}_{i}.png" | |
| filepath = os.path.join(args.image_folder, filename) | |
| with open(filepath, "wb") as f: | |
| f.write(img_bytes) | |
| print(f"Saved masterpiece #{i+1} to {filepath}! It sparkles!") | |
| except requests.exceptions.ConnectionError: | |
| print("Oh no! The server didn't answer. Is it sleeping? (Connection Refused)") | |
| print("Maybe check if the host and port are correct? We tried: " + url) | |
| except Exception as e: | |
| print(f"Eek! Something went wrong on the journey: {e}") | |
| # We'll give it a gentle hug and try to understand... | |
| print("Don't worry, we can try again later!") | |
| if __name__ == "__main__": | |
| main() | |