No matter how many cool things I do at work, everyone thinks that the Bing image syncing script is the coolest. By using PowerShell to download the Bing image and Group Policy to distribute it, the default logon (sign in) background rotates each day. Several years ago, I wrote about that process in this post.
Last week, I was asked (yet again) where the picture of the day came from. I normally point people to Bing where they can look in the bottom right for the picture caption. On that day, I was feeling particularly automatous and thought it would be awesome to paste the picture title over top the downloaded image. Thanks to PowerShell, that is what I did!
To use this script, set the $saveLocation and $saveLocationWithDescriptionAdded variables at the top of the script. Keep the file name (backgroundDefault.jpg) the same.
Set the script to run daily and then to repeat every hour in case the image changes during the day. Make sure that the user running the script has write permission to the path specified in your two variables. The Group Policy settings can be found below the script.
#Location to store original image $saveLocation = ‘\\SERVER\SHARE\Bing Background\WithoutText\backgroundDefault.jpg’ #Location to store image with title added to it. Group Policy should point to this image. $saveLocationWithDescriptionAdded = '\\SERVER\SHARE\Bing Background\backgroundDefault.JPG' #Height From Bottom in Pixels. This controls how far up from the bottom that the next is written. Should not be lower than 21. Set to 75 for the text to appear above taskbar if used as desktop background. $HeightfromBottom = 45 #Download Bing Image to SaveLocation $uri = “https://www.bing.com/HPImageArchive.aspx?format=rss&idx=0&n=1&mkt=en-US” [xml]$BingImage = Invoke-WebRequest -Uri $uri -SessionVariable Bing -ContentType "text/xml; charset=utf-8" -Method Get $CurrentImage = $BingImage.rss.channel.item #Microsoft provides several different resolutions. This script grabs the 1920x1080. Remove the .Replace* to keep the 1366x768 version. $ImageURL = "https://www.bing.com" + ($CurrentImage.link).Replace("1366x768.jpg","1920x1080.jpg") Invoke-WebRequest $ImageURL -OutFile $savelocation #Get Bing Image Title $Title = Invoke-WebRequest -Uri $uri -SessionVariable Bing -ContentType "text/xml; charset=utf-8" -Method Get -OutFile C:\Users\Public\title.txt $Title = (Get-Content C:\Users\Public\title.txt -Encoding UTF8) $Title = $Title -split '>' $Title = $Title.Item(12) $Description = $Title.Replace('</title',"") Remove-Item C:\Users\Public\title.txt -Force #Find Rough Description Pixel Length. 8.35 is average pixel size of a letter a 14 Ariel font. [int]$DescriptionPixelLength = ($Description.Length)*8.35 [int]$MiddleStartingPoint = 960 - ($DescriptionPixelLength/2) #Get Average Color of bottom left corner of picture Add-Type -Assembly System.Drawing $filename = "$saveLocation" $BitMap = [System.Drawing.Bitmap]::FromFile((Get-Item $filename).fullname) $Colors = @() Foreach($y in (($Bitmap.Height-$HeightfromBottom)..($BitMap.Height-($HeightfromBottom-20)))){ Foreach($x in ($MiddleStartingPoint..(($MiddleStartingPoint+$DescriptionPixelLength)))){ $Pixel = $BitMap.GetPixel($X,$Y) $R = $Pixel | select -ExpandProperty R $G = $Pixel | select -ExpandProperty G $B = $Pixel | select -ExpandProperty B $A = $Pixel | select -ExpandProperty A $Color = New-Object -TypeName psobject -Property ([ordered] @{ R = $R G = $G B = $B A = $A }) $Colors += $Color } } #Big thanks to Andrew for finding this out the used by another process bug. $BitMap.Dispose() $AverageColor = New-Object -TypeName psobject -Property ([ordered] @{ R = $Colors.R | Measure-Object -Average | select -ExpandProperty Average G = $Colors.G | Measure-Object -Average | select -ExpandProperty Average B = $Colors.B | Measure-Object -Average | select -ExpandProperty Average A = $Colors.A | Measure-Object -Average | select -ExpandProperty Average }) #Set Font RGB values for image title text if ($AverageColor.R -lt 128){$FontColorR = 255} if ($AverageColor.G -lt 128){$FontColorG = 255} if ($AverageColor.B -lt 128){$FontColorB = 255} if ($AverageColor.R -ge 128){$FontColorR = 0} if ($AverageColor.G -ge 128){$FontColorG = 0} if ($AverageColor.B -ge 128){$FontColorB = 0} #Converts Font Color to Black or White if (($FontColorR + $FontColorB + $FontColorG) -ge 510){$FontColorR = 255; $FontColorG = 255; $FontColorB = 255} if (($FontColorR + $FontColorB + $FontColorG) -lt 510){$FontColorR = 0 ; $FontColorG = 0 ; $FontColorB = 0 } #Add Bing Image Title to lower left corner of image. Orignal code from http://www.ravichaganti.com/blog/?p=1012 Function Add-TextToImage { [CmdletBinding()] PARAM ( [Parameter(Mandatory=$true)][String] $sourcePath, [Parameter(Mandatory=$true)][String] $destPath, [Parameter(Mandatory=$true)][String] $Title ) Write-Verbose "Load System.Drawing" [Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null Write-Verbose "Get the image from $sourcePath" $srcImg = [System.Drawing.Image]::FromFile($sourcePath) Write-Verbose "Create a bitmap as $destPath" $bmpFile = new-object System.Drawing.Bitmap([int]($srcImg.width)),([int]($srcImg.height)) Write-Verbose "Intialize Graphics" $Image = [System.Drawing.Graphics]::FromImage($bmpFile) $Image.SmoothingMode = "AntiAlias" $Rectangle = New-Object Drawing.Rectangle 0, 0, $srcImg.Width, $srcImg.Height $Bottom = $srcImg.Height - $HeightfromBottom $Image.DrawImage($srcImg, $Rectangle, 0, 0, $srcImg.Width, $srcImg.Height, ([Drawing.GraphicsUnit]::Pixel)) Write-Verbose "Draw title: $Title" $Font = new-object System.Drawing.Font("Arial", 14) $Brush = New-Object Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(240,$FontColorR,$FontColorG,$FontColorB)) $Image.DrawString($Title, $Font, $Brush, $MiddleStartingPoint, $Bottom) Write-Verbose "Save and close the files" $bmpFile.Save($savelocationwithdescriptionadded,[System.Drawing.Imaging.ImageFormat]::JPEG) $bmpFile.Dispose() $srcImg.Dispose() } Add-TextToImage -sourcePath $savelocation -destPath $savelocationwithdescriptionadded -Title $Description
Before continuing to the Group Policy portion, manually run the script once. You should see the current image from Bing.com saved to the file path specified in the first variable. You should see that same image along with the image description saved to the file path specified in the second variable. The text title color will change to contrast with the average color behind it.
[UPDATED 05/04/18]
This script now:
- Centers the text
- Accurately finds average background color of text regardless of text length.
- Chooses either black or white for text font. Disable the two lines under #Converts Font Color to Black or White to restore funky colors
- Able to write special symbols now. No more strange ?? symbols.
- Able to run script multiple times in the same window. Thanks for Andrew for finding that problem!
- Images and titles are now pulled directly from Bing instead of a 3rd party RSS feed.
Using Group Policy to Sync the Bing Image
Create a new GPO for your Bing Image configuration and link it to an OU containing computers. Under Computer Configuration\Policies\Windows Settings\Security Settings\File System, add a new entry for %SystemRoot%\Web\Wallpaper\Windows\img0.jpg and copy the permissions from the picture below.
Next, navigate to Administrative Templates\Control Panel\Personalization and enable Force a specific default lock screen and logon image. Set the value to: C:\windows\system32\oobe\info\backgrounds\backgroundDefault.jpg
In the same GPO, create three new File Preferences under Computer Configuration. The first preference uses a Create action and the second preference uses a Replace action. For both, the source should point to the JPG location that you entered for the $saveLocationWithDescriptionAdded variable. The target location for both preferences should be: C:\Windows\System32\oobe\info\backgrounds\backgroundDefault.jpg .
The third preference also uses a Replace action. The source should be C:\Windows\System32\oobe\info\backgrounds\backgroundDefault.jpg and the Target should be C:\Windows\Web\Wallpaper\Windows\img0.jpg .
Finally, configure a Registry preference under Computer Configuration matching the image below. This registry key is only need for Windows 7 clients so use an ILT to applies this key to just that operating system.
With all of that done, run a GPUpdate and reboot the computer. You should now see your Bing image (with the description) set as the logon and default background. If you have any questions or suggestions, let me know in the comments below!
01/22/18: Updated to fix ‘ symbol issues in the description text.
*Script Improvements to do (in case anyone else has a bit of spare time)
Figure out why script keeps withouttext\defaultBackground.jpg opened after completionFigure out how to get pixel width of description instead of assuming 600 pixel width value.