Spaces:
Sleeping
Sleeping
File size: 5,127 Bytes
f38e71b 69f734d f38e71b 00d3b13 f38e71b 00d3b13 69f734d b514f65 00d3b13 f38e71b b514f65 00d3b13 5ad001d 00d3b13 69f734d 00d3b13 b514f65 00d3b13 5ad001d f38e71b 00d3b13 f38e71b 69f734d 00d3b13 69f734d 00d3b13 a8621bc 00d3b13 69f734d 00d3b13 69f734d 00d3b13 69f734d 00d3b13 b514f65 69f734d f38e71b 00d3b13 69f734d 5ad001d a8621bc 00d3b13 b514f65 69f734d b514f65 00d3b13 b514f65 00d3b13 69f734d 5ad001d 00d3b13 69f734d 5ad001d b514f65 69f734d 00d3b13 69f734d 00d3b13 69f734d 00d3b13 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
import fitz # PyMuPDF
import base64
import logging
from fastapi import FastAPI, File, UploadFile
from fastapi.middleware.cors import CORSMiddleware
# Set up logging for Hugging Face console
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI()
# Enable CORS for Figma Plugin access
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
def safe_f(val, default=0.0):
"""Guards against float(None) errors."""
if val is None:
return default
try:
return float(val)
except (TypeError, ValueError):
return default
def get_figma_color(color):
"""Converts various PDF color formats to Figma 0-1 RGB."""
if color is None:
return None
try:
# If color is an integer, convert to RGB tuple
if isinstance(color, int):
color = fitz.utils.getColor(color)
if not isinstance(color, (list, tuple)):
return None
# Handle Grayscale (1 component)
if len(color) == 1:
val = safe_f(color[0])
return {"r": val, "g": val, "b": val}
# Handle RGB/CMYK (take first 3)
if len(color) >= 3:
return {
"r": safe_f(color[0]),
"g": safe_f(color[1]),
"b": safe_f(color[2])
}
except Exception:
return None
return None
@app.get("/")
async def root():
return {"status": "PDF Converter is Online", "engine": "PyMuPDF"}
@app.post("/convert")
async def convert_pdf(file: UploadFile = File(...)):
try:
logger.info(f"Processing: {file.filename}")
pdf_bytes = await file.read()
doc = fitz.open(stream=pdf_bytes, filetype="pdf")
pages_data = []
for page in doc:
page_dict = {
"width": safe_f(page.rect.width),
"height": safe_f(page.rect.height),
"elements": []
}
# 1. TEXT AND IMAGES (using dict for structured layout)
raw_dict = page.get_text("dict")
for block in raw_dict.get("blocks", []):
# Type 0 is Text
if block.get("type") == 0:
for line in block.get("lines", []):
for span in line.get("spans", []):
page_dict["elements"].append({
"type": "TEXT",
"content": span.get("text", ""),
"x": safe_f(span["bbox"][0]),
"y": safe_f(span["bbox"][1]),
"size": safe_f(span.get("size"), 12.0),
"color": get_figma_color(span.get("color"))
})
# Type 1 is Image
elif block.get("type") == 1:
page_dict["elements"].append({
"type": "IMAGE",
"bytes": base64.b64encode(block["image"]).decode("utf-8"),
"x": safe_f(block["bbox"][0]),
"y": safe_f(block["bbox"][1]),
"width": safe_f(block["bbox"][2] - block["bbox"][0]),
"height": safe_f(block["bbox"][3] - block["bbox"][1])
})
# 2. VECTOR DRAWINGS (Paths, Lines, Rectangles)
for path in page.get_drawings():
d_path = ""
for item in path.get("items", []):
# Line
if item[0] == "l":
d_path += f"M {safe_f(item[1].x)} {safe_f(item[1].y)} L {safe_f(item[2].x)} {safe_f(item[2].y)} "
# Rectangle
elif item[0] == "re":
r = item[1]
d_path += f"M {safe_f(r.x0)} {safe_f(r.y0)} L {safe_f(r.x1)} {safe_f(r.y0)} L {safe_f(r.x1)} {safe_f(r.y1)} L {safe_f(r.x0)} {safe_f(r.y1)} Z "
# Curve
elif item[0] == "c":
d_path += f"M {safe_f(item[1].x)} {safe_f(item[1].y)} C {safe_f(item[2].x)} {safe_f(item[2].y)} {safe_f(item[3].x)} {safe_f(item[3].y)} {safe_f(item[4].x)} {safe_f(item[4].y)} "
if d_path:
page_dict["elements"].append({
"type": "VECTOR",
"path": d_path.strip(),
"fill": get_figma_color(path.get("fill")),
"stroke": get_figma_color(path.get("color")),
"strokeWeight": safe_f(path.get("width"), 1.0)
})
pages_data.append(page_dict)
doc.close()
return {"pages": pages_data}
except Exception as e:
logger.error(f"Error during conversion: {str(e)}")
return {"error": str(e)}
if __name__ == "__main__":
import uvicorn
# Important: Hugging Face uses port 7860
uvicorn.run(app, host="0.0.0.0", port=7860) |