diff --git a/imagedephi/gui.py b/imagedephi/gui.py index 4d2870cb..28154cf6 100644 --- a/imagedephi/gui.py +++ b/imagedephi/gui.py @@ -11,7 +11,7 @@ import urllib.parse from PIL import Image, UnidentifiedImageError -from fastapi import BackgroundTasks, FastAPI, Form, HTTPException, Request +from fastapi import BackgroundTasks, FastAPI, Form, HTTPException, Request, WebSocket from fastapi.responses import HTMLResponse, PlainTextResponse, StreamingResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates @@ -20,6 +20,9 @@ import tifftools from imagedephi.redact import iter_image_files, redact_images +from imagedephi.utils.progress_log import get_next_progress_message + +# from imagedephi.redact.redact import output_file_counter from imagedephi.utils.tiff import get_associated_image_svs, get_ifd_for_thumbnail, get_is_svs if TYPE_CHECKING: @@ -67,6 +70,7 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: shutdown_event = asyncio.Event() app.mount("/assets", StaticFiles(directory="imagedephi/assets"), name="assets") +app.mount("/js", StaticFiles(directory="imagedephi/js"), name="js") class DirectoryData: @@ -268,3 +272,14 @@ def redact( "redacted": True, }, ) + + +@app.websocket("/ws") +async def websocket_endpoint(websocket: WebSocket): + await websocket.accept() + while True: + message = get_next_progress_message() + if message is not None: + await websocket.send_text(str({message[0]})) + else: + await asyncio.sleep(0.001) diff --git a/imagedephi/js/redaction.js b/imagedephi/js/redaction.js new file mode 100644 index 00000000..8717bd02 --- /dev/null +++ b/imagedephi/js/redaction.js @@ -0,0 +1,12 @@ +window.onload = (event) => { + + const redactBanner = document.getElementById("redacting"); + const redactButton = document.getElementById("dephi"); + const redactForm = document.getElementById('redact') + redactForm.addEventListener("submit", () => { + redactButton.setAttribute("disabled", "true") + redactBanner.classList.remove("hidden") + location.reload() + }) + +} diff --git a/imagedephi/main.py b/imagedephi/main.py index 9ce46946..41d381ea 100644 --- a/imagedephi/main.py +++ b/imagedephi/main.py @@ -114,9 +114,9 @@ def imagedephi( @click.pass_obj def run(obj: ImagedephiContext, input_path: Path, output_dir: Path, verbose, quiet, log_file): """Perform the redaction of images.""" - redact_images(input_path, output_dir, obj.override_rule_set) if verbose or quiet or log_file: set_logging_config(verbose, quiet, log_file) + redact_images(input_path, output_dir, obj.override_rule_set) @imagedephi.command diff --git a/imagedephi/redact/redact.py b/imagedephi/redact/redact.py index 64cbeb5b..d205a912 100644 --- a/imagedephi/redact/redact.py +++ b/imagedephi/redact/redact.py @@ -3,14 +3,17 @@ from collections.abc import Generator import datetime import importlib.resources +from io import StringIO from pathlib import Path +import click import tifftools import tifftools.constants import yaml from imagedephi.rules import Ruleset from imagedephi.utils.logger import logger +from imagedephi.utils.progress_log import push_progress from .build_redaction_plan import FILE_EXTENSION_MAP, build_redaction_plan from .svs import MalformedAperioFileError @@ -78,24 +81,32 @@ def redact_images( output_file_max = len(images_to_redact) redact_dir = create_redact_dir(output_dir) show_redaction_plan(input_path) - for image_file in images_to_redact: - logger.info(f"Redacting {image_file.name}...") - if image_file.suffix in FILE_EXTENSION_MAP: - redaction_plan = build_redaction_plan(image_file, base_rules, override_rules) - if not redaction_plan.is_comprehensive(): - logger.info(f"Redaction could not be performed for {image_file.name}.") - redaction_plan.report_missing_rules() - else: - redaction_plan.execute_plan() - output_path = _get_output_path( - image_file, - redact_dir, - output_file_name_base, - output_file_counter, - output_file_max, - ) - redaction_plan.save(output_path, overwrite) - output_file_counter += 1 + + file = StringIO() + with click.progressbar( + images_to_redact, label="Redacting Images", show_pos=True, file=file, show_percent=True + ) as bar: + for image_file in bar: + push_progress(image_file.name, output_file_counter, output_file_max) + + if image_file.suffix in FILE_EXTENSION_MAP: + redaction_plan = build_redaction_plan(image_file, base_rules, override_rules) + if not redaction_plan.is_comprehensive(): + logger.info(f"Redaction could not be performed for {image_file.name}.") + redaction_plan.report_missing_rules() + else: + redaction_plan.execute_plan() + output_path = _get_output_path( + image_file, + redact_dir, + output_file_name_base, + output_file_counter, + output_file_max, + ) + redaction_plan.save(output_path, overwrite) + if output_file_counter == output_file_max: + click.echo("Redactions completed") + output_file_counter += 1 def show_redaction_plan(input_path: Path, override_rules: Ruleset | None = None) -> None: diff --git a/imagedephi/templates/HomePage.html.j2 b/imagedephi/templates/HomePage.html.j2 index ad1e3ee5..1ab570c0 100644 --- a/imagedephi/templates/HomePage.html.j2 +++ b/imagedephi/templates/HomePage.html.j2 @@ -68,11 +68,12 @@ }, } +