Powershell Image Conversion script – Part 4: Finalizing and check functionality

Standard

This the final part of the series. I’ll show the different functions that check several parameters so the script will run flawlessly.

The Init function

The name “Init” is a name I gave to the function becaue it’s the initial function that calls all the other functions.
The first part of the function look like this:

Function Init(){
$Error.Clear()

# If the createconfig parameters is set
If($createconfig -ne "")
{
Create-Config $createconfig
exit 0
}

First all the errors are cleared so no messages from former executions will be in the logfile.
Second the script checks if the script is executed to create a config. If the parameter is set the “Create-Config” function is called.

The next part of the script checks if the parameter “config” is set.

# Check for the "config" parameter. If so load the file
If($config -ne "")
{
# Does the file exist
If((Check-Config $config) -eq 0)
{
$xmlconfig = [xml]( Get-Content $config)
$source = $xmlconfig.Configuration.SourceImages

$sourceorg = @()
Foreach($s In $xmlconfig.Configuration.SourceReorganisation.Source)
{
$sourceorg = $sourceorg + $s
}

$destimage = $xmlconfig.Configuration.DestinationImage
$destthumb = $xmlconfig.Configuration.DestinationThumb

$destorg = @()
Foreach($d In $xmlconfig.Configuration.DestinationReorganisation.Destination)
{
$destorg = $destorg + $d
}

$archive = $xmlconfig.Configuration.ImageArchive
$sizeimage = $xmlconfig.Configuration.SizeImage
$sizethumb = $xmlconfig.Configuration.SizeThumb
$sourceext = $xmlconfig.Configuration.SourceExtension
$targetext = $xmlconfig.Configuration.TargetExtension
$logdir = $xmlconfig.Configuration.Logdirectory

$cleanfolder = @()
Foreach($c In $xmlconfig.Configuration.CleanFolder.Folder)
{
$cleanfolder = $cleanfolder + $c
}
}
Else
{
exit 0
}
}

It checks if the file exists. If it does it the file is loaded. If not the script is stopped. The config file is not mandatory for the script because it can work with only parameters.

The next part is to check all the values:

# Check values
If((Check-Logdir $logdir) -ne 0){exit 0}
If((Check-SourceExtension $sourceext) -ne 0){ exit 0 }
If((Check-TargetExtension $targetext) -ne 0){ exit 0 }
If((Check-Dimensions $sizeimage $sizethumb) -ne 0){ exit 0}
If((Check-Directories $source) -ne 0){ exit 0}
If((Check-Directories $destimage) -ne 0){ exit 0}
If((Check-Directories $destthumb) -ne 0){ exit 0}
If((Check-Directories $archive) -ne 0){ exit 0}
If((Check-Directories $archive) -ne 0){ exit 0}

Function Check-Logdir

The code check if the logdir is given or exists. It look like this:

# Function Check-Logdir
# This function checks the logdirectory
#
# Parameters:
# [string] $strLogdir: Directory variable
# Return:
# [int] 0: Succes
# [int] 1: Error
Function Check-Logdir([string]$strLogdir)
{
#If no log directory is given
If([string] $logdir -eq "")
{
$message = "No log directory is given"
Write-Host $message
Return 1
}
#If the log directory does not exist
If(!(Test-Path $strLogdir))
{
$message = "The log directory $strLogdir does not exist!"
Write-Logfile $message
Write-Host $message
Return 1
}

Return 0
}

Function Check-SourceExtension

The code check for a source extension parameter. If no parameter is given it uses the standard source extension.

# Function Check-SourceExtension
# This function checks the the given extension
#
# Parameters:
# [string] $strExt: Extension the script searches for
# Return:
# [int] 0: Success
# [int] 1: Error
Function Check-SourceExtension([string]$strExt)
{
If([string] $strExt -eq "")
{
$message = "No source extension is given. Standard extension $SOURCEEXTENSION will be used."
Write-Logfile $message
Write-Host $message
Return 0
}

return 0
}

Function Check-TargetExtension

This function works the same as the function Source-Extension but sets a different value in case of an error.

# Function Check-SourceExtension
# This function checks the the given extension
#
# Parameters:
# [string] $strExt: Extension the script will convert the images to
# Return:
# [int] 0: Success
# [int] 1: Error
Function Check-TargetExtension([string]$strExt)
{
If([string] $strExt -eq "")
{
$message = "No target extension is given. Standard extension $TARGETEXTENSION will be used."
Write-Logfile $message
Write-Host $message
Return 0
}

return 0
}

Function Check-Dimensions

The following function checks if the dimensions given at the parameters are right.

# Function Check-Dimensions
# This function checks the given dimensions voor the image resizing
#
# Parameters:
# [int] $sizeimage: Size of large image
# [int] $sizethumb: Size of thumbnail
# Return:
# [int] 0: Success
# [int] 1: Error
Function Check-Dimensions($sizeimg, $sizethb)
{
# If the size of the resize is greater than the original
If($sizeimg -ne "" -and $sizeimg -lt $sizethb)
{
$message = "Size of the large image is greater than the thumbnail size."
Write-Logfile $message
Write-Host $message
Return 1
}

# If no parameter is given for the larger image
If($sizeimg -eq "" -or 0)
{
$message = "No size given for the image."
Write-Logfile $message
Write-Host $message

Return 1
}
# If no parameter is given for the thimbnail image
If($sizethb -eq "" -or 0)
{
$message = "No size is given or the thumbnail."
Write-Logfile $message
Write-Host $message

Return 1
}

return 0
}

Function Check-Directories

This function checks if a directory value is given or if it exists.

# Function Check-Directories
# This function checks the directory is given or exists
# doorgegeven variabele een waarde bevat
#
# Parameters:
# [string] $strDir: Directory
# Return:
# [int] 0: Success
# [int] 1: Error
Function Check-Directories([string]$strDir)
{
#If no directory is given
If([string] $strDir -eq "")
{
$message = "No directory given!"
Write-Logfile $message
Write-Host $message
Return 1
}
#If directory doesn't exist
If(!(Test-Path $strDir))
{
$message = "Directory $strDir doesn't exist!"
Write-Logfile $message
Write-Host $message
Return 1
}

Return 0
}

The next part is to get the image format of the target extension:

# Get the image format
$imageFormat = Get-Imageformat $targetext

The code for getting the image format looks like this:

# Function Get-Imageformat
# Get the image format based on the parameter
#
# Parameters:
# [string] $strExt: String with extension
# Return:
# [string] $imageFormat: String with image format
Function Get-Imageformat([string]$strExt)
{
$imageFormat = "";
# Controleer de extensie
Switch($strExt)
{
# Set the extension
"gif" {$imageFormat = "gif"}
"GIF" {$imageFormat = "gif"}
"jpg" {$imageFormat = "jpeg"}
"jpeg" {$imageFormat = "jpeg"}
"tiff" {$imageFormat = "tiff"}
"TIFF" {$imageFormat = "tiff"}
"png" {$imageFormat = "png"}
"PNG" {$imageFormat = "png"}

# If the given parameter does not ccontain a right image format
default
{
$message = "The extension os no known image format!"
Write-Logfile $message
Write-Host $message
exit 0
}
}
# Return the image format
Return $imageFormat
}

The next part is to get all the files and folders from the given directory.

# Get alle the files and directories
$arraySourcedir = Get-Sourcedirs $source $sourceext

The code to get all the files and folders looks like this:
[cc lang="powershell"]
# Function Get-Sourcedirs
# This function returns all the subdirectories and files from the given source directory
#
# Parameters:
# [string] $s
# Resturns
# [array] $y: Array with all subdirectories and files
Function Get-Sourcedirs([string]$s, [string]$e)
{
# Execute the Get-Child-Item function
$y = Get-ChildItem -r $s -include $e | % { $_.FullName }

# Return results
return $y
}

The next part is to start converting the images

# If there any results in the sourcearray
If($arraySourcedir.length -gt 0)
{
# Loop through the functions for image conversion
Foreach($item In $arraySourcedir)
{
Convert-Image $item $destimage $sizeimage $targetext $imageFormat
Convert-Image $item $destthumb $sizethumb $targetext $imageFormat
Move-Image $item $archive
}
}
Else
{
# Write error in logfile
$message = "No images found in given directory!"
Write-Host $message
Write-Logfile $message
}
}

