"""Background Remover Service - Clipping Magic API""" import httpx import os import base64 from uuid import uuid4 from datetime import datetime from app.database import SessionLocal from app.models.job import Job from app.models.asset import Asset from app.config import settings async def remove_background(job_id: str): """Remove background from image using Clipping Magic""" db = SessionLocal() try: job = db.query(Job).filter(Job.id == job_id).first() if not job: return input_data = job.input_data input_asset_ids = job.input_asset_ids if not input_asset_ids: raise ValueError("No input asset provided") input_asset = db.query(Asset).filter(Asset.id == input_asset_ids[0]).first() if not input_asset: raise ValueError("Input asset not found") job.progress = 10 job.api_provider = "clipping_magic" db.commit() # Read input image with open(input_asset.file_path, "rb") as f: image_data = f.read() output_format = input_data.get("output_format", "png") job.progress = 20 db.commit() # Call Clipping Magic API async with httpx.AsyncClient(timeout=120) as client: # Decode the API key (it's base64 encoded in the original code) api_key = settings.clipping_magic_api_key response = await client.post( "https://clippingmagic.com/api/v1/images", auth=(api_key, ""), files={"image": (input_asset.original_filename, image_data, input_asset.mime_type)}, data={ "format": "result" if output_format == "png" else "clipping_path_tiff" } ) response.raise_for_status() result = response.json() image_id = result.get("image", {}).get("id") job.progress = 50 db.commit() if image_id: # Download the result download_response = await client.get( f"https://clippingmagic.com/api/v1/images/{image_id}", auth=(api_key, ""), params={"format": "result" if output_format == "png" else "clipping_path_tiff"} ) download_response.raise_for_status() processed_data = download_response.content job.progress = 80 db.commit() # Save output ext = "png" if output_format == "png" else "tiff" filename = f"nobg_{uuid4()}.{ext}" storage_path = os.path.join(settings.storage_path, "images") os.makedirs(storage_path, exist_ok=True) file_path = os.path.join(storage_path, filename) with open(file_path, "wb") as f: f.write(processed_data) # Create output asset output_asset = Asset( user_id=job.user_id, project_id=job.project_id, original_filename=filename, stored_filename=filename, file_path=file_path, file_type="image", mime_type=f"image/{ext}", file_size_bytes=len(processed_data), width=input_asset.width, height=input_asset.height, source_module="background_remover", source_job_id=job.id, parent_asset_id=input_asset.id, metadata={"output_format": output_format} ) db.add(output_asset) db.commit() db.refresh(output_asset) job.output_asset_ids = [output_asset.id] job.output_data = {"asset_id": str(output_asset.id), "file_path": file_path} # Delete from Clipping Magic (cleanup) await client.post( f"https://clippingmagic.com/api/v1/images/{image_id}/delete", auth=(api_key, "") ) job.progress = 100 job.status = "completed" job.completed_at = datetime.utcnow() db.commit() except Exception as e: job.status = "failed" job.error_message = str(e) db.commit() finally: db.close()