Introduction
The best feature of the Bing search engine is that every day it has a nice photo as the start page background. Currently, I'm working on a larger app, that has a start screen & I thought about creating a similar design of different backgrounds every day.
Of course, this would require some sort of web service, and some work every now and then selecting the images. Basically, you would have to reinvent the wheel. Luckily, the Photo of the day can be downloaded easily.
Background
The Photo of the day information is available in several formats, provided by the Bing developers as an easy to use API. The photo data can be downloaded in XML, RSS and JSON formats. through the following links:
My implementation uses the XML data. I decided to use the XML data, because the Framework has built in Linq support for it, so parsing an XML is not much of a problem. RSS could be used also, but for that additional tweaking & bug fixing of the SyndicationFeed class would be required, because it has some problems with deserializing time information in RSS files. I wanted the code to be compact, so I decided to use the XML format.
The XML Layout
The XML root tag is images, which can contain multiple Image
tags. In the request URL, if you change the n parameter from 1
to 10
, then you will get the images of the last 10 days.
Each Image
node has a copyright & a copyrightlink node, which hold information for the copyright text & the associated copyright link. The Image
url is contained by the url node.
The Images
can have hotspots. These hotspots are special areas of the image. If your mouse is over a hotspot area, then an associated tooltip text could be displayed using this information. This feature isn't required by me, so the implementation doesn't deal with this.
After the Images data, a tooltips node is displayed, which contains tooltip data for creating a slideshow of the images. This data can be used as tooltips for the play, pause, next, and previous buttons. The data is returned in the requested regions language. The requested region is specified by the mkt url parameter.
="1.0" ="utf-8"
<images>
<image>
<startdate>20151028</startdate>
<fullstartdate>201510280000</fullstartdate>
<enddate>20151029</enddate>
<url>/az/hprichbg/rb/StagUK_EN-US9650313735_1366x768.jpg</url>
<urlBase>/az/hprichbg/rb/StagUK_EN-US9650313735</urlBase>
<copyright>A male red deer in London’s Richmond Park,
England (© Ian Schofield/Offset)</copyright>
<copyrightlink>http://www.bing.com/search?
q=red+deer+(animal)&form=hpcapt</copyrightlink>
<drk>1</drk>
<top>1</top>
<bot>1</bot>
<hotspots>
<hotspot>
<desc>You have a little something on your antler.</desc>
<link>http://www.bing.com/images/search?q=red+deer+
(Cervus+elaphus)&FORM=hphot1</link>
<query>There, you got it</query>
<LocX>15</LocX>
<LocY>33</LocY>
</hotspot>
<hotspot>
<desc>This time of year in the European wilderness…</desc>
<link>http://www.bing.com/videos/search?q=Red+Deer+Rut+
Fight&Form=hphot2#view=detail&
amp;mid=2A889A1A464E79E32F582A889A1A464E79E32F58</link>
<query>These males put those antlers to dangerous use</query>
<LocX>37</LocX>
<LocY>42</LocY>
</hotspot>
<hotspot>
<desc>There's no need to trek deep into the woods to see these stags.</desc>
<link>http://www.bing.com/search?q=richmond+park+london&form=hphot3</link>
<query>This one lives in the middle of an urban center</query>
<LocX>66</LocX>
<LocY>33</LocY>
</hotspot>
</hotspots>
<messages></messages>
</image>
<tooltips>
<loadMessage>
<message>Betöltés...</message>
</loadMessage>
<previousImage>
<text>Elozo</text>
</previousImage>
<nextImage>
<text>Következo</text>
</nextImage>
<play>
<text>Játék</text>
</play>
<pause>
<text>Szünet</text>
</pause>
</tooltips>
</images>
Using the Code
The interesting part of the code is located in the BingWallPaperClient.cs file, which implements the download functionality. The implementation uses image caching. The image & the assigned copyright information is stored in the temp directory of the user. If the temp file exists & it's not older than 24 hours, then no download is required, because the Photo of the day changes every 24 hours. The Image
data can be used in both WPF & Windows Forms projects, because both subsystems support loading JPEG files.
The DownLoad
function is available as synchronous & as an asynchronous method.
using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml.Linq;
namespace BingPhotoOfDayClient
{
public class BingWallPaperClient
{
private readonly string _feed;
private readonly string _tempfilename;
private readonly string _tempcoppyright;
private bool _loadcalled;
public BingWallPaperClient()
{
var tempdir = Environment.ExpandEnvironmentVariables("%temp%");
_tempfilename = Path.Combine(tempdir, "bingphotooftheday.jpg");
_tempcoppyright = Path.Combine(tempdir, "bingphotooftheday.txt");
_loadcalled = false;
_feed = "http://www.bing.com/HPImageArchive.aspx?
format=xml&idx=0&n=1&mkt=en-US";
}
public void DownLoad()
{
bool downloadneeded = true;
if (File.Exists(_tempfilename))
{
FileInfo fi = new FileInfo(_tempfilename);
if ((DateTime.UtcNow - fi.LastWriteTimeUtc).TotalHours < 24)
{
downloadneeded = false;
}
}
if (File.Exists(_tempcoppyright))
{
CoppyRightData = File.ReadAllText(_tempcoppyright);
downloadneeded = false;
}
else downloadneeded = true;
_loadcalled = true;
if (!downloadneeded) return;
var document = XDocument.Load(_feed).Elements().Elements().FirstOrDefault();
var url = (from i in document.Elements()
where i.Name == "url"
select i.Value.ToString()).FirstOrDefault();
var imgurl = "http://www.bing.com" + url;
var copyright = (from i in document.Elements()
where i.Name == "copyright"
select i.Value.ToString()).FirstOrDefault();
var cplink = (from i in document.Elements()
where i.Name == "copyrightlink"
select i.Value.ToString()).FirstOrDefault();
CoppyRightData = copyright + "\r\n" + cplink;
File.WriteAllText(_tempcoppyright, CoppyRightData);
using (var client = new WebClient())
{
client.DownloadFile(imgurl, _tempfilename);
}
}
public Task DownloadAsync()
{
return Task.Run(() =>
{
DownLoad();
});
}
public ImageSource WPFPhotoOfTheDay
{
get
{
if (!_loadcalled)
throw new InvalidOperationException("Call the DownLoad() method first");
return new BitmapImage(new Uri(_tempfilename));
}
}
public Bitmap WFPhotoOfTheDay
{
get
{
if (!_loadcalled)
throw new InvalidOperationException("Call the DownLoad() method first");
return new Bitmap(_tempfilename);
}
}
public string CoppyRightData
{
get;
private set;
}
}
}
Points of Interest
History
- 2015-10-28 Initial release