Home > Software engineering >  Use PowerShell to save a System.Windows.Interop.InteropBitmap to disk
Use PowerShell to save a System.Windows.Interop.InteropBitmap to disk

Time:06-11

Summary

I would like to use PowerShell to retrieve an image from the Windows clipboard, and save it to a file. When I copy an image to the clipboard, from a web browser for example, I am able to retrieve a System.Windows.Interop.InteropBitmap object. Once I have this object, I need to save the object to disk.

Question: How can I accomplish this?

Add-Type -AssemblyName PresentationCore
$DataObject = [System.Windows.Clipboard]::GetDataObject()
$DataObject | Get-Member

CodePudding user response:

All credits goes to this answer, this is merely a PowerShell adaptation of that code.

The code consists in 2 functions, one that outputs the InteropBitmap instance of the image in our clipboard and the other function that receives this object from the pipeline and outputs it to a file. The Set-ClipboardImage function can output using 3 different Encoders, you can add more if needed. See System.Windows.Media.Imaging Namespace for details.

These functions are tested and compatible with Windows PowerShell 5.1 and PowerShell Core. I do not know if this can or will work in prior versions.

using namespace System.Windows
using namespace System.Windows.Media.Imaging
using namespace System.IO
using namespace System.Windows.Interop

Add-Type -AssemblyName PresentationCore

function Get-ClipboardImage {
    $image = [Clipboard]::GetDataObject().GetImage()
    do {
        Start-Sleep -Milliseconds 200
        $downloading = $image.IsDownloading
    } while($downloading)
    $image
}

function Set-ClipboardImage {
    [cmdletbinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateScript({
            if(Test-Path (Split-Path $_)) {
                return $true
            }

            throw [ArgumentException]::new(
                'Destination folder does not exist.', 'Destination'
            )
        })]
        [string] $Destination,

        [Parameter(Mandatory, ValueFromPipeline, DontShow)]
        [InteropBitmap] $InputObject,

        [Parameter()]
        [ValidateSet('Png', 'Bmp', 'Jpeg')]
        [string] $Encoding = 'Png'
    )

    end {
        try {
            $Destination = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Destination)
            $encoder = switch($Encoding) {
                Png  { [PngBitmapEncoder]::new(); break }
                Bmp  { [BmpBitmapEncoder]::new(); break }
                Jpeg { [JpegBitmapEncoder]::new() }
            }
            $fs = [File]::Create($Destination)
            $encoder.Frames.Add([BitmapFrame]::Create($InputObject))
            $encoder.Save($fs)
        }
        catch {
            $PSCmdlet.WriteError($_)
        }
        finally {
            $fs.ForEach('Dispose')
        }
    }
}

Get-ClipboardImage | Set-ClipboardImage -Destination .\test.jpg -Encoding Jpeg
  • Related