diff --git a/server.py b/server.py index 7756484..3addbb3 100644 --- a/server.py +++ b/server.py @@ -1626,9 +1626,9 @@ def get_visit_stats(): # ─── File Uploads ─────────────────────────────────────────────────────────── ICON_MAX_SIZE = 2 * 1024 * 1024 # 2 MB -PHOTO_MAX_SIZE = 10 * 1024 * 1024 # 10 MB +PHOTO_MAX_SIZE = 20 * 1024 * 1024 # 20 MB ICON_ALLOWED_EXTS = {".png", ".jpg", ".jpeg", ".svg"} -PHOTO_ALLOWED_EXTS = {".png", ".jpg", ".jpeg"} +PHOTO_ALLOWED_EXTS = {".png", ".jpg", ".jpeg", ".dng"} def _dms_to_decimal(dms_tuple: tuple, ref: str) -> float: @@ -1827,14 +1827,17 @@ async def upload_photo(file: UploadFile = File(...), exif_data: str = Form(None) @app.post("/api/ocr", status_code=200) -async def ocr_sticker(file: UploadFile = File(...)): +async def ocr_sticker(file: UploadFile = File(...), exif_data: str = Form(None)): """OCR a sticker photo to extract machine_id from XXXXX-XXXXXX format. Accepts an image upload, runs Tesseract OCR, and looks for a pattern like '12345-678901'. Also extracts EXIF GPS data from the raw file bytes before processing, returning both in one response. - Returns {machine_id, exif_gps (if found), raw_text, raw_match, confidence}. + When exif_data is provided (gallery upload), saves the photo permanently and + re-embeds the client-side EXIF data for a proper round-trip. + + Returns {machine_id, exif_gps (if found), path (if permanent), raw_text, ...}. """ # Read file contents first (validate size before saving) contents = await file.read() @@ -1844,26 +1847,40 @@ async def ocr_sticker(file: UploadFile = File(...)): # Extract EXIF GPS from raw bytes before any processing exif_gps = _extract_gps_from_bytes(contents) if contents else None - # Save temp file for OCR — try original extension, fallback to jpg - ext = file.filename.rsplit(".", 1)[-1].lower() if "." in (file.filename or "") else "jpg" - if ext not in {"png", "jpg", "jpeg", "webp", "bmp", "dng", "tiff", "tif"}: - ext = "jpg" # PIL detects format from bytes regardless of extension - temp_dir = Path(UPLOADS_DIR / "ocr") - temp_dir.mkdir(parents=True, exist_ok=True) - temp_path = temp_dir / f"{uuid.uuid4().hex}.{ext or 'jpg'}" - temp_path.write_bytes(contents) + # If client sent EXIF data (gallery upload), save permanently with EXIF round-trip + saved_path: str | None = None + if exif_data: + try: + saved_path = _save_upload_bytes(contents, file.filename, "photos", PHOTO_ALLOWED_EXTS, PHOTO_MAX_SIZE) + _re_embed_exif(Path(UPLOADS_DIR / saved_path.lstrip("/")), exif_data) + except Exception: + saved_path = None # fall through to temp-file path below + + # Save file for OCR — use permanent path if available, otherwise temp + if saved_path: + ocr_path = Path(UPLOADS_DIR / saved_path.lstrip("/")) + else: + ext = file.filename.rsplit(".", 1)[-1].lower() if "." in (file.filename or "") else "jpg" + if ext not in {"png", "jpg", "jpeg", "webp", "bmp", "dng", "tiff", "tif"}: + ext = "jpg" + temp_dir = Path(UPLOADS_DIR / "ocr") + temp_dir.mkdir(parents=True, exist_ok=True) + ocr_path = temp_dir / f"{uuid.uuid4().hex}.{ext or 'jpg'}" + ocr_path.write_bytes(contents) try: - img = PILImage.open(temp_path) + img = PILImage.open(ocr_path) # Preprocess: convert to grayscale and increase contrast for better OCR img_gray = img.convert("L") text = pytesseract.image_to_string(img_gray, config="--psm 6") except Exception as e: - temp_path.unlink(missing_ok=True) + if not saved_path: + ocr_path.unlink(missing_ok=True) raise HTTPException(status_code=500, detail=f"OCR processing failed: {str(e)}") - # Don't keep temp file after processing - temp_path.unlink(missing_ok=True) + # Clean up temp file (but keep permanent photos) + if not saved_path: + ocr_path.unlink(missing_ok=True) # Build response — search for XXXXX-XXXXXX pattern (5 digits - 6 digits or more) match = re.search(r"(\d{5})[-\s]*(\d{6,})", text) @@ -1900,6 +1917,8 @@ async def ocr_sticker(file: UploadFile = File(...)): if exif_gps: result["exif_gps"] = exif_gps + if saved_path: + result["path"] = saved_path return result diff --git a/static/index.html b/static/index.html index 97322b2..ad4251e 100644 --- a/static/index.html +++ b/static/index.html @@ -883,6 +883,8 @@ + +