Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1833,7 +1833,7 @@ def similarity_matching(input_json_path: str, project_folder:str) -> str:
|
|
1833 |
# DEFINE PATHS #
|
1834 |
# ============================== #
|
1835 |
image_dirs = [backdrop_images_path, sprite_images_path]
|
1836 |
-
|
1837 |
project_json_path = os.path.join(project_folder, "project.json")
|
1838 |
|
1839 |
# ============================== #
|
@@ -1869,6 +1869,7 @@ def similarity_matching(input_json_path: str, project_folder:str) -> str:
|
|
1869 |
SPRITE_DIR / "Crab.sprite3" / "bear_element.png",
|
1870 |
SPRITE_DIR / "Soccer Ball.sprite3" / "cat_football.png",
|
1871 |
]
|
|
|
1872 |
# ============================== #
|
1873 |
# DECODE SPRITE IMAGES #
|
1874 |
# ============================== #
|
@@ -2121,41 +2122,45 @@ def upscale_image(image: Image.Image, scale: int = 2) -> Image.Image:
|
|
2121 |
logger.error(f"❌ Error during image upscaling: {str(e)}")
|
2122 |
return image
|
2123 |
|
2124 |
-
def create_sb3_archive(project_folder
|
2125 |
"""
|
2126 |
Zips the project folder and renames it to an .sb3 file.
|
|
|
2127 |
Args:
|
2128 |
-
project_folder (
|
2129 |
project_id (str): The unique ID for the project, used for naming the .sb3 file.
|
|
|
2130 |
Returns:
|
2131 |
-
|
2132 |
"""
|
2133 |
print(" --------------------------------------- create_sb3_archive INITIALIZE ---------------------------------------")
|
2134 |
-
|
|
|
|
|
2135 |
zip_path = None
|
2136 |
sb3_path = None
|
2137 |
try:
|
2138 |
-
|
2139 |
-
|
2140 |
-
zip_path_str = shutil.make_archive(str(output_base_name), 'zip', root_dir=str(project_folder))
|
2141 |
-
zip_path = Path(zip_path_str) # Convert back to Path object
|
2142 |
logger.info(f"Project folder zipped to: {zip_path}")
|
2143 |
-
|
2144 |
# 2. Rename the .zip file to .sb3
|
2145 |
-
sb3_path =
|
2146 |
os.rename(zip_path, sb3_path)
|
|
|
2147 |
logger.info(f"Renamed {zip_path} to {sb3_path}")
|
2148 |
|
2149 |
return sb3_path
|
2150 |
except Exception as e:
|
2151 |
-
logger.error(f"Error creating SB3 archive for {project_id}: {e}"
|
2152 |
# Clean up any partial files if an error occurs
|
2153 |
-
if zip_path and
|
2154 |
os.remove(zip_path)
|
2155 |
-
if sb3_path and
|
2156 |
os.remove(sb3_path)
|
2157 |
return None
|
2158 |
|
|
|
2159 |
@app.route('/')
|
2160 |
def index():
|
2161 |
return render_template('app_index.html')
|
@@ -2166,30 +2171,28 @@ def download_sb3(project_id):
|
|
2166 |
Allows users to download the generated .sb3 Scratch project file.
|
2167 |
"""
|
2168 |
sb3_filename = f"{project_id}.sb3"
|
2169 |
-
sb3_filepath =
|
2170 |
|
2171 |
try:
|
2172 |
-
if
|
2173 |
logger.info(f"Serving SB3 file for project ID: {project_id}")
|
|
|
2174 |
return send_from_directory(
|
2175 |
-
directory=
|
2176 |
path=sb3_filename,
|
2177 |
-
as_attachment=True,
|
2178 |
-
download_name=sb3_filename
|
2179 |
)
|
2180 |
else:
|
2181 |
-
logger.warning(f"SB3 file not found for ID: {project_id}
|
2182 |
return jsonify({"error": "Scratch project file not found"}), 404
|
2183 |
except Exception as e:
|
2184 |
-
logger.error(f"Error serving SB3 file for ID {project_id}: {e}"
|
2185 |
return jsonify({"error": "Failed to retrieve Scratch project file"}), 500
|
2186 |
|
|
|
2187 |
@app.route('/process_pdf', methods=['POST'])
|
2188 |
def process_pdf():
|
2189 |
-
project_id = None
|
2190 |
-
project_folder = None
|
2191 |
-
temp_dir = None
|
2192 |
-
extracted_json_parent_dir = None # Initialize for finally block cleanup or later use
|
2193 |
try:
|
2194 |
logger.info("Received request to process PDF.")
|
2195 |
if 'pdf_file' not in request.files:
|
@@ -2200,48 +2203,59 @@ def process_pdf():
|
|
2200 |
if pdf_file.filename == '':
|
2201 |
return jsonify({"error": "Empty filename"}), 400
|
2202 |
|
|
|
|
|
|
|
2203 |
project_id = str(uuid.uuid4()).replace('-', '')
|
|
|
2204 |
project_folder = OUTPUT_DIR / project_id
|
2205 |
|
2206 |
-
|
2207 |
-
|
2208 |
-
|
|
|
|
|
|
|
2209 |
filename = secure_filename(pdf_file.filename)
|
2210 |
-
temp_dir =
|
2211 |
-
saved_pdf_path = temp_dir
|
2212 |
pdf_file.save(saved_pdf_path)
|
2213 |
|
|
|
2214 |
logger.info(f"Saved uploaded PDF to: {saved_pdf_path}")
|
2215 |
|
2216 |
-
#
|
2217 |
-
|
2218 |
-
|
2219 |
-
|
2220 |
-
|
2221 |
-
)
|
2222 |
-
|
2223 |
-
# Now, directly use extracted_sprites_json_file_path to check for its existence
|
2224 |
-
if not extracted_sprites_json_file_path.exists():
|
2225 |
-
logger.error(f"No extracted_sprites.json found at {extracted_sprites_json_file_path}")
|
2226 |
-
return jsonify({"error": "No extracted_sprites.json found"}), 500
|
2227 |
|
2228 |
-
|
2229 |
-
|
2230 |
|
2231 |
-
#
|
2232 |
-
|
2233 |
-
|
|
|
|
|
2234 |
|
2235 |
with open(project_output, 'r') as f:
|
2236 |
project_skeleton = json.load(f)
|
2237 |
|
2238 |
-
|
|
|
|
|
2239 |
page = images[0]
|
|
|
2240 |
buf = BytesIO()
|
2241 |
page.save(buf, format="PNG")
|
2242 |
img_bytes = buf.getvalue()
|
2243 |
img_b64 = base64.b64encode(img_bytes).decode("utf-8")
|
|
|
2244 |
|
|
|
2245 |
# initial_state_dict = {
|
2246 |
# "project_json": project_skeleton,
|
2247 |
# "description": "The pseudo code for the script",
|
@@ -2252,59 +2266,31 @@ def process_pdf():
|
|
2252 |
# "temporary_node": {},
|
2253 |
# }
|
2254 |
|
2255 |
-
# final_state_dict = app_graph.invoke(initial_state_dict)
|
2256 |
|
2257 |
-
final_project_json =
|
|
|
2258 |
|
|
|
2259 |
with open(project_output, "w") as f:
|
2260 |
json.dump(final_project_json, f, indent=2)
|
2261 |
logger.info(f"Final project JSON saved to {project_output}")
|
2262 |
|
|
|
2263 |
sb3_file_path = create_sb3_archive(project_folder, project_id)
|
2264 |
if sb3_file_path:
|
2265 |
logger.info(f"Successfully created SB3 file: {sb3_file_path}")
|
2266 |
-
|
|
|
2267 |
print(f"DOWNLOAD_URL: {download_url}")
|
2268 |
-
return jsonify({"message": "
|
2269 |
else:
|
2270 |
return jsonify(error="Failed to create SB3 archive"), 500
|
2271 |
|
2272 |
except Exception as e:
|
2273 |
logger.error(f"Error during processing the pdf workflow for project ID {project_id}: {e}", exc_info=True)
|
2274 |
-
return jsonify({"error": f"❌ Failed to process PDF: {str(e)}"}), 500
|
2275 |
-
|
2276 |
-
if temp_dir and temp_dir.exists():
|
2277 |
-
shutil.rmtree(temp_dir)
|
2278 |
-
logger.info(f"Cleaned up temporary directory: {temp_dir}")
|
2279 |
-
|
2280 |
-
# Optional: Clean up the extracted JSON and image directories for this project_id
|
2281 |
-
# if extracted_json_parent_dir and extracted_json_parent_dir.exists():
|
2282 |
-
# shutil.rmtree(extracted_json_parent_dir)
|
2283 |
-
# logger.info(f"Cleaned up extracted JSON directory: {extracted_json_parent_dir}")
|
2284 |
-
# if pdf_filename_stem: # You'd need to get pdf_filename_stem from `filename` earlier
|
2285 |
-
# corresponding_image_dir = DETECTED_IMAGE_DIR / pdf_filename_stem
|
2286 |
-
# if corresponding_image_dir.exists():
|
2287 |
-
# shutil.rmtree(corresponding_image_dir)
|
2288 |
-
# logger.info(f"Cleaned up detected image directory: {corresponding_image_dir}")
|
2289 |
-
|
2290 |
-
|
2291 |
-
@app.route('/list_projects', methods=['GET'])
|
2292 |
-
def list_projects():
|
2293 |
-
"""
|
2294 |
-
Lists all generated .sb3 files and their download URLs for debugging.
|
2295 |
-
"""
|
2296 |
-
try:
|
2297 |
-
sb3_files = []
|
2298 |
-
for file_path in GEN_PROJECT_DIR.iterdir():
|
2299 |
-
if file_path.suffix == '.sb3' and file_path.is_file():
|
2300 |
-
project_id = file_path.stem
|
2301 |
-
download_url = f"/download_sb3/{project_id}"
|
2302 |
-
sb3_files.append({"project_id": project_id, "download_url": download_url, "filename": file_path.name})
|
2303 |
-
|
2304 |
-
return jsonify({"generated_sb3_files": sb3_files}), 200
|
2305 |
-
except Exception as e:
|
2306 |
-
logger.error(f"Error listing projects: {e}", exc_info=True)
|
2307 |
-
return jsonify({"error": "Failed to list generated projects"}), 500
|
2308 |
-
|
2309 |
if __name__ == '__main__':
|
|
|
2310 |
app.run(host='0.0.0.0', port=7860, debug=True)
|
|
|
1833 |
# DEFINE PATHS #
|
1834 |
# ============================== #
|
1835 |
image_dirs = [backdrop_images_path, sprite_images_path]
|
1836 |
+
print(" --------------------------------------- input_json_path ---------------------------------------", input_json_path)
|
1837 |
project_json_path = os.path.join(project_folder, "project.json")
|
1838 |
|
1839 |
# ============================== #
|
|
|
1869 |
SPRITE_DIR / "Crab.sprite3" / "bear_element.png",
|
1870 |
SPRITE_DIR / "Soccer Ball.sprite3" / "cat_football.png",
|
1871 |
]
|
1872 |
+
print(" --------------------------------------- folder_image_paths ---------------------------------------\n", folder_image_paths)
|
1873 |
# ============================== #
|
1874 |
# DECODE SPRITE IMAGES #
|
1875 |
# ============================== #
|
|
|
2122 |
logger.error(f"❌ Error during image upscaling: {str(e)}")
|
2123 |
return image
|
2124 |
|
2125 |
+
def create_sb3_archive(project_folder, project_id):
|
2126 |
"""
|
2127 |
Zips the project folder and renames it to an .sb3 file.
|
2128 |
+
|
2129 |
Args:
|
2130 |
+
project_folder (str): The path to the directory containing the project.json and assets.
|
2131 |
project_id (str): The unique ID for the project, used for naming the .sb3 file.
|
2132 |
+
|
2133 |
Returns:
|
2134 |
+
str: The path to the created .sb3 file, or None if an error occurred.
|
2135 |
"""
|
2136 |
print(" --------------------------------------- create_sb3_archive INITIALIZE ---------------------------------------")
|
2137 |
+
# output_filename = os.path.join("outputs", project_id)
|
2138 |
+
#output_filename = OUTPUT_DIR / project_id
|
2139 |
+
output_filename = GEN_PROJECT_DIR / project_id
|
2140 |
zip_path = None
|
2141 |
sb3_path = None
|
2142 |
try:
|
2143 |
+
zip_path = shutil.make_archive(output_filename, 'zip', root_dir=project_folder)
|
2144 |
+
print(" --------------------------------------- zip_path_str ---------------------------------------", output_base_name, project_folder)
|
|
|
|
|
2145 |
logger.info(f"Project folder zipped to: {zip_path}")
|
2146 |
+
|
2147 |
# 2. Rename the .zip file to .sb3
|
2148 |
+
sb3_path = f"{output_filename}.sb3"
|
2149 |
os.rename(zip_path, sb3_path)
|
2150 |
+
print(" --------------------------------------- rename paths ---------------------------------------", zip_path, sb3_path)
|
2151 |
logger.info(f"Renamed {zip_path} to {sb3_path}")
|
2152 |
|
2153 |
return sb3_path
|
2154 |
except Exception as e:
|
2155 |
+
logger.error(f"Error creating SB3 archive for {project_id}: {e}")
|
2156 |
# Clean up any partial files if an error occurs
|
2157 |
+
if zip_path and os.path.exists(zip_path):
|
2158 |
os.remove(zip_path)
|
2159 |
+
if sb3_path and os.path.exists(sb3_path):
|
2160 |
os.remove(sb3_path)
|
2161 |
return None
|
2162 |
|
2163 |
+
|
2164 |
@app.route('/')
|
2165 |
def index():
|
2166 |
return render_template('app_index.html')
|
|
|
2171 |
Allows users to download the generated .sb3 Scratch project file.
|
2172 |
"""
|
2173 |
sb3_filename = f"{project_id}.sb3"
|
2174 |
+
sb3_filepath = os.path.join("generated_projects", sb3_filename)
|
2175 |
|
2176 |
try:
|
2177 |
+
if os.path.exists(sb3_filepath):
|
2178 |
logger.info(f"Serving SB3 file for project ID: {project_id}")
|
2179 |
+
# send_from_directory serves the file and handles content-disposition for download
|
2180 |
return send_from_directory(
|
2181 |
+
directory="generated_projects",
|
2182 |
path=sb3_filename,
|
2183 |
+
as_attachment=True, # This makes the browser download the file
|
2184 |
+
download_name=sb3_filename # This sets the filename for the download
|
2185 |
)
|
2186 |
else:
|
2187 |
+
logger.warning(f"SB3 file not found for ID: {project_id}")
|
2188 |
return jsonify({"error": "Scratch project file not found"}), 404
|
2189 |
except Exception as e:
|
2190 |
+
logger.error(f"Error serving SB3 file for ID {project_id}: {e}")
|
2191 |
return jsonify({"error": "Failed to retrieve Scratch project file"}), 500
|
2192 |
|
2193 |
+
# API endpoint
|
2194 |
@app.route('/process_pdf', methods=['POST'])
|
2195 |
def process_pdf():
|
|
|
|
|
|
|
|
|
2196 |
try:
|
2197 |
logger.info("Received request to process PDF.")
|
2198 |
if 'pdf_file' not in request.files:
|
|
|
2203 |
if pdf_file.filename == '':
|
2204 |
return jsonify({"error": "Empty filename"}), 400
|
2205 |
|
2206 |
+
# ================================================= #
|
2207 |
+
# Generate Random UUID for project folder name #
|
2208 |
+
# ================================================= #
|
2209 |
project_id = str(uuid.uuid4()).replace('-', '')
|
2210 |
+
# project_folder = os.path.join("outputs", f"{project_id}")
|
2211 |
project_folder = OUTPUT_DIR / project_id
|
2212 |
|
2213 |
+
# =========================================================================== #
|
2214 |
+
# Create empty json in project_{random_id} folder #
|
2215 |
+
# =========================================================================== #
|
2216 |
+
#os.makedirs(project_folder, exist_ok=True)
|
2217 |
+
|
2218 |
+
# Save the uploaded PDF temporarily
|
2219 |
filename = secure_filename(pdf_file.filename)
|
2220 |
+
temp_dir = tempfile.mkdtemp()
|
2221 |
+
saved_pdf_path = os.path.join(temp_dir, filename)
|
2222 |
pdf_file.save(saved_pdf_path)
|
2223 |
|
2224 |
+
# logger.info(f"Created project folder: {project_folder}")
|
2225 |
logger.info(f"Saved uploaded PDF to: {saved_pdf_path}")
|
2226 |
|
2227 |
+
# Extract & process
|
2228 |
+
json_path = None
|
2229 |
+
output_path, result = extract_images_from_pdf(saved_pdf_path, json_path)
|
2230 |
+
print(" --------------------------------------- zip_path_str ---------------------------------------", output_path, result)
|
2231 |
+
# Check extracted_sprites.json for "scratch block" in any 'name'
|
2232 |
+
# extracted_dir = os.path.join(JSON_DIR, os.path.splitext(filename)[0])
|
2233 |
+
# extracted_sprites_json = os.path.join(extracted_dir, "extracted_sprites.json")
|
|
|
|
|
|
|
|
|
2234 |
|
2235 |
+
# if not os.path.exists(extracted_sprites_json):
|
2236 |
+
# return jsonify({"error": "No extracted_sprites.json found"}), 500
|
2237 |
|
2238 |
+
# with open(extracted_sprites_json, 'r') as f:
|
2239 |
+
# sprite_data = json.load(f)
|
2240 |
+
|
2241 |
+
project_output = similarity_matching(output_path, project_folder)
|
2242 |
+
logger.info("Received request to process PDF.")
|
2243 |
|
2244 |
with open(project_output, 'r') as f:
|
2245 |
project_skeleton = json.load(f)
|
2246 |
|
2247 |
+
|
2248 |
+
images = convert_from_path(saved_pdf_path, dpi=300)
|
2249 |
+
print(type)
|
2250 |
page = images[0]
|
2251 |
+
# img_base64 = base64.b64encode(images).decode("utf-8")
|
2252 |
buf = BytesIO()
|
2253 |
page.save(buf, format="PNG")
|
2254 |
img_bytes = buf.getvalue()
|
2255 |
img_b64 = base64.b64encode(img_bytes).decode("utf-8")
|
2256 |
+
#image_paths = await convert_pdf_to_images_async(saved_pdf_path)
|
2257 |
|
2258 |
+
#updating logic here [Dev Patel]
|
2259 |
# initial_state_dict = {
|
2260 |
# "project_json": project_skeleton,
|
2261 |
# "description": "The pseudo code for the script",
|
|
|
2266 |
# "temporary_node": {},
|
2267 |
# }
|
2268 |
|
2269 |
+
# final_state_dict = app_graph.invoke(initial_state_dict) # Pass dictionary
|
2270 |
|
2271 |
+
# final_project_json = final_state_dict['project_json'] # Access as dict
|
2272 |
+
final_project_json = project_skeleton
|
2273 |
|
2274 |
+
# Save the *final* filled project JSON, overwriting the skeleton
|
2275 |
with open(project_output, "w") as f:
|
2276 |
json.dump(final_project_json, f, indent=2)
|
2277 |
logger.info(f"Final project JSON saved to {project_output}")
|
2278 |
|
2279 |
+
# --- Call the new function to create the .sb3 file ---
|
2280 |
sb3_file_path = create_sb3_archive(project_folder, project_id)
|
2281 |
if sb3_file_path:
|
2282 |
logger.info(f"Successfully created SB3 file: {sb3_file_path}")
|
2283 |
+
# Instead of returning the local path, return a URL to the download endpoint
|
2284 |
+
download_url = f"https://prthm11-scratch-vlm-v1.hf.space/download_sb3/{project_id}"
|
2285 |
print(f"DOWNLOAD_URL: {download_url}")
|
2286 |
+
return jsonify({"message": "Procesed PDF and Game sb3 generated successfully", "project_id": project_id, "download_url": download_url})
|
2287 |
else:
|
2288 |
return jsonify(error="Failed to create SB3 archive"), 500
|
2289 |
|
2290 |
except Exception as e:
|
2291 |
logger.error(f"Error during processing the pdf workflow for project ID {project_id}: {e}", exc_info=True)
|
2292 |
+
return jsonify({"error": f"❌ Failed to process PDF: {str(e)}"}), 500
|
2293 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2294 |
if __name__ == '__main__':
|
2295 |
+
# os.makedirs("outputs", exist_ok=True) #== commented by P
|
2296 |
app.run(host='0.0.0.0', port=7860, debug=True)
|