mirror of
https://github.com/Hopiu/NDPI-to-DZI.git
synced 2026-03-16 22:00:24 +00:00
94 lines
No EOL
2.6 KiB
Python
Executable file
94 lines
No EOL
2.6 KiB
Python
Executable file
from pathlib import Path
|
|
|
|
import click
|
|
import pyvips
|
|
|
|
DEPTH_CHOICES = click.Choice(["onetile", "onepixel", "one"], case_sensitive=False)
|
|
|
|
|
|
def convert_ndpi_to_dzi(
|
|
input_ndpi: str,
|
|
output_dzi: str,
|
|
*,
|
|
tile_size: int = 254,
|
|
overlap: int = 1,
|
|
quality: int = 90,
|
|
depth: str = "onetile",
|
|
) -> None:
|
|
"""Convert an NDPI file to DZI format using pyvips."""
|
|
# Strip .dzi extension if provided — dzsave appends it automatically
|
|
output = str(Path(output_dzi).with_suffix(""))
|
|
|
|
try:
|
|
image = pyvips.Image.new_from_file(input_ndpi)
|
|
except pyvips.Error as exc:
|
|
raise click.ClickException(f"Failed to open '{input_ndpi}': {exc}") from exc
|
|
|
|
image.set_progress(True)
|
|
|
|
try:
|
|
with click.progressbar(length=100, label="Converting") as bar:
|
|
last_percent = [0]
|
|
|
|
def eval_cb(_image, progress):
|
|
delta = progress.percent - last_percent[0]
|
|
if delta > 0:
|
|
bar.update(delta)
|
|
last_percent[0] = progress.percent
|
|
|
|
image.signal_connect("eval", eval_cb)
|
|
|
|
image.dzsave(
|
|
output,
|
|
suffix=f".jpeg[Q={quality}]",
|
|
tile_size=tile_size,
|
|
overlap=overlap,
|
|
depth=depth,
|
|
)
|
|
except pyvips.Error as exc:
|
|
raise click.ClickException(f"Failed to save DZI: {exc}") from exc
|
|
|
|
click.echo(f"Conversion complete: {output}.dzi")
|
|
|
|
|
|
@click.command()
|
|
@click.argument("input_ndpi", type=click.Path(exists=True))
|
|
@click.argument("output_dzi", type=click.Path())
|
|
@click.option("--tile-size", default=254, show_default=True, help="Tile size in pixels.")
|
|
@click.option("--overlap", default=1, show_default=True, help="Tile overlap in pixels.")
|
|
@click.option("-q", "--quality", default=90, show_default=True, help="JPEG quality (1-100).")
|
|
@click.option(
|
|
"--depth",
|
|
default="onetile",
|
|
show_default=True,
|
|
type=DEPTH_CHOICES,
|
|
help="Pyramid depth: onetile, onepixel, or one.",
|
|
)
|
|
def cli(
|
|
input_ndpi: str,
|
|
output_dzi: str,
|
|
tile_size: int,
|
|
overlap: int,
|
|
quality: int,
|
|
depth: str,
|
|
) -> None:
|
|
"""Convert NDPI whole-slide images to DZI format.
|
|
|
|
Uses pyvips (libvips) for fast, multi-threaded tile generation.
|
|
|
|
\b
|
|
INPUT_NDPI Path to the input NDPI file.
|
|
OUTPUT_DZI Path/name for the output DZI (e.g. "output" → output.dzi + output_files/).
|
|
"""
|
|
convert_ndpi_to_dzi(
|
|
input_ndpi,
|
|
output_dzi,
|
|
tile_size=tile_size,
|
|
overlap=overlap,
|
|
quality=quality,
|
|
depth=depth,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
cli() |