Introduction
Flickr is a very popular web 2.0 social image sharing website. Each picture has a description and a certain amount of tags. It's fun to search on a specific tag and see what images are showing up. Tickr for Mac OS X was the first to create a slideshow based on given keywords.
Shortly after Tickr, there was Slickr, a Windows client that did the same. There is also a OpenGL screensaver and a AJAX plugin for Wordpress named also Slickr.
Now I want to show the beginning web 2.0 developer or mashup creator how easy it is to create such an application with .NET. We leave out the on-desktop sliding feature from Tickr and Slickr, to create a simple and reusable piece of code.
Using the Code
We create a TextBox
, Button
, PictureBox
and a StatusStrip
on the form. Then we initialize a thread and a delegate as member variables of the form. The delegate is used in the thread to safely update the picturebox
.
private Thread workerThread = null;
private delegate void SetPictureHandler(string URL);
When the button is clicked, we gently start the thread.
If it was already running, we interrupt that one and start a new one.
private void searchButton_Click(object sender, EventArgs e)
{
if (workerThread != null)
{
workerThread.Interrupt();
workerThread = null;
}
workerThread = new Thread(new ThreadStart(DoWork));
workerThread.Start();
}
The real work is done inside the thread's function. We use a HttpWebRequest
to get the flickr webpage with the given keyword(s) in the textbox. The HttpWebResponse
gives us the server response. We store the response in the variable html
and use Regular Expressions to filter out the content we need.
We filter out all images by using the Regular Expression Pattern
<img(.*)/>
. The problem now is that we also get the buddyicons, the main flickr logo and other useless images. We can filter out the usable images by checking if the current URL of the image contains
farm (which is the server where flickr stores images) and doesn't contain
buddyicons (all buddy icons contain this string).
We get each image apart by using the GetImage
function which actually uses HttpWebRequest
and HttpWebResponse
again to create an image from the data stream. The image is set thread-safely using the SetImage
function.
We also extract the alt
-tag of the image URL, because this gives us the description of the current image. Each image is then shown for 3 seconds and afterwards the next image is extracted.
private void DoWork()
{
try
{
SetStatus("Fetching images...");
HttpWebRequest hwreq = (HttpWebRequest)WebRequest.Create
("http://www.flickr.com/search/?q=" + txtSearch.Text);
HttpWebResponse hwres = (HttpWebResponse)hwreq.GetResponse();
StreamReader sr = new StreamReader(hwres.GetResponseStream());
String html = sr.ReadToEnd();
String pattern = @"<img(.*)/>";
MatchCollection matches = Regex.Matches(html, pattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture |
RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);
foreach (Match match in matches)
{
String result = match.ToString();
if (result.Contains("farm") && !result.Contains("buddyicons"))
{
String URLPattern = @"http://(.*)jpg";
MatchCollection URLMatches = Regex.Matches(result, URLPattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture |
RegexOptions.IgnorePatternWhitespace);
foreach (Match URLMatch in URLMatches)
{
SetImage(URLMatch.ToString());
String AltPattern = @"alt=(.*)/";
MatchCollection AltMatches = Regex.Matches(result, AltPattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture |
RegexOptions.IgnorePatternWhitespace);
foreach (Match AltMatch in AltMatches)
{
SetStatus(AltMatch.ToString().Replace("alt=", "").Replace
("\"", "").Replace("/", ""));
}
Thread.Sleep(3000);
}
}
}
hwreq = null;
sr.Close();
hwres.Close();
}
catch (Exception ex)
{
}
}
The code for GetImage
routine:
private Image GetImage(string sURL)
{
Stream str = null;
HttpWebRequest wReq = (HttpWebRequest)WebRequest.Create(sURL);
HttpWebResponse wRes = (HttpWebResponse)(wReq).GetResponse();
str = wRes.GetResponseStream();
return Image.FromStream(str);
}
The code for the thread-safety function SetImage
goes like this:
private void SetImage(string URL)
{
if (this.pictureBox1.InvokeRequired)
{
SetPictureHandler d = new SetPictureHandler(SetImage);
pictureBox1.Invoke(d, new object[] { URL });
}
else
{
pictureBox1.Image = GetImage(URL);
}
}
The toolStripStatusLabel
can be set directly:
private void SetStatus(string text)
{
this.toolStripStatusLabel1.Text = text;
}
History
- 06/09/2007: Version 1.0, initial writing
About KristofLeroux
Kristof Leroux is a Master of Science in Informatics, option Artificial Intelligence.
He owns his own software development company Laranea which is specialized in software development using game AI, neural networks, genetic algorithms and machine learning. Another important branch is mobile development. At the moment, he is very active in the web 2.0 scene and with his research about artificial creativity.