This script will read in all the images from a folder, reduce them and randomly place them around in a new image. You control the size and number of the replicated images, the backgrounds color, whether they get a border and it’s color and width.
 
Here are some results from the script –
 
You can greatly reduce and replicate many times a lot of images so the final image is covered –
 
Collage_20140127_193941
 
Or just replicate a few images which are not so reduced for a different effect –
 
Collage_20140129_190200
 
The background can also be made transparent –
 
Collage_20140201_101539
 
In a WinForms Form I add the needed .Net namespaces, defined the basic form, set some global variables and get the scripts path.
 

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# Global Values
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$global:reductionPercent = 10
$global:backgroundText = "Black"
$global:imageWidth = 1024
$global:imageHeight = 768
$global:imageBorder = 2
$Global:outFile = ""

# WinForm Setup
$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Location = "200, 200"
$mainForm.Font = "Comic Sans MS,9"
$mainForm.FormBorderStyle = "FixedDialog"
$mainForm.ForeColor = "Black"
$mainForm.BackColor = "Cornsilk"
$mainForm.Text = " Image Collage Maker"
$mainForm.Width = 1030
$mainForm.Height = 380

 
I then add the Input Image Filename TextBox and Label. To make filling in the name effective I added a Browse Button which calls a Function which uses the FolderBrowserDialog control to allow you to browse for the images folder.
 

# Input Box
$textBoxIn = New-Object System.Windows.Forms.TextBox
$textBoxIn.Location = "15, 30"
$textBoxIn.Size = "460, 20"
$mainForm.Controls.Add($textBoxIn)

# Input Box Label
$ProcessLabel = New-Object System.Windows.Forms.Label
$ProcessLabel.Location = "15, 12"
$ProcessLabel.Size = "300, 23"
$ProcessLabel.ForeColor = "MediumBlue" 
$ProcessLabel.Text = "Input Images Folder"
$mainForm.Controls.Add($ProcessLabel)

# Browse Input Button
$buttonBrowse = New-Object System.Windows.Forms.Button
$buttonBrowse.Location = "30, 290"
$buttonBrowse.Size = "75, 23"
$buttonBrowse.ForeColor = "MediumBlue" 
$buttonBrowse.Text = "Browse"
$buttonBrowse.add_Click({selectFolder})
$mainForm.Controls.Add($buttonBrowse)

function selectFolder {
	$selectForm = New-Object System.Windows.Forms.FolderBrowserDialog
	$getKey = $selectForm.ShowDialog()
	If ($getKey -eq "OK") {
        	$textBoxIn.Text = $selectForm.SelectedPath
        	$completeLabel.Text = "      "
	}
} # End SelectFolder

 
FolderBroswer
 
Next came the TrackBar control for the Number of Images and the Amount of Image Reduction. If you select 10% you end up images reduced to 10% of their original size.
 

# Image Reduction TrackBar
$reductionTrackBar = New-Object System.Windows.Forms.TrackBar
$reductionTrackBar.Location = "200,140"
$reductionTrackBar.Orientation = "Horizontal"
$reductionTrackBar.Width = 280
$reductionTrackBar.Height = 40
$reductionTrackBar.LargeChange = 20
$reductionTrackBar.SmallChange = 1
$reductionTrackBar.TickFrequency = 5
$reductionTrackBar.TickStyle = "TopLeft"
$reductionTrackBar.SetRange(1, 100)
$reductionTrackBar.Value = 10
$reductionTrackBarValue = 10
$reductionTrackBar.add_ValueChanged({
    $reductionTrackBarValue = $reductionTrackBar.Value
    $reductionTrackBarLabel.Text = "Image Reduced Size ($reductionTrackBarValue%)"
    $global:reductionPercent = $reductionTrackBarValue
})
$mainForm.Controls.add($reductionTrackBar)

