diff --git a/orchestrators/imajin-pipeline/src/image_pipeline/models.py b/orchestrators/imajin-pipeline/src/image_pipeline/models.py index f8d038f2..9f05afa8 100644 --- a/orchestrators/imajin-pipeline/src/image_pipeline/models.py +++ b/orchestrators/imajin-pipeline/src/image_pipeline/models.py @@ -326,4 +326,10 @@ class ImagePipelineRequest(BaseModel): # Output options return_format: Literal["base64", "url"] = Field("base64") output_format: Literal["png", "webp"] = Field("png") + output_quality: int = Field( + 75, + ge=1, + le=100, + description="Output quality for lossy formats like WebP (1-100). Default 75 for good balance." + ) save_to_storage: bool = Field(False, description="Save to cloud storage") diff --git a/orchestrators/imajin-pipeline/src/image_pipeline/stages/output.py b/orchestrators/imajin-pipeline/src/image_pipeline/stages/output.py index 652b2afd..029809a6 100644 --- a/orchestrators/imajin-pipeline/src/image_pipeline/stages/output.py +++ b/orchestrators/imajin-pipeline/src/image_pipeline/stages/output.py @@ -67,7 +67,7 @@ class OutputStage(PipelineStage): save_kwargs = {"format": output_format} if output_format == "WEBP": - save_kwargs["quality"] = 90 + save_kwargs["quality"] = request.output_quality elif output_format == "PNG": save_kwargs["optimize"] = True diff --git a/scripts/run/generate_command.py b/scripts/run/generate_command.py index c46e0631..20dfd4a8 100644 --- a/scripts/run/generate_command.py +++ b/scripts/run/generate_command.py @@ -43,6 +43,7 @@ def generate_image( seed: Optional[int] = None, diffusion_url: str = "http://localhost:8002", enable_anatomy_fix: bool = False, + output_quality: int = 75, ) -> bool: """Generate an image and save to disk. @@ -57,6 +58,7 @@ def generate_image( seed: Random seed for reproducibility diffusion_url: Diffusion service URL enable_anatomy_fix: Enable anatomical error correction (hands, faces) + output_quality: WebP output quality (1-100) Returns: True if successful @@ -76,6 +78,7 @@ def generate_image( "steps": steps, "guidanceScale": guidance_scale, "outputFormat": output_format, + "outputQuality": output_quality, "enableModeration": False, # Skip moderation for one-off generation "enableAnatomyFix": enable_anatomy_fix, } @@ -90,8 +93,10 @@ def generate_image( print(f" Prompt: {prompt[:80]}{'...' if len(prompt) > 80 else ''}") print(f" Layout: {layout}") print(f" Steps: {steps}") + if output_format == "webp": + print(f" Quality: {output_quality}") if enable_anatomy_fix: - print(f" Anatomy fix: enabled") + print(" Anatomy fix: enabled") print() try: @@ -250,6 +255,13 @@ Available layouts: help="Enable anatomical error correction (hands, faces)", ) + parser.add_argument( + "--quality", + type=int, + default=75, + help="Output quality for WebP (1-100, default: 75)", + ) + parser.add_argument( "--start-service", action="store_true", @@ -314,6 +326,7 @@ Available layouts: seed=parsed.seed, diffusion_url=diffusion_url, enable_anatomy_fix=parsed.anatomy_fix, + output_quality=parsed.quality, ) return 0 if success else 1 diff --git a/services/imajin-diffusion/service/src/api/routes/generate.py b/services/imajin-diffusion/service/src/api/routes/generate.py index 408412df..3cddd7fd 100644 --- a/services/imajin-diffusion/service/src/api/routes/generate.py +++ b/services/imajin-diffusion/service/src/api/routes/generate.py @@ -99,6 +99,7 @@ class GenerateRequest(BaseModel): # Output options output_format: Literal["png", "webp"] = Field("png") + output_quality: int = Field(75, ge=1, le=100, description="WebP output quality (1-100)") class GenerateResponse(BaseModel): @@ -187,6 +188,7 @@ async def generate_single(request: GenerateRequest, req: Request) -> GenerateRes enable_anatomy_fix=request.enable_anatomy_fix, enable_watermark_removal=request.enable_watermark_removal, output_format=request.output_format, + output_quality=request.output_quality, ) # Execute 7-stage pipeline @@ -240,6 +242,7 @@ async def generate_batch(request: BatchRequest, req: Request) -> BatchResponse: enable_moderation=img_request.enable_moderation, enable_anatomy_fix=img_request.enable_anatomy_fix, output_format=img_request.output_format, + output_quality=img_request.output_quality, ) context = ImagePipelineContext(request=pipeline_request) @@ -423,6 +426,7 @@ async def generate_async(request: GenerateRequest, req: Request) -> dict[str, An enable_anatomy_fix=request.enable_anatomy_fix, enable_watermark_removal=request.enable_watermark_removal, output_format=request.output_format, + output_quality=request.output_quality, ) async def execute_job() -> None: