3

I'm trying to resize an image in PowerShell without saving a temporary file and then save it to Active Directory.

I'm getting a Byte Array from a database (I have no control over what is sent to me) and I'm able to save this as a file easily like this:

[System.Io.File]::WriteAllBytes("C:\PathToFile\img.jpg", $PhotoArray)

What I need to do is resize the image and then update the thumbnail image in Active Directory. I'm able to do this with the original file as it's already given to me as a Byte Array like this:

Set-ADUser -Identity $UserName -Replace @{thumbnailPhoto=$Photo} -Server $AdServerName

I can resize the image to make it smaller using this code:

$Photo_MemoryStream = new-object System.IO.MemoryStream(,$PhotoAsByteArray)
$quality = 75
$bmp = [system.drawing.Image]::FromStream($Photo_MemoryStream)
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[decimal]$canvasWidth = 100.0
[decimal]$canvasHeight = 100.0

$myEncoder = [System.Drawing.Imaging.Encoder]::Quality
$encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1)
$encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($myEncoder, $quality)
$myImageCodecInfo = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders()|where {$_.MimeType -eq 'image/jpeg'}

$ratioX = $canvasWidth / $bmp.Width;
$ratioY = $canvasHeight / $bmp.Height;
$ratio = $ratioY
if($ratioX -le $ratioY){
  $ratio = $ratioX
}

$newWidth = [int] ($bmp.Width*$ratio)
$newHeight = [int] ($bmp.Height*$ratio)
$bmpResized = New-Object System.Drawing.Bitmap($newWidth, $newHeight)

$graph = [System.Drawing.Graphics]::FromImage($bmpResized)
$graph.Clear([System.Drawing.Color]::White)
$graph.DrawImage($bmp,0,0 , $newWidth, $newHeight)

$bmpResized.Save("C:\PathToFile\img.jpg",$myImageCodecInfo, $($encoderParams))

How do I convert $bmpResized into a Byte Array so I can insert it into Active Directory? I'm sure this should be easy, but I've spent a long time trying to work out how to convert it into a Byte Array and failed!

I'm hoping someone out there has the magic answer I'm looking for :)

2
  • 2
    $Photo = [System.IO.File]::ReadAllBytes("C:\PathToFile\img.jpg"). Also, don't forget to $bmpResized.Dispose() when done
    – Theo
    Commented Dec 20, 2021 at 15:36
  • Could also save resized to MemoryStream, see: stackoverflow.com/questions/7350679/…
    – dugas
    Commented Dec 20, 2021 at 15:39

2 Answers 2

4

I've done this exact thing in C#. It's really the same in PowerShell since you're using .NET classes to do it.

You'd still use .Save, but to a MemoryStream, then use MemoryStream.ToArray(), like this:

$stream = New-Object System.IO.MemoryStream
$bmpResized.Save($stream, [System.Drawing.Imaging.ImageFormat]::Jpeg)
$byteArray = $stream.ToArray()

This assumes you want all your images in JPEG format.

0
3

@Theo already gave answer in OP for dealing with file. Below is an example of saving resized photo to MemoryStream:

See (C# example): Convert a bitmap into a byte array

try {
 $resizedStream = New-Object System.IO.MemoryStream
 $bmpResized.Save($resizedStream, ,$myImageCodecInfo, $encoderParams)
 $resizedPhotoByteArray = $resizedStream.ToArray()
}
finally {
 if ($null -ne $resizedStream) {
  $resizedStream.Dispose()
 }
}
1
  • You have a double comma in your .Save line. I'm assuming that's a typo? Commented Dec 20, 2021 at 15:55

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.