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.
Hi Overthere,
was trying this one out but only get errors “ampersand not allowed” Any clue with this?
Thx in advance
Ralf
Hey, does this still work? mine script just downloads the same images every day now.
I must have had an outdated copy, download it again and works fine.
I did at a few lines so that if the file size was larger than 256kb then is reduced the quality. I found that I was getting quite a few days where no image would be displayed, turns our if the file needs to be less than 256kb.
Thanks for the update, Martin!
Excellent idea! Stealing this today!
I personally think that the image description would look better back in the lower-left corner as originally described. What would I need to change in the script to revert that?
Thanks!
Thanks! I agree, it does look better in the left corner. I changed it because I had so many different monitor resolution types. On smaller resolutions, it would cut off the text.
Change line 30 to: [int]$MiddleStartingPoint = 45
Increase that value to make the text move to the right. Decrease it to move it to the left. It is currently 45 pixels off from the left which should give you a good padding.
Thanks a million!
I was able to resolve the issue with the script keeping the withouttext\defaultBackground.jpg open.
After the ForEach block that gets the average color add:
$BitMap.Dispose()
Thank you for this!! I edited the script and gave you credit for fixing that bug.
You may want to download the script again. I made some other changes to it.
Great script! Took me a while to get it to work though. It would run fine in ISE but not from the console untill I added
Add-Type -Assembly System.Drawing to the script.
Thanks Mark! Oddly, I did not need to add that to mine but I did edit the script on this page to include it. Thanks for helping out!
This won’t work on Windows 10 Pro, you need Enterprise, Edu or Server.
Hey Trent- try that registry key that I mentioned using for Windows 7 machines. Let me know if that works for Windows 10 Pro machines.