# Image Reduction Label
$reductionTrackBarLabel = New-Object System.Windows.Forms.Label 
$reductionTrackBarLabel.Location = "15,140"
$reductionTrackBarLabel.Size = "180,23"
$reductionTrackBarLabel.ForeColor = "MediumBlue"
$reductionTrackBarLabel.Text = "Images Reduction Size ($reductionTrackBarValue%)"
$mainForm.Controls.Add($reductionTrackBarLabel)

 
TrackBar
 
ComboBoxes provide the selections for Background Color, Output Image Size, Border Color and Width.
 

# Background ComboBox
$backgroundComboBox = New-Object System.Windows.Forms.ComboBox
$backgroundComboBox.Location = "120,200"
$backgroundComboBox.Size = "120,20"
$backgroundComboBox.ForeColor = "Indigo"
$backgroundComboBox.BackColor = "White"
[void]$backgroundComboBox.items.add("Black")
[void]$backgroundComboBox.items.add("White")
[void]$backgroundComboBox.items.add("Random")
[void]$backgroundComboBox.items.add("Transparent")        
$backgroundComboBox.SelectedIndex = 0
$mainForm.Controls.Add($backgroundComboBox)

# Background ComboBox Label
$backgroundComboBoxLabel = New-Object System.Windows.Forms.Label 
$backgroundComboBoxLabel.Location = "15,200"
$backgroundComboBoxLabel.Size = "120,20"
$backgroundComboBoxLabel.ForeColor = "MediumBlue"
$backgroundComboBoxLabel.Text = "Background Color"
$mainForm.Controls.Add($backgroundComboBoxLabel)

 
ComboBoxes
 
After the collage has been configured you click the Process Button to generate the collage. The button calls the ProcessButton function first sets multiple values and a default color.
 

# Process Button
$buttonProcess = New-Object System.Windows.Forms.Button
$buttonProcess.Location = "145,290"
$buttonProcess.Size = "75, 23"
$buttonProcess.ForeColor = "Green" 
$buttonProcess.Text = "Process"
$buttonProcess.add_Click({ProcessImage})
$mainForm.Controls.Add($buttonProcess)

