from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel import cv2 import zxingcpp import numpy as np from PIL import Image import base64 import io from typing import Dict, Any app = FastAPI(title="Barcode Scanner API", version="1.0.0") # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], # In production, specify your frontend domain allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) class ImageRequest(BaseModel): image: str # Base64 encoded image class ScanResponse(BaseModel): status: str text: str = None format: str = None message: str = None def decode_base64_image(base64_string: str) -> np.ndarray: """Decode base64 image to numpy array""" try: # Handle data URI format if base64_string.startswith('data:image'): # Remove the data:image/jpeg;base64, prefix base64_string = base64_string.split(',')[1] # Decode base64 image_bytes = base64.b64decode(base64_string) # Convert to PIL Image pil_image = Image.open(io.BytesIO(image_bytes)) # Convert to numpy array image_array = np.array(pil_image) return image_array except Exception as e: raise HTTPException(status_code=400, detail=f"Invalid image format: {str(e)}") @app.get("/") async def root(): return {"message": "Barcode Scanner API is running!"} @app.get("/health") async def health_check(): return {"status": "healthy"} @app.post("/scan", response_model=ScanResponse) async def scan_barcode(request: ImageRequest): """Scan barcode from base64 encoded image""" try: # Decode the base64 image image_array = decode_base64_image(request.image) # Convert RGB to BGR for OpenCV (if needed) if len(image_array.shape) == 3 and image_array.shape[2] == 3: bgr_image = cv2.cvtColor(image_array, cv2.COLOR_RGB2BGR) elif len(image_array.shape) == 3 and image_array.shape[2] == 4: # Handle RGBA images rgb_image = cv2.cvtColor(image_array, cv2.COLOR_RGBA2RGB) bgr_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2BGR) else: bgr_image = image_array # Scan for barcodes results = zxingcpp.read_barcodes(bgr_image) if results: # Return the first barcode found barcode = results[0] return ScanResponse( status="success", text=barcode.text, format=str(barcode.format) ) else: return ScanResponse( status="error", message="No barcode detected" ) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=f"Processing error: {str(e)}") # For HuggingFace Spaces, you might need this if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=7860)