Creating Image Markup Tools
In the previous article in this series, I demonstrated how to use PowerShell and the .NET Framework to add a layer of text to an image. I eventually want to have a tool that I can use to customize the cover images in my MuseScore MP3 files. However, the real takeaway is the process I used to create the tool.
When we left off, I had demonstrated enough code to add a layer of text to an image.
Add-Type -AssemblyName System.Drawing
$Text = "Behind the PowerShell Pipeline"
$image = "C:\work\blue-robot-ps.jpg"
$imageObject = [System.Drawing.Image]::FromFile($image)
$rect = [System.Drawing.RectangleF]::new(0, 0, $imageObject.Width, $imageObject.Height)
$graphics = [System.Drawing.Graphics]::FromImage($imageObject)
$size = "36"
$font = "Cascadia Code"
$fontObject = New-Object System.Drawing.Font($font,$size)
$brush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::Black)
$graphics.DrawString($text, $fontObject, $brush, $rect, $format)
$output = "c:\temp\preview.jpg"
$imageObject.Save($output)
I am using Get-SpectreImage
from the pwshSpectreConsole
module to view the image in the PowerShell console.

> *I'll admit this isn't necessarily the best image to use. *
Formatting the Text
One step I'm missing is formatting the text. I would like to position the text in the image. I might also want to format the text to be bold or italic. Using the Get-TypeConstructor
function from the PSScriptTools module, I can see there is a constructor for the Font
class that takes a FontStyle
object.
PS C:\> Get-TypeConstructor system.drawing.font
[System.Drawing.Font]::new([System.Drawing.Font]$Prototype),[System.Drawing.FontStyle]$newStyle))
[System.Drawing.Font]::new([System.Drawing.FontFamily]$Family),
[System.Single]$emSize),
[System.Drawing.FontStyle]$Style),
[System.Drawing.GraphicsUnit]$Unit))
...
There is no default constructor for that class.
PS C:\> Get-TypeConstructor system.drawing.fontstyle
WARNING: No constructors found for FontStyle
I'll use Get-TypeMember
to explore this class.
PS C:\> Get-TypeMember system.drawing.fontstyle
Type: System.Drawing.FontStyle
Name MemberType ResultType IsStatic IsEnum
---- ---------- ---------- -------- ------
Bold Field System.Drawing.FontStyle True
Italic Field System.Drawing.FontStyle True
Regular Field System.Drawing.FontStyle True
Strikeout Field System.Drawing.FontStyle True
Underline Field System.Drawing.FontStyle True
GetType Method Type
HasFlag Method Boolean
ToString Method String
When I see fields, that tells me that I can define a value like this:
[System.Drawing.FontStyle]$FontStyle = 'Italic'
This should let me define the font.
PS C:\> $FontObject = New-Object System.Drawing.Font($Font, $Size, $FontStyle)
PS C:\> $FontObject
Size : 36
Style : Italic
Bold : False
Italic : True
Strikeout : False
Underline : False
FontFamily : [FontFamily: Name=Cascadia Code]
Name : Cascadia Code
Unit : Point
GdiCharSet : 1
GdiVerticalFont : False
OriginalFontName : Cascadia Code
SystemFontName :
IsSystemFont : False
Height : 56
SizeInPoints : 36
Next, I have to figure out how to position the text on the image. I am using the DrawString()
method of the Graphics
class. I'll look at the definitions again.
PS C:\> $graphics.DrawString.OverloadDefinitions
void DrawString(string s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y)
void DrawString(System.ReadOnlySpan[char] s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y)
void DrawString(string s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point)
void DrawString(System.ReadOnlySpan[char] s, System.Drawing.Font font, System.Drawing.Brush brush, System.Drawing.PointF point)
void DrawString(string s, System.Drawing.Font font, System.Drawing.Brush brush, float x, float y, System.Drawing.StringFormat format)
...