en-US/about_PSImageConverter.help.txt
|
TOPIC about_PSImageConverter SHORT DESCRIPTION Cross-platform image conversion (HEIC/HEIF and more), powered by Magick.NET. LONG DESCRIPTION PSImageConverter converts images, for example HEIC/HEIF photos taken with an iPhone, to JPEG, PNG, WebP, AVIF, JPEG XL, TIFF, BMP or GIF and reads their metadata. The Magick.NET library and its native ImageMagick build are bundled with the module, so no codecs need to be installed. It requires PowerShell 7.4 or later and runs on Windows, Linux and macOS (x64 and arm64; on Alpine/musl Linux x64 only). Cmdlets: Convert-Image Converts every format Magick.NET can read to the -Format Jpeg, Png, WebP, Avif, Jxl (JPEG XL), Tiff, Bmp or Gif. ConvertTo-Jpeg Convert-Image -Format Jpeg. ConvertTo-Png Convert-Image -Format Png (lossless, no -Quality). ConvertTo-WebP Convert-Image -Format WebP. ConvertTo-Avif Convert-Image -Format Avif. ConvertTo-JpegXL Convert-Image -Format Jxl. ConvertFrom-Heic Converts .heic/.heif/.hif files only; -Format defaults to Jpeg. Get-ImageInfo Returns the format, dimensions, orientation, camera and date taken of images; its objects can be piped into the conversion cmdlets. The conversion cmdlets take -Path (wildcards) or -LiteralPath (aliases PSPath and LP; files piped from Get-ChildItem and the objects of Get-ImageInfo bind here; folders are skipped), -DestinationPath, -Quality (1 to 100, default 90, for Jpeg, WebP, Avif and Jxl), -StripMetadata, -Force, -WhatIf and -Confirm, and return a FileInfo object for every written file, the same object Get-Item returns, so it can be piped into the next cmdlet. The output gets the base name of the source and the extension of the format (.jpg, .png, .webp, .avif, .jxl, .tif, .bmp, .gif). A file given more than once in a call (e.g. by the patterns *.heic and IMG_*) is converted or described once. A conversion never overwrites its source file or a file written earlier in the same call, also not when the folder is reached through another path (a junction, a symbolic link, a subst or mapped drive, a UNC path), and never leaves a truncated or temporary file behind, also not when it is stopped with Ctrl+C. Wildcards skip hidden files and folders (on Windows those with the Hidden attribute, on Linux and macOS names that start with a dot), as Get-ChildItem does without -Force; -LiteralPath and a folder name without wildcards reach them. METADATA The EXIF orientation is applied to the pixels, so the output is upright. Without -StripMetadata the output keeps the metadata its format can carry: Jpeg, Png EXIF, XMP, IPTC, ICC colour profile, comments WebP, Avif EXIF, XMP, ICC colour profile Jxl EXIF, XMP; ICC colour profile only at -Quality 100 Tiff XMP, IPTC, ICC colour profile, comments Gif IPTC, ICC colour profile (browsers ignore it in GIF files), comments Bmp ICC colour profile Tiff, Gif and Bmp output gets no EXIF data (date taken, camera, GPS location); a warning is written for every source with EXIF data unless -StripMetadata is used. -StripMetadata removes EXIF (including the GPS location), XMP, IPTC and comments but keeps the ICC colour profile. The colours are kept when the source carries an ICC profile, as iPhone photos do. A HEIC or AVIF source that signals its colours only through nclx/CICP (no ICC profile) with primaries other than sRGB/BT.709 (e.g. Display P3 or BT.2020, also HDR with PQ or HLG) is converted without colour conversion, so its colours look less saturated; Avif output keeps the CICP values. Lossy Jxl output (-Quality below 100) is always sRGB, because the bundled JPEG XL encoder stores an ICC colour profile only in lossless files. The pixels of a source with an ICC profile (e.g. Display P3 or Adobe RGB) are converted to sRGB first, so the photo looks the same; colours outside sRGB are clipped. Use -Quality 100 or Avif to keep a wide gamut. A grey profile in a colour image, which viewers ignore, is ignored here as well. Chrome shows a lossless Jxl file whose profile describes its tone curve as a table (e.g. Photoshop's 'Dot Gain 20%' grey profiles) without colour management; Firefox applies such a profile. Bytes after the size the header of an ICC profile declares are not part of the profile (Samsung Galaxy HEIC photos, for example, have two zero bytes there, and so do JPEGs converted from them). The profile is written without them in every output format, with unchanged colours (-Verbose says so). The Png encoder refuses a profile with such bytes. An ICC profile that the colour engine cannot apply, because it is damaged (e.g. cut short inside its tag data) or names an unknown colour space, is left out of every output (-Verbose says so): viewers ignore it in the source, Png and lossless Jxl output could not be written with it, and Chrome and Edge would not display an Avif that carries it. A profile that the colour engine can apply but the Png or lossless Jxl encoder cannot write (e.g. a version 4 profile whose length is not a multiple of 4, a header that declares a few more bytes than the profile has although all its tags are complete, or, for Jxl, a rendering intent above 3) is left out of that output only, so the file is still written (-Verbose says so). Grey images with a grey ICC profile (e.g. Photoshop's 'Dot Gain 20%' or 'Gray Gamma 1.8', scanned greyscale) keep their grey pixels and the profile in Jpeg, Png, Tiff and lossless Jxl output. WebP, Avif, Bmp and Gif store grey pixels as RGB, for which a grey profile is not valid, so the pixels are converted to sRGB first. This includes a grey JPEG XL with a grey profile, which ImageMagick reads as RGB. A profile made for other pixels is not valid: viewers ignore a grey profile in a colour image, and browsers apply an RGB profile to the pixels of a grey JPEG, while Windows (Photos, Explorer) rejects it. Such a profile is kept, except where the file could not be written or would look different with it: it is left out of lossless Jxl output and, as a grey profile on colour pixels, out of Avif and Bmp output, and out of Jpeg, Png and Tiff output when the colour pixels are all neutral grey (these formats store them as grey). Neutral grey pixels with an RGB profile (a black-and-white photo in Adobe RGB) are stored as RGB in Jpeg, Png and Tiff output, so the profile stays valid. When the orientation is applied, an EXIF thumbnail is removed (it would show rotated against the photo), and the XMP orientation and pixel dimensions are updated. CMYK images (e.g. print JPEGs) stay CMYK with their colour profile in Jpeg and Tiff output; for the other formats they are converted to sRGB through their CMYK profile. Jpeg has no transparency: transparent and half-transparent pixels are placed on a white background (paper white for a CMYK image). The other formats keep the alpha channel (Gif only fully transparent or opaque pixels). FRAMES AND DAMAGED FILES Only the first frame of an animated GIF or WebP, a multi-page TIFF or a HEIC file with several images is converted. A warning is written for every such source: 'Only the first of <N> frames is converted: <path>'. A source that ImageMagick can read but reports as damaged, e.g. a JPEG cut off by an interrupted copy (the missing part becomes grey) or an animated GIF cut off after its first frame (its frames cannot be counted then), is converted with the warning 'The image may be damaged (<reasons>): <path>'; Get-ImageInfo writes the same warning. A JPEG that lacks only its end marker gets this warning as well, although its pixels are complete: the decoder reports it like a file that is cut off. Other ImageMagick warnings about a source go to the verbose stream. Writing HEIC files is not supported yet, because the bundled ImageMagick build does not contain an HEVC encoder. AVIF is the closest alternative. ERRORS Errors about a file are non-terminating: the cmdlets continue with the next file, $? is $false afterwards, -ErrorVariable holds one record per failed file and -ErrorAction Stop stops at the first one. Every error has a stable id: PathNotFound the input matches no file; for a pattern the message names a drive or folder that does not exist, a folder part that is a file, a folder part with wildcards that no folder (or only a hidden one) matches, or, when the folder exists, adds that wildcards skip hidden files and that [ and ] are wildcard characters and how to match them; for a PSDrive that is not global it names the drive (see PSDRIVES) InvalidWildcardPattern -Path is not a valid pattern ('a[.jpg'); use -LiteralPath UnsupportedProvider the input is not a file system path (one error per input, also for a pattern) NotHeicFile ConvertFrom-Heic: no .heic/.heif/.hif file TargetIsSource the output would overwrite the source DuplicateTarget two sources of one call map to one output TargetExists the output exists and -Force is not set ConfirmationFailed -Confirm (or the caller's $ConfirmPreference) asks for a confirmation the host cannot show, e.g. in pwsh -NonInteractive; use -Confirm:$false ImageReadFailed the source cannot be read ImageWriteFailed the output cannot be written, or the destination folder cannot be created or written to The target object is the source file; for PathNotFound, InvalidWildcardPattern and UnsupportedProvider it is the input as given. A -DestinationPath that cannot name a folder is a parameter error: it stops the whole call with one terminating error before any file is read, also with -WhatIf, and try/catch catches it without -ErrorAction Stop. Use $_ in the catch block or $Error[0] for the error record: -ErrorVariable holds the exception for these errors (its ErrorRecord property has the record). The ids are InvalidDestinationPath (white space only, an unknown drive or provider, invalid characters, on Windows also a colon after the drive such as C:\x:y, a drive-qualified path that climbs above the root of its drive such as Temp:\..\x, a PSDrive that is not global, see PSDRIVES), UnsupportedProvider (not a file system path) and DestinationNotDirectory (the path or one of its parent folders is a file, a junction or symbolic link whose target does not exist, or a link that cannot be resolved, such as one that points to itself); the target object is the -DestinationPath value. A relative path that climbs above the root of its drive stays at the root, as in other cmdlets. A folder that does not exist yet is created when the first file is written; when that fails (no permission, a read-only file system) or the folder cannot be written to, each file gets ImageWriteFailed. ConvertFrom-Heic and the ConvertTo-* cmdlets pass all files of one call to a single Convert-Image, so the errors it finds have the FullyQualifiedErrorId '<Id>,Convert-Image'. The checks they make before carry their own name: the -DestinationPath errors of every one of them, and the input errors (PathNotFound, InvalidWildcardPattern, UnsupportedProvider, NotHeicFile) of ConvertFrom-Heic. With Import-Module -Prefix, the errors raised inside Convert-Image during such a call keep the module's unprefixed name ',Convert-Image', while a direct call of the prefixed cmdlet and the checks of a prefixed wrapper carry the prefixed name. Separate calls or processes that write the same output file at the same time without -Force are not coordinated: on Windows the later one fails with TargetExists or ImageWriteFailed; on Linux and macOS both can succeed and the later file replaces the earlier one. With -Force the later file replaces the earlier one on every platform. Give parallel conversions different destination folders. PREFERENCE VARIABLES Like compiled cmdlets, the cmdlets follow the preference variables of their caller ($WhatIfPreference, $ConfirmPreference, $ErrorActionPreference, $WarningPreference, $InformationPreference, $VerbosePreference, $DebugPreference), also when a script or function sets them in its own scope. Functions of a script module do not see such values by themselves (PowerShell issue #4568), so each cmdlet copies them when it starts. A function with SupportsShouldProcess that is called with -WhatIf therefore passes it on, and $ErrorActionPreference = 'Stop' in a script makes the first error terminating. A common parameter given to the cmdlet itself (-WhatIf, -Confirm, -ErrorAction, -WarningAction, -InformationAction, -Verbose, -Debug) wins. PSDRIVES PSDrives that are not global cannot be used. A script module resolves paths in its own session state, which sees only the global drives; this is a limitation of the PowerShell engine (Microsoft.PowerShell.Archive behaves the same). A drive created with New-PSDrive without -Scope Global inside a function (also by a script dot-sourced there), at the top of a script run by its path or with & (.\setup.ps1, & .\setup.ps1), or in another module therefore fails in -Path and -LiteralPath with PathNotFound and in -DestinationPath with InvalidDestinationPath, and so does a relative input path while the current location is on such a drive. The message names the drive and its root. Create the drive with New-PSDrive -Scope Global, or use the file system path. A drive created at the prompt, in the profile, at the top level of pwsh -File or by a script dot-sourced there (. .\setup.ps1) is global and works. When such a drive has the name of a global drive (e.g. a script's own Temp:), the module would read and write on the global drive instead, so it fails the same way and the message names both roots. For a drive of another provider the message says that only file system paths are supported. Files piped from Get-ChildItem or Get-Item on such a drive work, because their PSPath holds the file system path, and so does a relative -DestinationPath; strings and the output of Resolve-Path (which has no PSPath) do not. EXAMPLES PS C:\> ConvertFrom-Heic -Path .\IMG_1234.HEIC PS C:\> Get-ChildItem -Path C:\Pictures -Filter *.heic | ConvertFrom-Heic -Format Png PS C:\> Get-ChildItem -Path C:\Pictures -Filter *.jpg | ConvertTo-WebP -Quality 80 -DestinationPath C:\Pictures\web PS C:\> ConvertTo-Avif -Path .\IMG_1234.HEIC -StripMetadata PS C:\> Convert-Image -Path C:\Pictures\*.png -Format Tiff -WhatIf PS C:\> Get-ChildItem -Path C:\Pictures -Filter *.heic | Get-ImageInfo PS C:\> Get-ImageInfo -Path .\*.heic | Where-Object -Property Width -GT 4000 | ConvertTo-Jpeg NOTE: Thank you to all those who contributed to this module, by writing code, sharing opinions, and provided feedback. TROUBLESHOOTING NOTE: Look out on the GitHub repository for issues and new releases: https://github.com/fasteiner/PSImageConverter SEE ALSO - Get-Help Convert-Image -Full - https://github.com/dlemstra/Magick.NET KEYWORDS HEIC, HEIF, Image, Conversion, JPEG, PNG, WebP, AVIF, JpegXL, ImageMagick |