├── input.png ├── resources ├── tileset.png ├── wordmark.png ├── single_tile.png └── walk_idle_format.png ├── img2img.py └── README.md /input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Retro-Diffusion/api-examples/HEAD/input.png -------------------------------------------------------------------------------- /resources/tileset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Retro-Diffusion/api-examples/HEAD/resources/tileset.png -------------------------------------------------------------------------------- /resources/wordmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Retro-Diffusion/api-examples/HEAD/resources/wordmark.png -------------------------------------------------------------------------------- /resources/single_tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Retro-Diffusion/api-examples/HEAD/resources/single_tile.png -------------------------------------------------------------------------------- /resources/walk_idle_format.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Retro-Diffusion/api-examples/HEAD/resources/walk_idle_format.png -------------------------------------------------------------------------------- /img2img.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import base64 3 | 4 | from PIL import Image 5 | from io import BytesIO 6 | 7 | 8 | def generate_image_with_input_image( 9 | api_key: str, 10 | input_image_path: str, 11 | output_image_path: str, 12 | prompt: str, 13 | style: str = "default", 14 | width: int = 256, 15 | height: int = 256, 16 | strength: float = 0.5, 17 | seed: int = 0 18 | ): 19 | # 1. Convert local image to Base64 and convert to RGB 20 | with Image.open(input_image_path) as img: 21 | rgb_img = img.convert('RGB') 22 | buffer = BytesIO() 23 | rgb_img.save(buffer, format='PNG') 24 | base64_input_image = base64.b64encode(buffer.getvalue()).decode('utf-8') 25 | 26 | # 2. Prepare the request 27 | url = "https://api.retrodiffusion.ai/v1/inferences" 28 | method = "POST" 29 | headers = { 30 | "X-RD-Token": api_key, 31 | } 32 | 33 | payload = { 34 | "prompt": prompt, 35 | "prompt_style": style, 36 | "model": model, 37 | "width": width, 38 | "height": height, 39 | "input_image": base64_input_image, 40 | "strength": strength, 41 | "num_images": 1, 42 | "seed": seed 43 | } 44 | 45 | # 3. Send the request 46 | response = requests.request(method, url, headers=headers, json=payload) 47 | 48 | # 4. Handle response 49 | if response.status_code == 200: 50 | data = response.json() 51 | # data['base64_images'] is a list of base64-encoded image strings 52 | base64_images = data.get("base64_images", []) 53 | if base64_images: 54 | # Take the first image 55 | img_data = base64_images[0] 56 | # Decode and save 57 | with open(output_image_path, "wb") as out_file: 58 | out_file.write(base64.b64decode(img_data)) 59 | print(f"Image generated and saved to {output_image_path}") 60 | else: 61 | print("No images returned by the API.") 62 | else: 63 | print(f"Request failed with status code {response.status_code}: {response.text}") 64 | 65 | 66 | if __name__ == "__main__": 67 | # Example usage 68 | YOUR_API_KEY = "rdpk-xxxxxxxxxxxx" # Replace with your actual API key 69 | INPUT_IMAGE_PATH = "input.png" # Replace with your local input image path 70 | OUTPUT_IMAGE_PATH = "generated_image.png" # Where you want to save the result 71 | 72 | generate_image_with_input_image( 73 | api_key=YOUR_API_KEY, 74 | input_image_path=INPUT_IMAGE_PATH, 75 | output_image_path=OUTPUT_IMAGE_PATH, 76 | prompt="an orange sports car", 77 | width=256, 78 | height=256, 79 | strength=0.75, 80 | seed = 1 81 | ) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
280 |
281 | ### All tileset styles
282 | - rd_tile__tileset `(16x16 <-> 32x32) Create full tilesets from a simple prompt describing the textures or environment, using a simple set of "wang" style combinations`
283 | - rd_tile__tileset_advanced `(16x16 <-> 32x32) Full tilesets from two prompts and/or textures, using a simple set of "wang" style combinations`
284 | - rd_tile__single_tile `(16x16 <-> 64x64) Detailed single tile texture for creating full tilesets or surfaces`
285 | - rd_tile__tile_variation `(16x16 <-> 128x128) Texture variations of the provided tile image`
286 | - rd_tile__tile_object `(16x16 <-> 96x96) Small assets for placing on sections of tiles`
287 | - rd_tile__scene_object `(64x64 <-> 384x384) Large assets for placing on tileset maps`
288 |
289 | ### Full tilesets
290 | - You can generate full tilesets using the following styles:
291 | - rd_tile__tileset
292 | - rd_tile__tileset_advanced
293 |
294 | - `rd_tile__tileset` supports an inspiration image via the `input_image` parameter
295 | - `rd_tile__tileset_advanced` supports inside and outside textures via the `input_image` and `extra_input_image` parameters. Advanced tilesets require the inside texture description in the `prompt` parameter and the outside texture description in the `extra_prompt` parameter.
296 | - The `width` and `height` parameters specify the size of each tile in the tileset. Values can range between 16 and 32.
297 |
298 | Advanced tileset example payload:
299 |
300 | ```python
301 | {
302 | "width": 32,
303 | "height": 32,
304 | "prompt": "grey stones with gravel and dirt",
305 | "extra_prompt": "lush green grass",
306 | "num_images": 1,
307 | "prompt_style": "rd_tile__tileset_advanced",
308 | "seed": 123,
309 | "input_image": "iVBORw0KGgoAAAANSUhEUgAAAUA... ... ...",
310 | "extra_input_image": "iVBORw0KGgoAAAANSUhEUgAAAUA... ... ..."
311 | }
312 | ```
313 | ### Tileset format:
314 |
318 |
319 | - You can generate single tiles using the `rd_tile__single_tile` style.
320 | - The `width` and `height` parameters specify the size of the tile and can range between 16 and 64.
321 |
322 | Example:
323 |
324 | ```python
325 | {
326 | "width": 32,
327 | "height": 32,
328 | "prompt": "volcanic rock with cracks",
329 | "num_images": 1,
330 | "prompt_style": "rd_tile__single_tile"
331 | }
332 | ```
333 |
334 | ### Tile variation
335 | - You can generate variations of a tile using the `rd_tile__tile_variation` style.
336 | - The `input_image` parameter is **required** and should be a base64 encoded image of the tile you want to create variations from.
337 | - Use the `prompt` parameter to describe the changes you want to see in the variations.
338 |
339 | Example:
340 |
341 | ```python
342 | {
343 | "width": 32,
344 | "height": 32,
345 | "prompt": "add moss and cracks",
346 | "num_images": 1,
347 | "prompt_style": "rd_tile__tile_variation",
348 | "input_image": "iVBORw0KGgoAAAANSUhEUgAAAUA... ... ..."
349 | }
350 | ```
351 |
352 | ## Using img2img
353 |
354 | - Just send a **base64** image in the `input_image` parameter and adjust `strength` to your likinng. Strength is a value between 0 and 1 and represents how much the image should be modified.
355 | - No need to include `data:image/png;base64,` in the base64 image.
356 | - Send your image as a base64 string, it should be a RGB image with no transparency.
357 |
358 | ```python
359 | with Image.open(input_image_path) as img:
360 | rgb_img = img.convert('RGB')
361 | buffer = BytesIO()
362 | rgb_img.save(buffer, format='PNG')
363 | base64_input_image = base64.b64encode(buffer.getvalue()).decode('utf-8')
364 |
365 | payload = {
366 | "prompt": "A really cool corgi wearing sunglasses and a party hat",
367 | "width": 256,
368 | "height": 256,
369 | "input_image": base64_input_image,
370 | "strength": 0.8
371 | }
372 | ```
373 |
374 | ## Using a palette for reference
375 |
376 | - You can use the `input_palette` parameter to let the model know what palette to use as a reference.
377 | - Just send a **base64** image in the `input_palette` parameter.
378 | - The `input_palette` should be a base64 encoded image with no transparency.
379 | - Keep your palette image small, below 1mb is recommended 200k characters or less.
380 | - No need to include `data:image/png;base64,` in the base64 image.
381 |
382 | ```python
383 | {
384 | "prompt": "a raven with a glowing green eye",
385 | "width": 256,
386 | "height": 256,
387 | "num_images": 1,
388 | "seed": 1234,
389 | "input_palette": "iVBORw0KGgoAAAANSUhEUgAAAUA... ... ..."
390 | }
391 | ```
392 |
393 | - Optionally, you can also receive the original image before palette is applied by setting `return_pre_palette` to `true`:
394 |
395 | ```python
396 | {
397 | "prompt": "a raven with a glowing green eye",
398 | "width": 256,
399 | "height": 256,
400 | "num_images": 1,
401 | "seed": 1234,
402 | "input_palette": "iVBORw0KGgoAAAANSUhEUgAAAUA... ... ...",
403 | "return_pre_palette": true
404 | }
405 | ```
406 |
407 | When `return_pre_palette` is enabled, the response will include an additional string in the `base64_images` array, which is the original image before the palette is applied.
408 |
409 | ## Using background removal for transparent images
410 |
411 | - Simply `remove_bg` as a boolean
412 |
413 | ```python
414 | payload = {
415 | "prompt": "a raven with a glowing green eye",
416 | "width": 128,
417 | "height": 128,
418 | "remove_bg": True
419 | }
420 | ```
421 |
422 | - Optionally, you can also receive the original image before background removal by setting `return_non_bg_removed` to `true`:
423 |
424 | ```python
425 | payload = {
426 | "prompt": "a raven with a glowing green eye",
427 | "width": 128,
428 | "height": 128,
429 | "remove_bg": True,
430 | "return_non_bg_removed": True
431 | }
432 | ```
433 |
434 | When `return_non_bg_removed` is enabled, the response will include an additional string in the `base64_images` array, which is the original image before background removal.
435 |
436 | ## Using seamless tiling
437 |
438 | - Simply add `tile_x` and `tile_y` both as booleans
439 |
440 | ```python
441 | payload = {
442 | "prompt": "Stone bricks",
443 | "width": 128,
444 | "height": 128,
445 | "tile_x": true,
446 | "tile_y": true
447 | }
448 | ```
449 |
450 | ## Ignoring prompt expansion
451 | - You can use the `bypass_prompt_expansion` parameter to disable prompt expansion for your request.
452 | ```python
453 | payload = {
454 | "prompt": "a raven with a glowing green eye",
455 | "width": 128,
456 | "height": 128,
457 | "bypass_prompt_expansion": True
458 | }
459 | ```
460 |
461 | ## Image editing
462 | 
463 |
464 | - You can use the `https://api.retrodiffusion.ai/v1/edit` endpoint to edit images.
465 | - The request should be a POST request with the following parameters:
466 |
467 | ```json
468 | {
469 | "prompt": "add a hat",
470 | "inputImageBase64": "iVBORw0KGgoAAAANSUhEUgAAAUA...",
471 | }
472 | ```
473 |
474 | - We support sizes between 16x16 and 256x256
475 | - You can send any image within the size limits to be edited
476 | - Progressive editing is possible by sending the response you get from one task as the input for a new task
477 | - The cost is 5 credits per image edit
478 | - We have the following response format:
479 |
480 | ```json
481 | {
482 | "outputImageBase64": "iVBORw0KGgoAAAANSUhEUgAAAUA...",
483 | "remaining_credits": 999
484 | }
485 | ```
486 |
487 | ## FAQ
488 |
489 | - **How much does it cost?**
490 | - Cost is calculated based on the model and resolution you choose. You can check the cost of each request in our [web app](https://www.retrodiffusion.ai/)
491 | These formulas can be used as a guide for automated cost calculations:
492 | **Standard image model pricing**
493 | All costs are rounded to three decimal places.
494 | `rd_fast` styles:
495 |
496 | Balance cost = `max(0.015, ((width * height) + 100000) / 6000000) * number of images`
497 |
498 | `rd_plus` styles:
499 |
500 | Balance cost = `max(0.025, ((width * height) + 50000) / 2000000) * number of images`
501 |
502 | **Low resolution model pricing**
503 | `rd_plus__mc_texture`, `rd_plus__mc_item`, `rd_plus__low_res`, `rd_plus__classic`, `rd_plus__topdown_item`, `rd_plus__skill_icon`, `rd_tile__tile_variation`, `rd_tile__single_tile`, `rd_tile__tile_object`:
504 |
505 | Balance cost = `max(0.02, ((width * height) + 13700) / 600000) * number of images`
506 |
507 | `rd_pro` styles:
508 |
509 | Balance cost = `0.22 * number of images`
510 |
511 | **Editing class styles**
512 | `rd_pro__pixelate`
513 |
514 | Balance cost = `0.25 * number of images`
515 |
516 | **Unique model pricing:**
517 | `animation__four_angle_walking`, `animation__walking_and_idle`, `animation__small_sprites`, `animation__vfx`:
518 |
519 | Balance cost = `0.07`
520 |
521 | `rd_tile__tileset`, `rd_tile__tileset_advanced`:
522 |
523 | Balance cost = `0.10`
524 |
525 | `animation__any_animation`, `animation__8_dir_rotation`:
526 |
527 | Balance cost = `0.25`
528 |
529 |
530 |
531 |
532 | - **How can I check my remaining credits?**
533 | - You can make a GET request to the `https://api.retrodiffusion.ai/v1/inferences/credits` endpoint, with the header `X-RD-Token` set to your API key. The response will include the remaining credits in the following format:
534 |
535 | ```json
536 | {
537 | "credits": 999
538 | }
539 | ```
540 |
541 | - **Can I buy credits from the API?**
542 | - No, but to ensure you always have enough credits for your requests, you can set up **auto refills** in the [Payment Methods section](https://www.retrodiffusion.ai/app/payment-methods)
543 | - **What happened to RD_CLASSIC?**
544 | - We just dropped support for RD_CLASSIC
545 | - **What happened to RD_FLUX?**
546 | - We just renamed RD_FLUX to RD_FAST, so you can use it as before.
547 | - **What happened to the model parameter**
548 | - `model` is no longer required, as the model is determined by the `prompt_style` parameter.
549 | - **How to get images at native resolution?**
550 | - You can use the `upscale_output_factor` parameter to get images at native resolution. Set it to 1 for native resolution, or `null` for regular size.
551 |
--------------------------------------------------------------------------------