In this part of code another function is called named “Move-Image”. This function moves the original file to the given archive directory. The code looks like this:

# Function Move-Image
# This function moves the original image.
# It checks if the target directory exists. If not it creates the directory
#
# Parameters:
# [string] $imageLocation: Original location of the image
# [string] $to: Target location of the image
Function Move-Image([string]$imageLocation, [string] $to)
{
# Create a new path for the file
$newImageLocation = Replace-String $source $to $imageLocation
# Get the directory from the path
$newFolder = [System.IO.Path]::GetDirectoryName($newImageLocation)

# Test if the target directory exists
If(!(Test-Path $newFolder))
{
# If not create it
New-Item $newFolder -type directory
}

# Move the image
Move-Item $imageLocation $newImageLocation -force
}

The above code uses the function “Replace-String” that is also used in the function “Convert-Image”.

The last part of the code starts the reorganization and cleaning of the directory:

# Reorganize directories
Reorganise-Folders $sourceorg $destorg

# If the "cleanfolder" parameter is set
If($cleanfolder)
{
If($cleanfolder.length -gt 0)
{
Clean-Folder $cleanfolder
}
}

The function for reorganizing the directory by selecting the first three characters from the image’s directory. Creating an new directory and move the images to the archive:

# Function Reorganise-Folders
# This function reorganises the directories by selecting the first three characters
# from the original directory.
# Example: 1020567 will be replaced with 102
#
# Parameters:
# [array] $s: Source directory
# [array] $d: Target directory
Function Reorganise-Folders($s, $d)
{
# Check if the directories are correct and exist
If($s.length -and $d.length -gt 0)
{
For($i = 0; $i -lt $s.length; $i++)
{
If((Check-Directories $s[$i]) -ne 0){ exit 0}
If((Check-Directories $d[$i]) -ne 0){ exit 0}

# Get alle directories
$arraySourcedirs = Get-ChildItem $s[$i] | Where { $_.attributes -eq "Directory" }

# Loop through the array
If($arraySourcedirs.length -gt 0)
{
Foreach($item in $arraySourcedirs)
{
# Convert the item in the array to string
[string] $dir = $item

# Check if the length of the directory is no greater than 3
If($dir.length -gt 3)
{
# Create the new name
$newName = $dir.Substring(0,3);

# Create the old en new full paths
$oldDir = $s[$i] + "\" + $dir
$newDir = $d[$i] + "\" + $newName + "\" + $dir

# Test if the new path exists
If(!(Test-Path $newDir))
{
# If not create it
New-Item $newDir -type directory
}

# Move the images from the directory to the new one
#Move-Item $oldDir $newDir -force -verbose
Write-Host "robocopy.exe $olddir $newdir /E /S /R:10 /MOVE"
robocopy.exe $olddir $newdir /E /R:10 /MOVE /IS
}
}
}
}
}

An example for an archive folder would be:

  • C:\Imageconversion\Archive\104\10453678\

Where the original directory would be:

  • C:\Imageconversion\Source\10453678\

The last function cleans all the folder given. The original images are moved away from the source directory what leaves empty directories. To clean them the following function is used:

# Function Clean-Folders
# This function makes it possible to clean up the empty directories
#
# Parameters:
# [array] $folder: Location of the folder that need to be cleaned
Function Clean-Folder($folder)
{
Foreach($i In $folder)
{
# Get all the subdirectories
$f = Get-ChildItem $i | Where-Object {$_.PSIsContainer -eq $True}

# Check the length of the results
If($f.length -gt 0)
{
# Loop door de items heen
Foreach ($item in $f)
{
# Check if the directory doesn't contain any files
If($item.GetFiles().Count -eq 0)
{
# Create path to dir
$d = $i + "\" + $item
# Check if the path still exists
If(Test-Path $d)
{
# Remove dir
Remove-Item $d -Recurse
}
}
}
}
}
}

I hope you enjoyed the article. It contained a lot functionality what created the solution. If you have any recommendation or remarks about the article leave a comment.

The full script can be downloaded from here.

Powershell Image Conversion script – Part 3: Configuration functionality

Standard

Because I’m one of the type of people that is lazy as hell as it comes to IT, I created functionality that enabled me to create and read a configuration file for the script.

The first part of the article will explain the proces of creating a configuration file. The second part will show how the script works wih reading the configuration file.

In case of configuration files you have a lot of choices what type of file you use. There is a simple text file with the settings separated by comma of a new line . You can choose to use a Microsoft Access DB of any other database type but that will make you rely on a third-party product.
The reason why I chose XML is because it a good standard for setting op data. There are a lot of articles around that show you how to create and read config file. Further I like XML because it just look real clean.

Creating the configuration file

Like I mentioned before  I don’t like to do things by hand too much and I wanted other people to be able to implement the script in a way that you don’t have to be a rocket scientist to set it up.
With the use of input boxes  you have an easy way to let users input values that we can use to create the configuration file.

Powershell doesn’t support input boxes but Visual Basic does. The following code show the function:

# Function Show-Inputbox
# This function generates a inputbox where values can be inserted
#
# Parameters:
# [string] $question: Question in screen
# [string] $title: Title of the input box
# [string] $default: Default value if the cancel button is clicked
Function Show-Inputbox([string]$question, [string]$title, [string]$default)
{
[reflection.assembly]::loadwithpartialname("microsoft.visualbasic") | Out-Null
[microsoft.visualbasic.interaction]::InputBox($question, $title, $default)
}

The reason I created this function is because the function that will create the configuration file will use this functionality multiple times.

The following code will set up the part where the settings are picked up from the user:

# Function Create-Config
# This function makes it possible to create a coniguration file
#
# Parameters:
# [array] $loc: Full path where the configuration will be created
Function Create-Config($loc)
{
# Get the settings
$var1 = Show-Inputbox "Source directory images" "Source directory Images" ""
$var2 = Show-Inputbox "Source directory for reorganisation" "Source directory Reorganisation" ""
$var3 = Show-Inputbox "Target directory for images" "Target directory images" ""
$var4 = Show-Inputbox "Target directory for thumbnails" "Target directory thumbnails" ""
$var5 = Show-Inputbox "Target directory for reorganisation" "Target directory Reorganisation" ""
$var6 = Show-Inputbox "Archive directory for images" "Archive directory" ""
$var7 = Show-Inputbox "Size for images" "Size images" ""
$var8 = Show-Inputbox "Size for thumbnails" "Size thumbnails" ""
$var9 = Show-Inputbox "Source extension" "Source extension" ""
$var10 = Show-Inputbox "Target extension" "Target Extension" ""
$var11 = Show-Inputbox "Directory for logfiles" "Log directory" ""
$var12 = Show-Inputbox "Dierctory to clean up" "Directory for cleaning" ""

As you can see the function for the input box is called 12 times to get all the settings.

The next part will show how the XML file is set up and saved:

# Setup XML data
$xmlconfig = [xml]"
$var1
$var2
$var3
$var4
$var5
$var6
$var7
$var8
$var9
$var10
$var11
$var12
"

# Save the data
If(!(Test-Path $loc))
{
New-Item $loc -type file
}
$xmlconfig.save($loc)
}

The function can be used in the following way:

Create-Config "E:\Imageconversion\MyConfiguration.xml"

Reading the configuration file

Now we have a way to reate a configuration file. But how do we read the data from it. This can be done with the following code:

$xmlconfig = [xml]( Get-Content $config)
$source = $xmlconfig.Configuration.SourceImages

$sourceorg = @()
Foreach($s In $xmlconfig.Configuration.SourceReorganisation.Source)
{
$sourceorg = $sourceorg + $s
}

$destimage = $xmlconfig.Configuration.DestinationImage
$destthumb = $xmlconfig.Configuration.DestinationThumb

$destorg = @()
Foreach($d In $xmlconfig.Configuration.DestinationReorganisation.Destination)
{
$destorg = $destorg + $d
}

$archive = $xmlconfig.Configuration.ImageArchive
$sizeimage = $xmlconfig.Configuration.SizeImage
$sizethumb = $xmlconfig.Configuration.SizeThumb
$sourceext = $xmlconfig.Configuration.SourceExtension
$targetext = $xmlconfig.Configuration.TargetExtension
$logdir = $xmlconfig.Configuration.Logdirectory

$cleanfolder = @()
Foreach($c In $xmlconfig.Configuration.CleanFolder.Folder)
{
$cleanfolder = $cleanfolder + $c
}

As you can see some variables in the script can handle multiple directories. In the Create-Config function I didn’t implement the feature to add multiple values because in my case that wasn’t an issue.
The above code uses the global variables created in the beginning of our first script by creating parameters for Powershell.

I didn’t make a function for reading the configuration file because later on it’ll only be used once during the execution of the script.

Powershell Image Conversion script – Part 2: Logging functionality

Standard

One of the important parts of the script is the logging functionality. Because we’re dealing with large amounts of files that are converted it’s good to know what has been done and may have gone wrong.

The following code will write the logfile:

# Function Write-Logfile
# This function writes, in case of an error, a rule to the logfile
# The logfile will be created with the following format: yyyymmdd
#
# Parameters:
# [string] $message: Message that need to be written
Function Write-Logfile([string]$message)
{
# set up date
$date = Get-Date -format "yyyyMMdd"
# get time for the logging
$logtime = Get-Date -Format "[HH:mm:ss]"
#set up the path to logfile
$logfile = $logdir + "\" + "logfile-" + $date + ".log"
# add the contect to the file
Add-Content $logfile "$logtime $message"
}

The function will write a line in a logfile. If no logfile exists it will create a logfile with the following name: logfile-yyyymmdd.log. An example of the name could be: logfile-20100922.log
If the file already exists it will not be created, instead it will write to the file. The log in the file would look similar to this:

09:22 Image 87623e8668762 converted

The function uses the local variable $logfile that has been added as a parameter during execution.
To add the log functionality to the “Convert-Image” do the following:

After the code:

# Create a new imageobject
$oldImage = new-object System.Drawing.Bitmap $sourceImage
[/cc]

add the following code:
[cc lang="powershell"]
# If there is an error write to logfile
If($Error.Count -ne 0)
{
Write-Logfile($Error)
$Error.Clear()
}
[/cc]

After the code:
[cc lang="powershell"]
# Save the new image
$newImage.Save($newFile, ([system.drawing.imaging.imageformat]::$imageFormat))

add the following code:

# Write the results to a logfile
Write-Logfile "Image $newFile converted"

Powershell Image Conversion script – Part 1: Image conversion

Standard

Introduction

In one of my former jobs I was responsible for a few servers that where used for an OCR (Optical Character Processing) proces. All the dossiers that were ever archived were being scanned and processed to range of  TIFF files of the individual pages into a directory.

Internally dossiers were viewable through a portal that searched for the files in a certain directory.

The proces was implemented with batch files calling IrfanView that processed the pages of the dossiers to images that would be viewable in a browser. The TIFF files were converted to GIF because viewing TIFF files is not a standard feature in browser.

After Irfanview processed the images  another batch file would be executed to copy the files to there final destination and archive the original files.

The problem

During the day the IrfanView proces would crash multiple times (read about 20 times a day). Further of all the program IrfanView is/was only free for personal use only. The company didn’t have a license so the product had to be replaced.

During he crash all the images that were waiting to be processed got lost and had to be copied from an archive to the processing directory. You can imagine that wasn’t a good situation where 80% of the company relied on the documents to be available on the portal.

All the  batch file were configured using the Task scheduler of Windows Server 2003. They were configured to run at a certain moment after each other. If one of the batch processes was unable to finish in time the other batch proces would cut in and to his work.

That again is not a reliable situation for the company.

All the dossiers were saved in a single directory. The company had more than 2,5 million dossiers. Anyone who ever had a lot of files in one directory knows that filesystems will have trouble scanning a directory that contains thousands of directories (at least Windows based filesystems). The directory already contained over 20.000 dossiers so performance was starting to be a problem.

Another problem that created an unreliable situation.

The challenge

The following obstacles had to be overcome to create a reliable situation:

  • create a solution where third party software wasn’t needed anymore like IrfanView
  • create a script to convert the images from any imagetype to another imagetype
  • make functionality
    • that would group individual directories.
    • that check all the files and directories for possible errors
    • that would read a config file or create one
  • logging the script actions had to be possible
  • the solution had to do the whole proces in one go

Hmm a lot of work. In the series I will show how to do this and the source files will be downloadable.

The series exist of the following:

  1. Create functionality for image conversion
  2. Create functionality for logging
  3. Create functionality for configuration files
  4. Finalizing and implement check functionality

Part 1 will be explained in this article. The rest will be posted soon.

Part 1: Create functionality for image conversion

I gave myself the following demands what the script had to be or image conversion:

  1. The script had convert had to search for specific image type
  2. The script had to convert any imagetype to any other image type
  3. The script had to be able to resize the image
  4. The name of the new image has to be unique in the dossierfolder.

The general idea of he conversion is to call the method for the conversion twice for every image. One for the large image and once for the thumbnail. This way we dont have to create two seperate functions.

The top part of the script looks as follows:

Param(
[string]$source,
[array]$sourceorg,
[string]$destimage,
[string]$destthumb,
[array]$destorg,
[int]$sizeimage,
[int]$sizethumb,
[string]$sourceext,
[string]$targetext,
[string]$logdir,
[string]$archive,
[string]$config,
[string]$createconfig,
[array]$cleanfolder
)
[reflection.assembly]::LoadWithPartialName("System.Drawing")

In the first part of this article we won’t need all the parameters. The reason I included them is because in the following articles they’ll be needed.

Below the parameters we’re adding .Net functionality to the powershell script to be able to convert the images.

The first part of the function contains the following code:

 

# Function Convert-Image
# This function converts the image and creates a thumbnail
#
# Parameters:
# [string] $sourceImage : Path to image
# [string] $destinationDir : Destination directory
# [int] $newSize : New size for image
# [string] $extension : New extension or image
# [string] $imgFormat : New imageformat for image
Function Convert-Image
(
[string]$sourceImage,
[string]$destinationDir,
[int]$newSize,
[string]$extension,
[string]$imgFormat
)
{

The function has 5 parameters:

  1. sourceImage: Contains the full path to the original directory
  2. destinationDir: Path to the destination of the newly created image
  3. newSize: The size of the longest side of the new image
  4. extension: Extension of the new image
  5. imgFormat: The format of the new image

The next step is to load the source image and get several data rom it like width and height etc.

# Create a new imageobject
$oldImage = new-object System.Drawing.Bitmap $sourceImage

# Get the height of the original image
$longSide = $oldImage.Height

# If the height is smaller than width
If($oldImage.Height -lt $oldImage.Width)
{
# Set the longest side to be the width
$longSide = $oldImage.Width
}

In the code above the image is read into memory. Than the scripts looks for the longest side of the image.
Later in the script were using this value to resize the image.

Next up is to decide what the new width and height are going to be.

# If the longest side is greater than the new size
If ($longSide -gt $newSize)
{
# If the height of the original image is lower than the with
If ($oldImage.Height -lt $oldImage.Width)
{
# Set the variables
$newH = $newSize
$newW = [int]($oldImage.Width * $newSize / $oldImage.Height)

}
# If the height of the original image is greater than the width
Else
{
$newW = $newSize
$newH = [int]($oldImage.Height * $newW / $oldImage.Width)
}
}

The script first checks if the longest side is greater than the new size of the image. If this isn’t the case there is no need for it to be resized. You could resize the image from a smaller version to a larger image but than the quality of the image would be insufficient to work with.

The next thing the script checks is if the original image’s height is smaller than the width. Based on this the new height en new width are calculated.

The next code creates a new image object in memory. Than chooses the algorithm is wants to use to convert the image.
Finally it creates the new image with the desired size.

# Create a new imageobject
$newImage = new-object System.Drawing.Bitmap $newW, $newH
$g = [System.Drawing.Graphics]::FromImage($newImage)

# Use high quality conversion
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic

# Resize the image
$g.DrawImage($oldImage, 0, 0, $newW, $newH)

The next code creates the new directory for the image and checks if it is successfully created.

# Create the folders where the image will be copied
$oldFolder = [System.IO.Path]::GetDirectoryName($sourceImage)
$newFolder = Replace-String $source $destinationDir $oldFolder

# Check if the path exists. If not create it
If(!(Test-Path $newFolder))
{
New-Item $newFolder -type directory
}

The code above uses a function named “Replace-String”. I created this function to easily create a new directory based on the old directory. The code for the function is as follows:

# Function Replace-String
# This function replaces a certain text in a string
#
# Parameters:
# [string] $find: Text that needs to be searched for
# [string] $replace: Original text needs to be replaced with
# [string] $string: Text what should be searched in
Function Replace-String([string]$find, [string]$replace, [string]$string)
{
# Replace text
$x = $string.Replace($find, $replace)

# Return results
return $x
}

I could have used the Replace function but I wanted to make a nice method from it.

The next code will set up the new path to the new image and write the data rom memory to it.
Further it will dispose the used data from memory

# Setup the full path of the new image
$newFile = $newFolder + "\" + $name

# Save the new image
$newImage.Save($newFile, ([system.drawing.imaging.imageformat]::$imageFormat))

# Remove data of the proces from memory
$newImage.Dispose()
$oldImage.Dispose()

Finally the function ends with the code below:

}
Else
{
Write-host -NoNewLine "."
$oldImage.Dispose()
}
}

How to execute the created code:

Convert-Image C:\Imagedir\12423423\image1.jpg C:\Portal\124\124234\ 200 .jpg jpeg