1

I am trying to get a base64 image string into the system.drawing.image object (done) and then back out to base64 (not working), to include inline in an HTML e-mail, but am having difficulty.

The below (commented out lines) came from a website page on how to do what isn't working, but the first error relates to no arguments in the MemoryStream object creation, so I am wondering if this is a wholly wrong way of going about this. I am having problems finding any other websites that detail how to do this, especially in Powershell and not these objects native .NET.

Note: The rest of the code works to edit the image as intended, shown by outputting to a file instead ($NewBitmap.save(<filename>)).

What am I missing?

$ImageBytes = [Convert]::FromBase64String($AccountNameInputExamplePic)
$ImageBytesMemoryStream = New-Object IO.MemoryStream($ImageBytes, 0, $ImageBytes.Length)

$OldBitmap = [System.Drawing.Image]::FromStream($ImageBytesMemoryStream, $true)
#new-object System.Drawing.Bitmap $Source
$NewBitmap = new-object System.Drawing.Bitmap $OldBitmap.width,$OldBitmap.height
$g=[System.Drawing.Graphics]::FromImage($NewBitmap)
$g.clear([System.Drawing.Color]::White)
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic 
$g.DrawImage($OldBitmap, 0, 0, $OldBitmap.width,$OldBitmap.height)
$font = new-object System.Drawing.Font "Segoe UI",13
$brushFg = [System.Drawing.Brushes]::Yellow         
$g.DrawString($($UserAndPasswordExpiry.sAMAccountName),$font,$brushFg,190,463) 
$g.Dispose() 

#$ImageBytesMemoryStream = New-Object IO.MemoryStream()

#$NewBitmap.save($ImageBytesMemoryStream, System.Drawing.Imaging.ImageFormat.ToString())

#$ImageBase64 = [Convert]::ToBase64String($ImageBytesMemoryStream)
8
  • Your mail message has to be MIME and the image one of the MIME attachments. See learn.microsoft.com/en-us/previous-versions/office/developer/… Commented Jun 25, 2024 at 12:40
  • @jdweng As my question didn't include any code to e-mail anything, I am not sure how your comment relates. However, whether it is by standards, or not, have tested the unaltered image works in a <img src="data:image/png;base64,""> tag, fine. Commented Jun 25, 2024 at 14:27
  • You said " to include inline in an HTML e-mail," With HTML email, when you combine text and images it is MIME. Commented Jun 25, 2024 at 15:04
  • @jdweng Worked fine without, so hopefully this is useful to others. Commented Jun 26, 2024 at 16:02
  • You can send the entire email body as Base64 text, but then you will need to unpack the entire body. MIME give more options on treating an email in sections instead of one object. Commented Jun 26, 2024 at 20:26

2 Answers 2

2

You have a few typos in the last section of your code:

  1. New-Object IO.MemoryStream(), when using the New-Object command you don't need parentheses to invoke a specific constructor, ctor arguments are space delimited and in this case and the parentheses are causing a parsing issue. See Recommended way of creating a new object using the newer syntax.

    $ImageBytesMemoryStream = [System.IO.MemoryStream]::new()
    
  2. Second argument passed to .Save: System.Drawing.Imaging.ImageFormat.ToString() is a syntax error. The argument is expecting a ImageFormat property value, see the link to check which are available. I'll use Png for the example.

    $NewBitmap.Save($ImageBytesMemoryStream, [System.Drawing.Imaging.ImageFormat]::Png)
    
  3. You're trying to convert a memory stream object to base64 instead of its bytes, use .ToArray() to get the image bytes stored in it:

    [Convert]::ToBase64String($ImageBytesMemoryStream.ToArray())
    

Summing up, this is how the last section of your code should look:

$ImageBytesMemoryStream = [System.IO.MemoryStream]::new()
$NewBitmap.Save($ImageBytesMemoryStream, [System.Drawing.Imaging.ImageFormat]::Png)
$ImageBase64 = [Convert]::ToBase64String($ImageBytesMemoryStream.ToArray())
Sign up to request clarification or add additional context in comments.

Comments

1

Assuming you want the adjusted image in $NewBitmap back to Base64 string, you can do below:

# select the image format to use (here PNG as example)
$imageFormat  = [System.Drawing.Imaging.ImageFormat]::Png
# create a MemoryStream object
$memoryStream = [System.IO.MemoryStream]::new()
# use the Bitmap's Save() method and save the data to the MemoryStream
$NewBitmap.Save($memoryStream, $imageFormat)
# use the MemoryStream's ToArray() method to get the bytes to convert into a Base64 string
$ImageBase64 = [Convert]::ToBase64String($memoryStream.ToArray())

# clean up memory when no longer needed
$memoryStream.Dispose()
$NewBitmap.Dispose()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.