Private/Show-PiskelFile.ps1
|
function Show-PiskelFile { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$PiskelPath, [int]$LayerIndex = 0, [switch]$AddShadow, [int]$ShadowOffsetX = 1, [int]$ShadowOffsetY = 1, [int[]]$ShadowColor = @(20, 20, 20), [switch]$TreatBlackAsForeground ) ################################################################################ ##### ##### ##### Description ###### ##### ##### ################################################################################ $CurrentFunction = Get-FunctionName Write-Log -Message "### Start Function $CurrentFunction ###" #$StartRunTime = (Get-Date).ToString($Script:DateFormatLog) #################### main code | out- host ##################### Add-Type -AssemblyName System.Drawing if ($PSVersionTable.PSVersion.Major -le 5 -and $env:OS -eq 'Windows_NT') { try { Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; public class VTConsole { [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr GetStdHandle(int nStdHandle); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode); public static void EnableVT() { IntPtr handle = GetStdHandle(-11); uint mode; GetConsoleMode(handle, out mode); SetConsoleMode(handle, mode | 0x4); } } "@ -ErrorAction SilentlyContinue [VTConsole]::EnableVT() } catch { } } if ($ShadowColor.Count -ne 3) { throw "ShadowColor must contain exactly 3 integers: R,G,B" } If (-not (Test-Path -LiteralPath $PiskelPath)) { return } $json = Get-Content -LiteralPath $PiskelPath -Raw | ConvertFrom-Json if (-not $json.piskel) { $JsonData = Get-Content -Path $Script:T0VRIFilePath -Raw | ConvertFrom-Json $json = $JsonData.PiskelLogo } else { $json = Get-Content -LiteralPath $PiskelPath -Raw | ConvertFrom-Json } $width = [int]$json.piskel.width $height = [int]$json.piskel.height if ($LayerIndex -ge $json.piskel.layers.Count) { throw "LayerIndex $LayerIndex out of range. Available layers: $($json.piskel.layers.Count)" } $layer = $json.piskel.layers[$LayerIndex] | ConvertFrom-Json if (-not $layer.chunks -or $layer.chunks.Count -eq 0) { throw "Layer does not contain any chunks." } $chunk = $layer.chunks[0] if (-not $chunk.base64PNG) { throw "Chunk does not contain base64PNG." } $base64Png = $chunk.base64PNG -replace '^data:image/png;base64,', '' $imageBytes = [Convert]::FromBase64String($base64Png) $memoryStream = [System.IO.MemoryStream]::new($imageBytes) $bitmap = [System.Drawing.Bitmap]::new($memoryStream) try { $sourceWidth = $bitmap.Width $sourceHeight = $bitmap.Height $scaleX = $sourceWidth / $width $scaleY = $sourceHeight / $height $ESC = [char]27 $LowerHalfBlock = [char]0x2584 function Get-TrueColorFg { param([int]$R, [int]$G, [int]$B) "$ESC[38;2;${R};${G};${B}m" } function Get-TrueColorBg { param([int]$R, [int]$G, [int]$B) "$ESC[48;2;${R};${G};${B}m" } function Get-LogicalPixelColor { param( [int]$X, [int]$Y ) $sampleX = [int][math]::Floor((($X + 0.5) * $scaleX)) $sampleY = [int][math]::Floor((($Y + 0.5) * $scaleY)) if ($sampleX -ge $sourceWidth) { $sampleX = $sourceWidth - 1 } if ($sampleY -ge $sourceHeight) { $sampleY = $sourceHeight - 1 } $bitmap.GetPixel($sampleX, $sampleY) } function Test-IsBackgroundPixel { param( [Parameter(Mandatory)] [System.Drawing.Color]$Color ) if ($Color.A -lt 32) { return $true } if ($TreatBlackAsForeground) { return $false } return ($Color.R -le 8 -and $Color.G -le 8 -and $Color.B -le 8) } function New-ShadowColor { [System.Drawing.Color]::FromArgb( 255, [int]$ShadowColor[0], [int]$ShadowColor[1], [int]$ShadowColor[2] ) } $pixels = New-Object 'System.Drawing.Color[,]' $width, $height for ($y = 0; $y -lt $height; $y++) { for ($x = 0; $x -lt $width; $x++) { $pixels[$x, $y] = Get-LogicalPixelColor -X $x -Y $y } } if ($AddShadow) { $shadowPixels = New-Object 'System.Drawing.Color[,]' $width, $height for ($y = 0; $y -lt $height; $y++) { for ($x = 0; $x -lt $width; $x++) { $shadowPixels[$x, $y] = $pixels[$x, $y] } } for ($y = 0; $y -lt $height; $y++) { for ($x = 0; $x -lt $width; $x++) { $srcColor = $pixels[$x, $y] if (-not (Test-IsBackgroundPixel -Color $srcColor)) { $sx = $x + $ShadowOffsetX $sy = $y + $ShadowOffsetY if ($sx -ge 0 -and $sx -lt $width -and $sy -ge 0 -and $sy -lt $height) { $targetColor = $shadowPixels[$sx, $sy] if (Test-IsBackgroundPixel -Color $targetColor) { $shadowPixels[$sx, $sy] = New-ShadowColor } } } } } for ($y = 0; $y -lt $height; $y++) { for ($x = 0; $x -lt $width; $x++) { if (-not (Test-IsBackgroundPixel -Color $pixels[$x, $y])) { $shadowPixels[$x, $y] = $pixels[$x, $y] } } } $pixels = $shadowPixels } $oddHeight = ($height % 2) -eq 1 $startY = if ($oddHeight) { -1 } else { 0 } $endY = if ($oddHeight) { $height - 1 } else { $height } for ($y = $startY; $y -lt $endY; $y += 2) { $line = "" for ($x = 0; $x -lt $width; $x++) { $topY = $y $bottomY = $y + 1 if ($topY -lt 0) { $topPixel = $null } else { $topPixel = $pixels[$x, $topY] } $bottomPixel = $pixels[$x, $bottomY] $botR = if ($bottomPixel.A -lt 32) { 0 } else { [int]$bottomPixel.R } $botG = if ($bottomPixel.A -lt 32) { 0 } else { [int]$bottomPixel.G } $botB = if ($bottomPixel.A -lt 32) { 0 } else { [int]$bottomPixel.B } if ($null -eq $topPixel) { $fg = Get-TrueColorFg -R $botR -G $botG -B $botB $line += "${fg}${LowerHalfBlock}" } else { $topR = if ($topPixel.A -lt 32) { 0 } else { [int]$topPixel.R } $topG = if ($topPixel.A -lt 32) { 0 } else { [int]$topPixel.G } $topB = if ($topPixel.A -lt 32) { 0 } else { [int]$topPixel.B } $bg = Get-TrueColorBg -R $topR -G $topG -B $topB $fg = Get-TrueColorFg -R $botR -G $botG -B $botB $line += "${bg}${fg}${LowerHalfBlock}" } } $line += "$ESC[0m" Write-Host $line } Write-Host "" } finally { $bitmap.Dispose() $memoryStream.Dispose() } #$runtime = Get-RunTime -StartRunTime $StartRunTime #Add-SAFunctionRunTime -Function $CurrentFunction -Runtime $runtime #Write-Log -Message " Run Time: $runtime [h] ###" Write-Log -Message "### End Function $CurrentFunction ###" } |