Skip to content

Instantly share code, notes, and snippets.

@peaeater
Created June 22, 2022 18:44
Show Gist options
  • Save peaeater/5752995936ee0570ef00d70d56eb3847 to your computer and use it in GitHub Desktop.
Save peaeater/5752995936ee0570ef00d70d56eb3847 to your computer and use it in GitHub Desktop.
DZI Deep Zoom Images from TIFs, requires libvips (https://libvips.github.io/libvips/)
<#
1. Leaf
Given a text file of TIF/TIFF filenames, create DZI (Deep Zoom Image) tiles from TIFs
and create a mirror directory structure for DZI file outputs.
* Handles filenames with entry separators
* Ignores TIF older than its DZI mirror unless -force param is used
* Requires libvips (https://libvips.github.io/libvips/)
.\tif2dzi.ps1 -in c:\dev\abc\extract\extracted\tifs\abc-tifs-1.txt `
-pathsnip \\abc\archive\bigpictures `
-pathprefix c:\dev\abc\raw\largeimages `
-outdir c:\dev\abc\raw\media `
2. Container
Given a directory path, create DZI (Deep Zoom Image) tiles from TIFs recursively
and create a mirror directory structure for DZI file outputs.
* Performs in-place if outdir is not provided
* Ignores TIF older than its DZI mirror unless -force param is used
* Requires libvips (https://libvips.github.io/libvips/)
.\tif2dzi.ps1 -indir c:\dev\abc\raw\largeimages -outdir c:\dev\abc\raw\media
or, in-place:
.\tif2dzi.ps1 -indir c:\dev\abc\raw\largeimages
#>
param (
[Parameter(Mandatory=$true, ParameterSetName="Leaf")]
[string]$in,
[Parameter(Mandatory=$true, ParameterSetName="Leaf")]
[string]$pathsnip,
[Parameter(Mandatory=$true, ParameterSetName="Leaf")]
[string]$pathprefix,
[Parameter(Mandatory = $true, ParameterSetName = "Container")]
[string]$indir,
[Parameter(Mandatory = $true, ParameterSetName = "Leaf")]
[Parameter(Mandatory = $false, ParameterSetName = "Container")]
[string]$outdir = $indir,
[Parameter(Mandatory = $false, ParameterSetName = "Leaf")]
[Parameter(Mandatory = $false, ParameterSetName = "Container")]
[string]$suffix = ".jpg",
[Parameter(Mandatory = $false, ParameterSetName = "Leaf")]
[Parameter(Mandatory = $false, ParameterSetName = "Container")]
[int]$quality = "75",
[Parameter(Mandatory = $false, ParameterSetName = "Leaf")]
[Parameter(Mandatory = $false, ParameterSetName = "Container")]
[ValidateSet("fs","zip")]
[string]$container = "fs",
[Parameter(Mandatory = $false, ParameterSetName = "Leaf")]
[Parameter(Mandatory = $false, ParameterSetName = "Container")]
[switch]$force,
[Parameter(Mandatory=$false, ParameterSetName="Leaf")]
[Parameter(Mandatory=$false, ParameterSetName="Container")]
[string]$logsrc = "",
[Parameter(Mandatory = $false, ParameterSetName = "Leaf")]
[Parameter(Mandatory = $false, ParameterSetName = "Container")]
[string]$vips = "c:\utils\vips\bin\vips.exe"
)
<#
FUNCTIONS
#>
. .\helper.logging.ps1
function getValidPaths([string]$in, [string]$pathprefix, [string]$pathsnip) {
$paths = get-content $in | Where-Object { $_ -ne '' } | ForEach-Object { $_.split('|') }
$i = 0
$e = 0
$validPaths = @()
foreach ($path in $paths) {
$i++
try {
if ($pathsnip) {
$path = $path.Replace($pathsnip, "", [System.StringComparison]::OrdinalIgnoreCase)
}
if ($pathprefix) {
$path = join-path $pathprefix $path
}
$path = $path.trim()
$ok = test-path $path -PathType Leaf -ErrorAction Stop
if ($ok) {
write-host "$path Found"
$validPaths = $validPaths + $path
}
else {
write-host "$path Not Found"
}
# update progress display
write-progress -activity "Validating file paths..." -status "Processing $i of $($paths.Count)" -percentcomplete (($i / $paths.Count) * 100)
}
catch [Exception] {
$e++
$msg = "Error occurred while validating $path. $($_.Exception)"
logError $logsrc $msg
}
}
return $validPaths
}
<#
MAIN
#>
if ($indir) {
$files = get-childitem "$indir\*" -include *.tif,*.tiff -Recurse
$pathprefix = $indir
}
if ($in) {
$files = get-childitem $(getValidPaths $in $pathprefix $pathsnip) -include *.tif,*.tiff
}
$i = 0
$e = 0
$skip = 0
foreach ($file in $files) {
$i++
$update = $true
$status = "Processing $i of $($files.Count)."
write-progress -activity "Converting to DZI..." -status $status -PercentComplete (($i / $files.Count) * 100)
try {
# dzi file path => [base out dir] + [tif parent dir w/o qualifier] + .dzi
$dzidir = join-path $outdir $($file.DirectoryName.Replace($pathprefix, "", [System.StringComparison]::OrdinalIgnoreCase))
$dzi_basefilename = join-path $dzidir $file.BaseName
$dzipath = "{0}.dzi" -f $dzi_basefilename
$tiledir = join-path $dzidir $("{0}_files" -f $file.BaseName)
# if dzi already exists and timestamp is newer than tif, skip (unless -force is active)
if ((-not $force) -and (test-path $dzipath)) {
$dzifile = get-itemproperty -path $dzipath
if ($dzifile.LastWriteTime -gt $file.LastWriteTime) {
write-output "$dzipath Skipped"
$update = $false
}
}
# create dzi from tif
if ($force -or $update) {
# vips can't overwrite existing files, permission denied, so delete pre-existing files for it
if (test-path $dzipath) {
remove-item $dzipath
}
if (test-path $tiledir) {
remove-item $tiledir -recurse
}
if (!(test-path $dzidir)) {
mkdir $dzidir | out-null
}
# do not make tiledir ahead of time or vips will skip making tiles
# if (!(test-path $tiledir)) {
# mkdir $tiledir | out-null
# }
$arguments = "dzsave `"$($file.FullName)`" `"$dzi_basefilename`" --layout dz --suffix $suffix[Q=$quality] --depth onepixel --container $container"
start-process $vips $arguments -wait -NoNewWindow
}
else {
$skip++
}
}
catch [Exception] {
$e++
$msg = "Error occurred while processing $($file.FullName). $($_.Exception)"
logError $logsrc $msg
}
}
# final report
$msg = "TIF to DZI finished processing $i {0} to $outdir. $skip skipped, $e {1}." -f $(if ($i -eq 1) {"file"} else {"files"}),$(if ($e -eq 1) {"error"} else {"errors"})
logInfo $logsrc $msg
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment