OutConsolePicture.psm1
Add-Type -Assembly 'System.Drawing' function GetPixelText ($color_fg, $color_bg) { "$([char]27)[38;2;{0};{1};{2}m$([char]27)[48;2;{3};{4};{5}m" -f $color_fg.r, $color_fg.g, $color_fg.b, $color_bg.r, $color_bg.g, $color_bg.b + [char]9600 + "$([char]27)[0m" } function Out-ConsolePicture { [CmdletBinding()] param ( [Parameter(Mandatory = $true, ParameterSetName = "FromPath", Position = 0)] [ValidateNotNullOrEmpty()][string[]] $Path, [Parameter(Mandatory = $true, ParameterSetName = "FromWeb")] [System.Uri[]]$Url, [Parameter(Mandatory = $true, ParameterSetName = "FromPipeline", ValueFromPipeline = $true)] [System.Drawing.Bitmap[]]$InputObject, [Parameter()] [int]$Width, [Parameter()] [switch]$DoNotResize ) begin { if ($PSCmdlet.ParameterSetName -eq "FromPath") { foreach ($file in $Path) { try { $image = New-Object System.Drawing.Bitmap -ArgumentList "$(Resolve-Path $file)" $InputObject += $image } catch { Write-Error "An error occurred while loading image. Supported formats are BMP, GIF, EXIF, JPG, PNG and TIFF." } } } if ($PSCmdlet.ParameterSetName -eq "FromWeb") { foreach ($uri in $Url) { try { $data = (Invoke-WebRequest $uri).RawContentStream } catch [Microsoft.PowerShell.Commands.HttpResponseException] { if ($_.Exception.Response.statuscode.value__ -eq 302) { $actual_location = $_.Exception.Response.Headers.Location.AbsoluteUri $data = (Invoke-WebRequest $actual_location).RawContentStream } else { throw $_ } } try { $image = New-Object System.Drawing.Bitmap -ArgumentList $data $InputObject += $image } catch { Write-Error "An error occurred while loading image. Supported formats are BMP, GIF, EXIF, JPG, PNG and TIFF." } } } if ($Host.Name -eq "Windows PowerShell ISE Host") { # ISE neither supports ANSI, nor reports back a width for resizing. Write-Warning "ISE does not support ANSI colors. No images for you. Sorry! :(" Break } } process { $InputObject | ForEach-Object { if ($_ -is [System.Drawing.Bitmap]) { # Resize image to console width or width parameter if ($width -or (($_.Width -gt $host.UI.RawUI.WindowSize.Width) -and -not $DoNotResize)) { if ($width) { $new_width = $width } else { $new_width = $host.UI.RawUI.WindowSize.Width } $new_height = $_.Height / ($_.Width / $new_width) $resized_image = New-Object System.Drawing.Bitmap -ArgumentList $_, $new_width, $new_height $_.Dispose() $_ = $resized_image } $color_string = New-Object System.Text.StringBuilder for ($y = 0; $y -lt $_.Height; $y++) { if ($y % 2) { continue } else { [void]$color_string.append("`n") } # If https://github.com/PowerShell/PowerShell/issues/8482 ever gets fixed, the below should return # to calling the GetPixelText function, like God intended. for ($x = 0; $x -lt $_.Width; $x++) { if (($y + 2) -gt $_.Height) { # We are now on the last row. The bottom half of it in images with uneven pixel height # should just be coloured like the background of the console. $color_fg = $_.GetPixel($x, $y) $color_bg = [System.Drawing.Color]::FromName($Host.UI.RawUI.BackgroundColor) $pixel = "$([char]27)[38;2;{0};{1};{2}m$([char]27)[48;2;{3};{4};{5}m" -f $color_fg.r, $color_fg.g, $color_fg.b, $color_bg.r, $color_bg.g, $color_bg.b + [char]9600 + "$([char]27)[0m" [void]$color_string.Append($pixel) } else { #$pixel = GetPixelText $_.GetPixel($x, $y) $_.GetPixel($x, $y + 1) $color_fg = $_.GetPixel($x, $y) $color_bg = $_.GetPixel($x, $y + 1) $pixel = "$([char]27)[38;2;{0};{1};{2}m$([char]27)[48;2;{3};{4};{5}m" -f $color_fg.r, $color_fg.g, $color_fg.b, $color_bg.r, $color_bg.g, $color_bg.b + [char]9600 + "$([char]27)[0m" [void]$color_string.Append($pixel) } } } $color_string.ToString() $_.Dispose() } } } end { } <# .SYNOPSIS Renders an image to the console .DESCRIPTION Out-ConsolePicture will take an image file and convert it to a text string. Colors will be "encoded" using ANSI escape strings. The final result will be output in the shell. By default images will be reformatted to the size of the current shell, though this behaviour can be suppressed with the -DoNotResize switch. ISE users, take note: ISE does not report a window width, and scaling fails as a result. I don't think there is anything I can do about that, so either use the -DoNotResize switch, or don't use ISE. .PARAMETER Path One or more paths to the image(s) to be rendered to the console. .PARAMETER Url One or more Urls for the image(s) to be rendered to the console. .PARAMETER InputObject A Bitmap object that will be rendered to the console. .PARAMETER DoNotResize By default, images will be resized to have their width match the current console width. Setting this switch disables that behaviour. .PARAMETER Width Renders the image at this specific width. Use of the width parameter overrides DoNotResize. .EXAMPLE Out-ConsolePicture ".\someimage.jpg" Renders the image to console .EXAMPLE Out-ConsolePicture -Url "http://somewhere.com/image.jpg" Renders the image to console .EXAMPLE $image = New-Object System.Drawing.Bitmap -ArgumentList "C:\myimages\image.png" $image | Out-ConsolePicture Creates a new Bitmap object from a file on disk renders it to the console .INPUTS One or more System.Drawing.Bitmap objects .OUTPUTS Gloriously coloured console output #> } |