99 lines
3.4 KiB
Python
99 lines
3.4 KiB
Python
|
|
"""Image editing API methods: expand, relight, style-transfer, icons."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from typing import Any, Optional, Tuple
|
||
|
|
|
||
|
|
from freepik_cli.api.client import FreepikClient
|
||
|
|
from freepik_cli.api.models import IconStyle, get_output_urls, get_status, get_task_id
|
||
|
|
|
||
|
|
|
||
|
|
class EditAPI:
|
||
|
|
def __init__(self, client: FreepikClient) -> None:
|
||
|
|
self._client = client
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------
|
||
|
|
# Icon generation
|
||
|
|
# ------------------------------------------------------------------
|
||
|
|
|
||
|
|
def generate_icon(
|
||
|
|
self,
|
||
|
|
prompt: str,
|
||
|
|
style: IconStyle = IconStyle.COLOR,
|
||
|
|
num_inference_steps: int = 30,
|
||
|
|
guidance_scale: float = 7.5,
|
||
|
|
seed: Optional[int] = None,
|
||
|
|
) -> str:
|
||
|
|
"""Submit a text-to-icon task. Returns task_id."""
|
||
|
|
payload: dict[str, Any] = {
|
||
|
|
"prompt": prompt,
|
||
|
|
"style": style.value,
|
||
|
|
"num_inference_steps": num_inference_steps,
|
||
|
|
"guidance_scale": guidance_scale,
|
||
|
|
}
|
||
|
|
if seed is not None:
|
||
|
|
payload["seed"] = seed
|
||
|
|
|
||
|
|
raw = self._client.post("/v1/ai/text-to-icon", json=payload)
|
||
|
|
return get_task_id(raw)
|
||
|
|
|
||
|
|
def icon_status(self, task_id: str) -> Tuple[str, dict[str, Any]]:
|
||
|
|
raw = self._client.get(f"/v1/ai/text-to-icon/{task_id}")
|
||
|
|
return get_status(raw), raw
|
||
|
|
|
||
|
|
def render_icon(self, task_id: str, fmt: str = "png") -> str:
|
||
|
|
"""Get the download URL for a completed icon in PNG or SVG format."""
|
||
|
|
raw = self._client.post(f"/v1/ai/text-to-icon/{task_id}/render/{fmt}", json={})
|
||
|
|
data = raw.get("data", raw)
|
||
|
|
return data.get("url") or data.get("download_url") or ""
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------
|
||
|
|
# Relight
|
||
|
|
# ------------------------------------------------------------------
|
||
|
|
|
||
|
|
def relight_submit(
|
||
|
|
self,
|
||
|
|
image_b64: str,
|
||
|
|
prompt: Optional[str] = None,
|
||
|
|
style: Optional[str] = None,
|
||
|
|
) -> str:
|
||
|
|
payload: dict[str, Any] = {"image": image_b64}
|
||
|
|
if prompt:
|
||
|
|
payload["prompt"] = prompt
|
||
|
|
if style:
|
||
|
|
payload["style"] = style
|
||
|
|
|
||
|
|
raw = self._client.post("/v1/ai/image-relight", json=payload)
|
||
|
|
return get_task_id(raw)
|
||
|
|
|
||
|
|
def relight_status(self, task_id: str) -> Tuple[str, dict[str, Any]]:
|
||
|
|
raw = self._client.get(f"/v1/ai/image-relight/{task_id}")
|
||
|
|
return get_status(raw), raw
|
||
|
|
|
||
|
|
# ------------------------------------------------------------------
|
||
|
|
# Style Transfer
|
||
|
|
# ------------------------------------------------------------------
|
||
|
|
|
||
|
|
def style_transfer_submit(
|
||
|
|
self,
|
||
|
|
content_image_b64: str,
|
||
|
|
style_image_b64: str,
|
||
|
|
strength: Optional[float] = None,
|
||
|
|
) -> str:
|
||
|
|
payload: dict[str, Any] = {
|
||
|
|
"content_image": content_image_b64,
|
||
|
|
"style_image": style_image_b64,
|
||
|
|
}
|
||
|
|
if strength is not None:
|
||
|
|
payload["strength"] = strength
|
||
|
|
|
||
|
|
raw = self._client.post("/v1/ai/image-style-transfer", json=payload)
|
||
|
|
return get_task_id(raw)
|
||
|
|
|
||
|
|
def style_transfer_status(self, task_id: str) -> Tuple[str, dict[str, Any]]:
|
||
|
|
raw = self._client.get(f"/v1/ai/image-style-transfer/{task_id}")
|
||
|
|
return get_status(raw), raw
|
||
|
|
|
||
|
|
def get_output_urls(self, raw: dict[str, Any]) -> list[str]:
|
||
|
|
return get_output_urls(raw)
|