Function ProcessImage {
    $global:imageWidth  = [int]$imageComboBox.Text.Split("x")[0]
    $global:imageHeight = [int]$imageComboBox.Text.Split("x")[1]
    $global:imageBorder = [int]$borderComboBox.Text
    $completeLabel.Text = ""
    # Default Random Color
    $red   = (Get-Random -minimum 0 -maximum 255)
    $green = (Get-Random -minimum 0 -maximum 255)
    $blue  = (Get-Random -minimum 0 -maximum 255)

 
The collage Bitmap image object is defined as well as it’s Graphics Properties object and the Brush used for the borders. The Image Background color selection is processed. If Transparent is selected I used the MakeTransparent method. If Random then I set it to a randomly selected color. If neither them I set the color to be Black or White as selected. Next is the Image Border color. Either a Random color or the specific color selected in the ComboBox is used.
 

    # Create Image
    $bitmap = New-Object System.Drawing.Bitmap($global:imageWidth,$global:imageHeight)
    $bitmapGraphics = [System.Drawing.Graphics]::FromImage($bitmap)
    $brushBorder = New-Object System.Drawing.SolidBrush("Black")

    # Image Background Color
    If ($backgroundComboBox.Text -eq "Transparent") {
        $bitmap.MakeTransparent()
    } Else {
        If ($backgroundComboBox.Text -eq "Random") {
            $red   = (Get-Random -minimum 0 -maximum 255)
            $green = (Get-Random -minimum 0 -maximum 255)
            $blue  = (Get-Random -minimum 0 -maximum 255)
            $backColor = [System.Drawing.Color]::FromArgb($red, $green, $blue)
            $bitmapGraphics.Clear($backColor)
        } Else {
            $bitmapGraphics.Clear($backgroundComboBox.Text)
        }
    }

    # Image Border Color
    If ($borderColorComboBox.Text -eq "Random") {
        $red   = (Get-Random -minimum 0 -maximum 255)
        $green = (Get-Random -minimum 0 -maximum 255)
        $blue  = (Get-Random -minimum 0 -maximum 255)
        $borderColor = [System.Drawing.Color]::FromArgb($red, $green, $blue)
        $brushBorder = New-Object System.Drawing.SolidBrush($borderColor)
    } Else {
        $brushBorder = New-Object System.Drawing.SolidBrush($borderColorComboBox.Text)
    }

 
The main processing loop then runs. I fill the $files array with all the filename collected form the selected folder. Next I loop through the file for the slected number of interations. The file are loaded into a variable using the System.Drawing.Image Class FromFile method. I enclosed that method call in a Try/Catch error checking construct because non-image files will error. I found it more efficient to just let them error, throw the error away, and then let processing continue than to try and pretest for image files. A random starting point for the images is selected. The height and width is reduced to the selected percentage. If an image border was selected then a rectangle of the appropriate color is painted behind where the image will be placed but oversized by the selected value. There is no border method in the Image class so painting a rectangle behind makes the image appear to have a border. The image is then draw from the selected point over the border image. Finally the file is written using a filename structure including the data and time for uniqueness. The $error variable is checked to make sure we got a good write, the collage image displayed in a PictureBox and the COM objects disposed of.
 

    $i = 0; $folderName = $textBoxIn.Text
    $files = @()
    $files = Get-ChildItem $folderName
    While ($files.Length-2 -le $numberTrackbar.Value) {
        $files += Get-ChildItem $folderName  
    }
    While ($i -le $numberTrackBar.Value) { $i++
        $fileName = $folderName + "\" + $files[$i]
        Try {
            $imageFile = [System.Drawing.Image]::FromFile($fileName)
        }
        Catch {
        }
        $pointX = (Get-Random -minimum -100 -maximum ([int]$global:imageWidth + 100))
        $pointY = (Get-Random -minimum -100 -maximum ([int]$global:imageHeight + 100))
        $height = $imageFile.Height * ([int]$global:reductionPercent * .01)
        $width = $imageFile.Width * ([int]$global:reductionPercent * .01)
        If ($global:imageBorder -gt 0) {
	        $bitmapGraphics.FillRectangle($brushBorder, `
                $pointX-$global:imageBorder, `
                $pointY-$global:imageBorder, `
                $width +($global:imageBorder*2), `
                $height+($global:imageBorder*2))
        }
        $bitmapGraphics.DrawImage($imageFile, $pointX, $pointY, $width, $height)
    }

    $error.clear()
    $Global:outFile = $scriptPath + "\"  + "Collage_" + (Get-Date -UFormat %Y%m%d_%H%M%S) + ".bmp"
    $bitmap.Save($Global:outFile)
    FinalPicture($Global:outFile)

    $bitmap.Dispose()
    $bitmapGraphics.Dispose()
    If($error.count -gt 0) {
        $completeLabel.ForeColor = "Red"
        $completeLabel.Text = "Error!"
    }
} # End ProcessImage

 
The output Collage image is displayed in the Form using PictureBox Class. I use the Zoom SizeMode to center the image within the PictureBox.
 

# Final PictureBox
$finalPicture = New-Object System.Windows.Forms.PictureBox
$finalPicture.Location = "520, 20"
$finalPicture.ClientSize = "480, 300"
$finalPicture.BackColor = "Black"
$finalPicture.SizeMode = "Zoom"
$mainForm.Controls.Add($finalPicture)

Function FinalPicture {
    $file = (Get-Item $Global:outFile)
    $image = [System.Drawing.Image]::Fromfile($file)
    $finalPicture.Image = $image
}

 
The Display Button calls the default system viewer with Invoke-Item to display the image.
 

Function DisplayImage {
    If ($Global:outFile.Length -gt 0) {
        Invoke-Item $Global:outFile
    }
}

 
CollageMaker
 
Download the complete script here – CollageMaker.ps1
 
Updated 7/5/14 – Added additional output images sizes and changed image size text parser from SubString to Split.
 

Advertisements