-
-
Save vt-idiot/f77a4265ea277d7fe2f5aad054ddae2d to your computer and use it in GitHub Desktop.
<# | |
.Description | |
PROOMPT PRESSER 1.3 | |
.PARAMETER Delete | |
Permenantly erase all input PNGs. Default behavior does not delete input PNGs. | |
.PARAMETER Recurse | |
Process subdirectories. Default behavior only processes working directory. | |
.PARAMETER Quality | |
JPEG compression level. Defaults to 88 if unset. | |
.PARAMETER TXT | |
Keeps a .txt copy of metadata extracted during conversion. | |
.PARAMETER InstallPS7 | |
Installs PowerShell 7...technically it can update PowerShell 7 for you too. | |
.INPUTS | |
PNG images with NovelAI or webui metadata. You cannot pipe .NET objects to this script, it runs on the current directory, and does not recurse subdirectories unless specified. | |
.OUTPUTS | |
Compressed JPEG images with preserved metadata. | |
.EXAMPLE | |
PS> .\Insanity.ps1 | |
Runs with default settings: converts to JPG at 88 Quality, copies metadata, does not delete input PNGs, does not store a .txt copy of metadata. | |
.EXAMPLE | |
PS> .\Insanity.ps1 -Delete | |
Converts to JPG at 88 Quality, copies metadata, deletes input PNGs. | |
.EXAMPLE | |
PS> .\Insanity.ps1 -Delete -TXT -Quality 69 | |
Converts to JPG using 69 Quality, copies metadata, deletes input PNGs, stores an additional .txt copy of metadata. | |
.EXAMPLE | |
PS> .\Insanity.ps1 -TXT -Quality 75 -Recurse | |
Converts all PNGs in current folder AND subfolders to JPG at 75 Quality, copies metadata, stores a .txt copy of metadata. | |
.LINK | |
Source : https://gist.github.com/vt-idiot/f77a4265ea277d7fe2f5aad054ddae2d | |
.LINK | |
Install ImageMagick : https://imagemagick.org/script/download.php#windows | |
.LINK | |
Download exiftool : https://exiftool.org/ | |
.SYNOPSIS | |
1. Take a folder full of stable-diffusion-webui or NovelAI generated PNGs | |
2. Compress them to JPG | |
3. Preserve the prompt metadata | |
4. Maintain the Date Created/Date Modified from the original PNGs | |
5. (Optionally) Delete the PNGs | |
#> | |
<#PATH REQUIREMENTS | |
1. imagemagick's "convert", "identify", and "mogrify" | |
https://imagemagick.org/script/download.php#windows | |
If installing the .exe, make sure to check "Add application directory to system path" | |
If using the portable distribution, make sure it's in your PATH | |
2. exiftool | |
Download the https://exiftool.org/ "Windows Executable" | |
"exiftool" has to be "exiftool.exe" - default download is "exiftool(-k).exe" or something, rename it! | |
#> | |
<#LIMITATIONS | |
1. ENSD value likely NOT be correct for images that were img2img/inpainted/upscaled/"enhanced" using NovelAI | |
2. That's it. Everything else works great now.#> | |
param( | |
[Parameter()][switch]$Delete, | |
[Parameter()][switch]$TXT, | |
[Parameter()][switch]$InstallPS7, | |
[Parameter()][switch]$Recurse, | |
[Parameter()][ValidateRange(0,100)][int]$Quality=88 | |
) | |
$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding | |
CHCP 65001 | |
#halt execution if magick.exe and exiftool.exe not found in $PATH | |
Write-Host "Checking PATH for ImageMagick" | |
$magickpath = Get-Command -CommandType Application magick.exe -ErrorAction SilentlyContinue | Select-Object -expandproperty Path | |
If ($magickpath) {Write-Host "ImageMagick found at" $magickpath} | |
Else { | |
Write-Warning -Message 'ImageMagick not found in your PATH, exiting!';throw #Go install ImageMagick! | |
} | |
Write-Host "Checking PATH for exiftool" | |
$exiftoolpath = Get-Command -CommandType Application exiftool.exe -ErrorAction SilentlyContinue | Select-Object -expandproperty Path | |
If ($exiftoolpath) {Write-Host "exiftool found at" $exiftoolpath} | |
Else { | |
Write-Warning -Message 'exiftool not found in your PATH, exiting!';throw #Go install exiftool! | |
} | |
if ($Recurse) {$GCI = Get-ChildItem . -Recurse -Filter *.png} | |
else {$GCI = Get-ChildItem . -Filter *.png} | |
$PS7 = $PSVersionTable.PSVersion.Major -ge 7 | |
if ($PS7) { | |
Write-Host "PowerShell" $($PSVersionTable.PSVersion) "detected, parallel execution enabled." | |
$GCI | ForEach-Object -Parallel { | |
$Quality = $using:Quality | |
$Delete = $using:Delete | |
$TXT = $using:TXT | |
magick convert "$($_.FullName)" -quality $Quality -define preserve-timestamp=true "$($_.Directory)\$($_.BaseName).jpg" | |
#uses ImageMagick "identify" to read webui prompt | |
$comments = magick identify -format '%[Parameters]' -verbose "$($_.FullName)" 2>$null | |
if (-not $comments) { | |
Write-Host -ForegroundColor Red $_ "either contained Unicode characters in the proompt, or was a NovelAI file, buckle up." | |
$NAIerror = magick identify -format '%[Description]' -verbose "$($_.FullName)" 2>$null | |
$NAItitle = magick identify -format '%[Title]' -verbose "$($_.FullName)" 2>$null | |
if ($NAIerror) { | |
Write-Host -ForegroundColor Green $_ "is a NovelAI file with an ANSI prompt." | |
Write-Host -ForegroundColor Red "Did you use Unicode in your negatives, but not in the prompt? Too bad, this is already disgusting to look at." | |
mogrify -strip "$($_.Directory)\$($_.BaseName).jpg" #magick convert copies the novelai "comment" which normally contains some JSON formatted prompt parameters, but not the full prompt, we need to delete it | |
$NAImetadataA = magick identify -format '%[Title]\n%[Description]\n%[Software]\n%[Source]\n%[Comment]' -verbose "$($_.FullName)" 2>$null #read novelai prompt, add linebreaks between tEXt tags | |
$NAIresolutionA = magick identify -format '%wx%h' "$($_.FullName)" #read novelai resolution | |
$NAIcommentA = $NAImetadataA -split "`n" | |
$NAIoutputA += $NAIcommentA[1] + "`n" #put prompt on first line of new output | |
$jsonDataA = (ConvertFrom-Json $NAIcommentA[4]) #parse that novelai JSON "comment" | |
$NAIoutputA += "Negative prompt: " + $jsonDataA.uc + "`n" #extract negative prompt | |
$NAIoutputA += "Steps: " + $jsonDataA.steps + ", " #extract steps | |
$samplerA = $jsonDataA.sampler #sampler handler, rewrites all 5 novelai sampler options to match webui metadata, ChatGPT actually insisted on the final "else", lol | |
if ($samplerA -eq "k_euler_ancestral") { | |
$NAIoutputA += "Sampler: Euler a, " | |
} | |
elseif ($samplerA -eq "k_euler") { | |
$NAIoutputA += "Sampler: Euler, " | |
} | |
elseif ($samplerA -eq "ddim") { | |
$NAIoutputA += "Sampler: DDIM, " | |
} | |
elseif ($samplerA -eq "k_lms") { | |
$NAIoutputA += "Sampler: LMS, " | |
} | |
elseif ($samplerA -eq "plms") { | |
$NAIoutputA += "Sampler: PLMS, " | |
} | |
else { | |
$NAIoutputA += "Sampler: " + $samplerA + ", " | |
} | |
#add the rest of the prompt, including the resolution we read from the file | |
#note - if you upscaled using novelai's "enhance", this won't be very helpful! | |
#I think changing their noise and strength options while using "enhance" technically changes the ENSD value | |
#if you still have the base, pre-"enhance" gen, KEEP IT, and use THAT image/prompt/seed for e.g. latent upscaling | |
#if you did NOT use enhance to upscale, but made a BASE generation at a higher resolution, then YOU SHOULD BE FINE | |
$NAIoutputA += "CFG scale: " + $jsonDataA.scale + ", Seed: " + $jsonDataA.seed + ", Size: " + $NAIresolutionA + ", " | |
$stableDiffA = $NAIcommentA[3].Split(" ")[2] | |
if ($stableDiffA -eq "1D44365E") { | |
$NAIoutputA += "Model hash: 1d4a34af, Model: animesfw-final-pruned" | |
} | |
elseif ($stableDiffA -eq "81274D13") { | |
$NAIoutputA += "Model hash: 925997e9, Model: animefull-final-pruned" | |
} | |
else { $NAIoutputA += "Model hash: Not specified, Model: Not specified" } | |
#see note beginning on line 65, ENSD value is hard coded, not calculated | |
$NAIoutputA += ", Clip skip: 2, ENSD: 31337" | |
$NAIoutputA | Out-File -LiteralPath "$($_.Directory)\$($_.BaseName).txt" -Encoding utf8 | |
exiftool -P "-ExifIFD:UserComment<=$($_.Directory)\$($_.BaseName).txt" "$($_.Directory)\$($_.BaseName).jpg" -overwrite_original | |
$PNGA = Get-Item -LiteralPath "$($_)" | |
$JPGA = Get-Item -LiteralPath "$($_.Directory)\$($_.BaseName).jpg" | |
$JPGA.CreationTime = $PNGA.CreationTime | |
$JPGA.LastWriteTime = $PNGA.LastWriteTime | |
If ($Delete) {Remove-Item -LiteralPath "$($_)"} | |
If (-not $TXT) {Remove-Item -LiteralPath "$($_.Directory)\$($_.BaseName).txt"} | |
If ($TXT) {$NAImetadata | Out-File -LiteralPath "$($_.Directory)\$($_.BaseName).nai.txt" -Encoding utf8} | |
} | |
#this might work, it might not, exiftool is stuck in the 20th century and cannot properly see a UTF-8 filename unless it's passed to it via a text file. wonderful! "$($_.Directory)\$($_.BaseName).$(Get-Random).txt" | |
elseif ($NAItitle) { | |
Write-Host -ForegroundColor Yellow -NoNewline $_ ; Write-Host -ForegroundColor Red " is a NovelAI File with Unicode in the PROOMPT" | |
Write-Host -ForegroundColor Green "Now trying exiftool Bodge Job. It's not any better...don't look at the code." | |
$exiftoolfilenameB = $($_.BaseName) -replace '[^\x30-\x39\x41-\x5A\x61-\x7A]+', '' | |
$exiftoolfilenameB += "." + $(Get-Random) | |
Add-Content -LiteralPath "$($_.Directory)\$($exiftoolfilenameB).txt" -Value $_.FullName -Encoding utf8 | |
$NAIutf = exiftool -charset filename=utf8 -@ "$($_.Directory)\$($exiftoolfilenameB).txt" "-*Description*" | |
Remove-Item -LiteralPath "$($_.Directory)\$($exiftoolfilenameB).txt" | |
$NAIresolutionB = magick identify -format '%wx%h' "$($_.FullName)" | |
$NAImetadataB = magick identify -format '%[Title]\n\n%[Software]\n%[Source]\n%[Comment]' -verbose "$($_.FullName)" 2>$null | |
$NAIutf = $NAIutf -split "Description : " | |
$NAIoutputB = $NAIutf[1] + "`n" | |
$NAImetadataB = $NAImetadataB -split "`n" | |
$jsonDataB = (ConvertFrom-Json $NAImetadataB[4]) | |
$NAIoutputB += "Negative prompt: " + $jsonDataB.uc + "`n" | |
$NAIoutputB += "Steps: " + $jsonDataB.steps + ", " | |
$samplerB = $jsonDataB.sampler | |
if ($samplerB -eq "k_euler_ancestral") { | |
$NAIoutputB += "Sampler: Euler a, " | |
} | |
elseif ($samplerB -eq "k_euler") { | |
$NAIoutputB += "Sampler: Euler, " | |
} | |
elseif ($samplerB -eq "ddim") { | |
$NAIoutputB += "Sampler: DDIM, " | |
} | |
elseif ($samplerB -eq "k_lms") { | |
$NAIoutputB += "Sampler: LMS, " | |
} | |
elseif ($samplerB -eq "plms") { | |
$NAIoutputB += "Sampler: PLMS, " | |
} | |
else { | |
$NAIoutputB += "Sampler: " + $samplerB + ", " | |
} | |
$NAIoutputB += "CFG scale: " + $jsonDataB.scale + ", Seed: " + $jsonDataB.seed + ", Size: " + $NAIresolutionB + ", " | |
$stableDiffB = $NAImetadataB[3].Split(" ")[2] | |
if ($stableDiffB -eq "1D44365E") { | |
$NAIoutputB += "Model hash: 1d4a34af, Model: animesfw-final-pruned" | |
} | |
elseif ($stableDiffB -eq "81274D13") { | |
$NAIoutputB += "Model hash: 925997e9, Model: animefull-final-pruned" | |
} | |
else { $NAIoutputB += "Model hash: Not specified, Model: Not specified" } | |
$NAIoutputB += ", Clip skip: 2, ENSD: 31337" | |
$NAIoutputB | Out-File -LiteralPath "$($_.Directory)\$($exiftoolfilenameB).txt" -Encoding utf8 | |
Rename-Item "$($_.Directory)\$($_.BaseName).jpg" "$($_.Directory)\$($exiftoolfilenameB).jpg" | |
mogrify -strip "$($_.Directory)\$($exiftoolfilenameB).jpg" | |
exiftool -P "-ExifIFD:UserComment<=$($_.Directory)\$($exiftoolfilenameB).txt" "$($_.Directory)\$($exiftoolfilenameB).jpg" -overwrite_original | |
Rename-Item "$($_.Directory)\$($exiftoolfilenameB).jpg" "$($_.Directory)\$($_.BaseName).jpg" | |
$PNGB = Get-Item -LiteralPath "$($_)" | |
$JPGB = Get-Item -LiteralPath "$($_.Directory)\$($_.BaseName).jpg" | |
$JPGB.CreationTime = $PNGB.CreationTime | |
$JPGB.LastWriteTime = $PNGB.LastWriteTime | |
If ($Delete) {Remove-Item -LiteralPath "$($_)"} | |
If (-not $TXT) {Remove-Item -LiteralPath "$($_.Directory)\$($exiftoolfilenameB).txt"} | |
ElseIf ($TXT) {Rename-Item "$($_.Directory)\$($exiftoolfilenameB).txt" "$($_.Directory)\$($_.BaseName).txt"} | |
} | |
elseif (-not $NAItitle) { | |
Write-Host -ForegroundColor Red "Unicode Parsing Error For ASSUMED webui File " -NoNewline; Write-Host -ForegroundColor Yellow $_ | |
Write-Host -ForegroundColor Green "Now trying exiftool Bodge Job. It's not any better...don't look at the code." | |
$exiftoolfilenameC = $($_.BaseName) -replace '[^\x30-\x39\x41-\x5A\x61-\x7A]+', '' | |
$exiftoolfilenameC += "." + $(Get-Random) | |
Add-Content -LiteralPath "$($_.Directory)\$($exiftoolfilenameC).txt" -Value $_.FullName -Encoding utf8 | |
$webuiutf = exiftool -charset filename=utf8 -@ "$($_.Directory)\$($exiftoolfilenameC).txt" "-*parameters*" | |
$webuisplit = $webuiutf -split "Parameters : " | |
$webuineg = $webuisplit -split "Negative prompt: " | |
$webuisteps = $webuineg -split "Steps: " | |
$webuiout = $webuisteps[1] + "`n" + "Negative prompt: " + $webuisteps[2] + "`n" + "Steps: " + $webuisteps[3] | |
$webuiout | Out-File -LiteralPath "$($_.Directory)\$($exiftoolfilenameC).txt" -Encoding utf8 | |
Rename-Item "$($_.Directory)\$($_.BaseName).jpg" "$($_.Directory)\$($exiftoolfilenameC).jpg" | |
exiftool -P "-ExifIFD:UserComment<=$($_.Directory)\$($exiftoolfilenameC).txt" "$($_.Directory)\$($exiftoolfilenameC).jpg" -overwrite_original | |
Rename-Item "$($_.Directory)\$($exiftoolfilenameC).jpg" "$($_.Directory)\$($_.BaseName).jpg" | |
$PNGC = Get-Item -LiteralPath "$($_)" | |
$JPGC = Get-Item -LiteralPath "$($_.Directory)\$($_.BaseName).jpg" | |
$JPGC.CreationTime = $PNGC.CreationTime | |
$JPGC.LastWriteTime = $PNGC.LastWriteTime | |
If ($Delete) {Remove-Item -LiteralPath "$($_)"} | |
If (-not $TXT) {Remove-Item -LiteralPath "$($_.Directory)\$($exiftoolfilenameC).txt"} | |
ElseIf ($TXT) {Rename-Item "$($_.Directory)\$($exiftoolfilenameC).txt" "$($_.Directory)\$($_.BaseName).txt"} | |
} | |
else {Write-Host -ForegroundColor Red "HELLO LINK, I AM ERROR"} | |
} | |
#webui ansi prompt handling | |
elseif ($comments) { | |
Write-Host -ForegroundColor Green $_ "is a webui PNG with purely ANSI metadata." | |
$comments | Out-File -LiteralPath "$($_.FullName).txt" -Encoding utf8 #write prompt to txt for exiftool | |
exiftool -P "-ExifIFD:UserComment<=$($_.FullName).txt" "$($_.Directory)\$($_.BaseName).jpg" -overwrite_original #set exif comment | |
$PNGD = Get-Item -LiteralPath "$($_)" | |
$JPGD = Get-Item -LiteralPath "$($_.Directory)\$($_.BaseName).jpg" | |
$JPGD.CreationTime = $PNGD.CreationTime #set date created to match png | |
$JPGD.LastWriteTime = $PNGD.LastWriteTime #set date modified to match png | |
If ($Delete) {Remove-Item -LiteralPath "$($_)"} | |
If (-not $TXT) {Remove-Item -LiteralPath "$($_.FullName).txt"} | |
} | |
else { | |
#This exception will actually never be caught. I couldn't think of any other way to catch webui Unicode parameters. If you see actually see this error below, congratulations. You win! | |
Write-Host -ForegroundColor Red "Unspecified Error for File " -NoNewline; Write-Host -ForegroundColor Yellow $_ | |
Write-Host -ForegroundColor DarkRed "Maybe it doesn't have metadata? Wait, this error is supposed to be impossible to trigger..." | |
Write-Host -ForegroundColor Green "Screw exiftool and ImageMagick anyways. And PowerShell. And everything. Why did I think this was a good idea?" | |
Rename-Item -LiteralPath $($_.Directory)\$($_.BaseName).jpg $($_.Directory)\Metadata-Error-$($_.BaseName).jpg | |
} | |
} | |
} | |
else { | |
Write-Host "PowerShell" $($PSVersionTable.PSVersion) "does not support parallel ForEach-Object execution. Will run single threaded and a bit more slowly. Run with `"-InstallPS7`" to download and install PowerShell 7 from Microsoft automatically." | |
if($InstallPS7) { | |
Write-Host "Now installing PowerShell 7." | |
Invoke-Expression "& { $(Invoke-RestMethod https://aka.ms/install-powershell.ps1) } -UseMSI" | |
throw "Go run it using pwsh.exe" | |
} | |
Write-Warning "Keep going, or quit to install PowerShell 7 and run it there?" -WarningAction Inquire | |
$GCI | ForEach-Object { | |
magick convert "$($_.FullName)" -quality $Quality -define preserve-timestamp=true "$($_.Directory)\$($_.BaseName).jpg" | |
#uses ImageMagick "identify" to read webui prompt | |
$comments = magick identify -format '%[Parameters]' -verbose "$($_.FullName)" 2>$null | |
if (-not $comments) { | |
Write-Host -ForegroundColor Red $_ "either contained Unicode characters in the proompt, or was a NovelAI file, buckle up." | |
$NAIerror = magick identify -format '%[Description]' -verbose "$($_.FullName)" 2>$null | |
$NAItitle = magick identify -format '%[Title]' -verbose "$($_.FullName)" 2>$null | |
if ($NAIerror) { | |
Write-Host -ForegroundColor Green $_ "is a NovelAI file with an ANSI prompt." | |
Write-Host -ForegroundColor Red "Did you use Unicode in your negatives, but not in the prompt? Too bad, this is already disgusting to look at." | |
mogrify -strip "$($_.Directory)\$($_.BaseName).jpg" #magick convert copies the novelai "comment" which normally contains some JSON formatted prompt parameters, but not the full prompt, we need to delete it | |
$NAImetadataA = magick identify -format '%[Title]\n%[Description]\n%[Software]\n%[Source]\n%[Comment]' -verbose "$($_.FullName)" 2>$null #read novelai prompt, add linebreaks between tEXt tags | |
$NAIresolutionA = magick identify -format '%wx%h' "$($_.FullName)" #read novelai resolution | |
$NAIcommentA = $NAImetadataA -split "`n" | |
$NAIoutputA += $NAIcommentA[1] + "`n" #put prompt on first line of new output | |
$jsonDataA = (ConvertFrom-Json $NAIcommentA[4]) #parse that novelai JSON "comment" | |
$NAIoutputA += "Negative prompt: " + $jsonDataA.uc + "`n" #extract negative prompt | |
$NAIoutputA += "Steps: " + $jsonDataA.steps + ", " #extract steps | |
$samplerA = $jsonDataA.sampler #sampler handler, rewrites all 5 novelai sampler options to match webui metadata, ChatGPT actually insisted on the final "else", lol | |
if ($samplerA -eq "k_euler_ancestral") { | |
$NAIoutputA += "Sampler: Euler a, " | |
} | |
elseif ($samplerA -eq "k_euler") { | |
$NAIoutputA += "Sampler: Euler, " | |
} | |
elseif ($samplerA -eq "ddim") { | |
$NAIoutputA += "Sampler: DDIM, " | |
} | |
elseif ($samplerA -eq "k_lms") { | |
$NAIoutputA += "Sampler: LMS, " | |
} | |
elseif ($samplerA -eq "plms") { | |
$NAIoutputA += "Sampler: PLMS, " | |
} | |
else { | |
$NAIoutputA += "Sampler: " + $samplerA + ", " | |
} | |
#add the rest of the prompt, including the resolution we read from the file | |
#note - if you upscaled using novelai's "enhance", this won't be very helpful! | |
#I think changing their noise and strength options while using "enhance" technically changes the ENSD value | |
#if you still have the base, pre-"enhance" gen, KEEP IT, and use THAT image/prompt/seed for e.g. latent upscaling | |
#if you did NOT use enhance to upscale, but made a BASE generation at a higher resolution, then YOU SHOULD BE FINE | |
$NAIoutputA += "CFG scale: " + $jsonDataA.scale + ", Seed: " + $jsonDataA.seed + ", Size: " + $NAIresolutionA + ", " | |
$stableDiffA = $NAIcommentA[3].Split(" ")[2] | |
if ($stableDiffA -eq "1D44365E") { | |
$NAIoutputA += "Model hash: 1d4a34af, Model: animesfw-final-pruned" | |
} | |
elseif ($stableDiffA -eq "81274D13") { | |
$NAIoutputA += "Model hash: 925997e9, Model: animefull-final-pruned" | |
} | |
else { $NAIoutputA += "Model hash: Not specified, Model: Not specified" } | |
#see note beginning on line 65, ENSD value is hard coded, not calculated | |
$NAIoutputA += ", Clip skip: 2, ENSD: 31337" | |
$NAIoutputA | Out-File -LiteralPath "$($_.Directory)\$($_.BaseName).txt" -Encoding utf8 | |
exiftool -P "-ExifIFD:UserComment<=$($_.Directory)\$($_.BaseName).txt" "$($_.Directory)\$($_.BaseName).jpg" -overwrite_original | |
$PNGA = Get-Item -LiteralPath "$($_.FullName)" | |
$JPGA = Get-Item -LiteralPath "$($_.Directory)\$($_.BaseName).jpg" | |
$JPGA.CreationTime = $PNGA.CreationTime | |
$JPGA.LastWriteTime = $PNGA.LastWriteTime | |
If ($Delete) {Remove-Item -LiteralPath "$($_.FullName)"} | |
If (-not $TXT) {Remove-Item -LiteralPath "$($_.Directory)\$($_.BaseName).txt"} | |
If ($TXT) {$NAImetadata | Out-File -LiteralPath "$($_.Directory)\$($_.BaseName).nai.txt" -Encoding utf8} | |
} | |
elseif ($NAItitle) { | |
Write-Host -ForegroundColor Yellow -NoNewline $_ ; Write-Host -ForegroundColor Red " is a NovelAI File with Unicode in the PROOMPT" | |
Write-Host -ForegroundColor Green "Now trying exiftool Bodge Job. It's not any better...don't look at the code." | |
$exiftoolfilenameB = $($_.BaseName) -replace '[^\x30-\x39\x41-\x5A\x61-\x7A]+', '' | |
$exiftoolfilenameB += "." + $(Get-Random) | |
Add-Content -LiteralPath "$($_.Directory)\$($exiftoolfilenameB).txt" -Value $_.FullName -Encoding utf8 | |
$NAIutf = exiftool -charset filename=utf8 -@ "$($_.Directory)\$($exiftoolfilenameB).txt" "-*Description*" | |
Remove-Item -LiteralPath "$($_.Directory)\$($exiftoolfilenameB).txt" | |
$NAIresolutionB = magick identify -format '%wx%h' "$($_.FullName)" | |
$NAImetadataB = magick identify -format '%[Title]\n\n%[Software]\n%[Source]\n%[Comment]' -verbose "$($_.FullName)" 2>$null | |
$NAIutf = $NAIutf -split "Description : " | |
$NAIoutputB = $NAIutf[1] + "`n" | |
$NAImetadataB = $NAImetadataB -split "`n" | |
$jsonDataB = (ConvertFrom-Json $NAImetadataB[4]) | |
$NAIoutputB += "Negative prompt: " + $jsonDataB.uc + "`n" | |
$NAIoutputB += "Steps: " + $jsonDataB.steps + ", " | |
$samplerB = $jsonDataB.sampler | |
if ($samplerB -eq "k_euler_ancestral") { | |
$NAIoutputB += "Sampler: Euler a, " | |
} | |
elseif ($samplerB -eq "k_euler") { | |
$NAIoutputB += "Sampler: Euler, " | |
} | |
elseif ($samplerB -eq "ddim") { | |
$NAIoutputB += "Sampler: DDIM, " | |
} | |
elseif ($samplerB -eq "k_lms") { | |
$NAIoutputB += "Sampler: LMS, " | |
} | |
elseif ($samplerB -eq "plms") { | |
$NAIoutputB += "Sampler: PLMS, " | |
} | |
else { | |
$NAIoutputB += "Sampler: " + $samplerB + ", " | |
} | |
$NAIoutputB += "CFG scale: " + $jsonDataB.scale + ", Seed: " + $jsonDataB.seed + ", Size: " + $NAIresolutionB + ", " | |
$stableDiffB = $NAImetadataB[3].Split(" ")[2] | |
if ($stableDiffB -eq "1D44365E") { | |
$NAIoutputB += "Model hash: 1d4a34af, Model: animesfw-final-pruned" | |
} | |
elseif ($stableDiffB -eq "81274D13") { | |
$NAIoutputB += "Model hash: 925997e9, Model: animefull-final-pruned" | |
} | |
else { $NAIoutputB += "Model hash: Not specified, Model: Not specified" } | |
$NAIoutputB += ", Clip skip: 2, ENSD: 31337" | |
$NAIoutputB | Out-File -LiteralPath "$($_.Directory)\$($exiftoolfilenameB).txt" -Encoding utf8 | |
Rename-Item "$($_.Directory)\$($_.BaseName).jpg" "$($_.Directory)\$($exiftoolfilenameB).jpg" | |
mogrify -strip "$($_.Directory)\$($exiftoolfilenameB).jpg" | |
exiftool -P "-ExifIFD:UserComment<=$($_.Directory)\$($exiftoolfilenameB).txt" "$($_.Directory)\$($exiftoolfilenameB).jpg" -overwrite_original | |
Rename-Item "$($_.Directory)\$($exiftoolfilenameB).jpg" "$($_.Directory)\$($_.BaseName).jpg" | |
$PNGB = Get-Item -LiteralPath "$($_.FullName)" | |
$JPGB = Get-Item -LiteralPath "$($_.Directory)\$($_.BaseName).jpg" | |
$JPGB.CreationTime = $PNGB.CreationTime | |
$JPGB.LastWriteTime = $PNGB.LastWriteTime | |
If ($Delete) {Remove-Item -LiteralPath "$($_.FullName)"} | |
If (-not $TXT) {Remove-Item -LiteralPath "$($_.Directory)\$($exiftoolfilenameB).txt"} | |
ElseIf ($TXT) {Rename-Item "$($_.Directory)\$($exiftoolfilenameB).txt" "$($_.Directory)\$($_.BaseName).txt"} | |
} | |
elseif (-not $NAItitle) { | |
Write-Host -ForegroundColor Red "Unicode Parsing Error For ASSUMED webui File " -NoNewline; Write-Host -ForegroundColor Yellow $_ | |
Write-Host -ForegroundColor Green "Now trying exiftool Bodge Job. It's not any better...don't look at the code." | |
$exiftoolfilenameC = $($_.BaseName) -replace '[^\x30-\x39\x41-\x5A\x61-\x7A]+', '' | |
$exiftoolfilenameC += "." + $(Get-Random) | |
Add-Content -LiteralPath "$($_.Directory)\$($exiftoolfilenameC).txt" -Value $_.FullName -Encoding utf8 | |
$webuiutf = exiftool -charset filename=utf8 -@ "$($_.Directory)\$($exiftoolfilenameC).txt" "-*parameters*" | |
$webuisplit = $webuiutf -split "Parameters : " | |
$webuineg = $webuisplit -split "Negative prompt: " | |
$webuisteps = $webuineg -split "Steps: " | |
$webuiout = $webuisteps[1] + "`n" + "Negative prompt: " + $webuisteps[2] + "`n" + "Steps: " + $webuisteps[3] | |
$webuiout | Out-File -LiteralPath "$($_.Directory)\$($exiftoolfilenameC).txt" -Encoding utf8 | |
Rename-Item "$($_.Directory)\$($_.BaseName).jpg" "$($_.Directory)\$($exiftoolfilenameC).jpg" | |
exiftool -P "-ExifIFD:UserComment<=$($_.Directory)\$($exiftoolfilenameC).txt" "$($_.Directory)\$($exiftoolfilenameC).jpg" -overwrite_original | |
Rename-Item "$($_.Directory)\$($exiftoolfilenameC).jpg" "$($_.Directory)\$($_.BaseName).jpg" | |
$PNGC = Get-Item -LiteralPath "$($_.FullName)" | |
$JPGC = Get-Item -LiteralPath "$($_.Directory)\$($_.BaseName).jpg" | |
$JPGC.CreationTime = $PNGC.CreationTime | |
$JPGC.LastWriteTime = $PNGC.LastWriteTime | |
If ($Delete) {Remove-Item -LiteralPath "$($_.FullName)"} | |
If (-not $TXT) {Remove-Item -LiteralPath "$($_.Directory)\$($exiftoolfilenameC).txt"} | |
ElseIf ($TXT) {Rename-Item "$($_.Directory)\$($exiftoolfilenameC).txt" "$($_.Directory)\$($_.BaseName).txt"} | |
} | |
else {Write-Host -ForegroundColor Red "HELLO LINK, I AM ERROR"} | |
} | |
#webui ansi prompt handling | |
elseif ($comments) { | |
Write-Host -ForegroundColor Green $_ "is a webui PNG with purely ANSI metadata." | |
$comments | Out-File -LiteralPath "$($_.FullName).txt" -Encoding utf8 #write prompt to txt for exiftool | |
exiftool -P "-ExifIFD:UserComment<=$($_.FullName).txt" "$($_.Directory)\$($_.BaseName).jpg" -overwrite_original #set exif comment | |
$PNGD = Get-Item -LiteralPath "$($_.FullName)" | |
$JPGD = Get-Item -LiteralPath "$($_.Directory)\$($_.BaseName).jpg" | |
$JPGD.CreationTime = $PNGD.CreationTime #set date created to match png | |
$JPGD.LastWriteTime = $PNGD.LastWriteTime #set date modified to match png | |
If ($Delete) {Remove-Item -LiteralPath "$($_.FullName)"} | |
If (-not $TXT) {Remove-Item -LiteralPath "$($_.FullName).txt"} | |
} | |
else { | |
#This exception will actually never be caught. I couldn't think of any other way to catch webui Unicode parameters. If you see actually see this error below, congratulations. You win! | |
Write-Host -ForegroundColor Red "Unspecified Error for File " -NoNewline; Write-Host -ForegroundColor Yellow $_ | |
Write-Host -ForegroundColor DarkRed "Maybe it doesn't have metadata? Wait, this error is supposed to be impossible to trigger..." | |
Write-Host -ForegroundColor Green "Screw exiftool and ImageMagick anyways. And PowerShell. And everything. Why did I think this was a good idea?" | |
Rename-Item -LiteralPath $($_.Directory)\$($_.BaseName).jpg $($_.Directory)\Metadata-Error-$($_.BaseName).jpg | |
} | |
} | |
} |
No filename collisions
Asks you to install PowerShell 7, will run fine otherwise
Halts immediately if exiftool and magick are not in $PATH
DISREGARD EVERYTHING BELOW
There are potential file name collision issues, but it's such an infinitesimally rare chance, and can only occur with -Parallel
processing enabled. If you're not using PowerShell 7, you already have to remove -Parallel
in order for the script to function.
Your images would have to:
- be from Novel AI
- use the same exact seed
- have non-ANSI characters
or {curly braces} or [brackets]in the prompt - end up with identical filenames once all the non-ANSI characters were stripped from the filename
So なほね s-12345.png
and おやすみ s-12345.png
would potentially result in one file overwriting the other (during the tag writing process) if they were processed simultaneously. Or Pretty sure I fixed that with some {tokoyami towa} s-12345.png
and {{tokoyami towa}} s-12345.png
.-LiteralPath
. Don't take my word for it.
なほね s-12345.png
and なほね s-12345 (1).png
would not overwrite each other.
The chance is much lower for combinations like towa s-12345.png
and {towa} s-12345.png
(in a folder with more than 5 images between the two of them...) because the files are processed in order based on the original filenames and not the temporary "safe" filenames that are required...because exiftool can't parse Unicode from the command line in 2023. {...
would be at the top of the list. t...
would be towards the bottom. Capisce?
The chances of filename collisions are even smaller than infinitesimally small with only webui images, because of the default numbered filename prefix; there is no chance that 00000-12345-なほね.png
and 00001-12345-おやすみ.png
could ever overwrite each other!
There is also NO chance of collision if you're NOT using -Parallel
- ZERO. So if you're worried about that, just delete -Parallel
and deal with it processing images single threaded, one at a time, vs. 5 at a time.
Couldn't you fix it with a randomized temporary file name
It's a miracle this thing even works at all. Even if I assign a string like $random
to GetRandom
and prepend the temporary filename with $random
, the very sloppy -Parallel
bodge means that you'll instead just end up with it "forgetting" what the file it was working on was supposed to be called once it hits the next file that requires a random number.
ImageMagick is actually fixing identify
and their other tools to properly handle Unicode PNG iTXT tags. https://github.com/ImageMagick/ImageMagick/discussions/6000#discussioncomment-4804761
If I can figure out how to write an EXIF comment using a magick...
command then I can drop exiftool entirely (it's still used for writing the new metadata, Unicode or otherwise) and then there will be 0 chance of filename collisions regardless of -Parallel
or what characters are in the input filenames. The last time I tried, I think I couldn't get it to place line breaks in them, which webui requires.
I have only tested this with:
You need imagemagick in your
PATH
for this to work.https://imagemagick.org/script/download.php#windows
You also need exiftool in your
PATH
.https://exiftool.org/
You must rename it to
exiftool.exe
and make sure it's in yourPATH
. If you don't know what that means, putexiftool.exe
in theC:\Program Files\ImageMagick-7.1.0-Q16-HDRI
folder after you install it, it'll work.If you are not using PowerShell 7.x, you must remove
-Parallel
from line 25.There is no real error handling here.
I think I might've been better served learning some C or C++ and just using imagemagick that way, maybe I could've figured out how to read Unicode iTXt.