Last active
June 28, 2023 04:03
-
-
Save vt-idiot/f77a4265ea277d7fe2f5aad054ddae2d to your computer and use it in GitHub Desktop.
an insane man's script to convert NovelAI and stable-diffusion-webui images to JPG while preserving metadata and file creation/modification dates
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.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 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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:
or {curly braces} or [brackets]in the promptSo
なほね 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.OrPretty 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 liketowa 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
and00001-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.It's a miracle this thing even works at all. Even if I assign a string like
$random
toGetRandom
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.