Click here to Skip to main content
15,884,177 members
Articles / Desktop Programming / Win32

APOD - Get Astronomy Picture of the Day

Rate me:
Please Sign up or sign in to vote.
4.20/5 (3 votes)
16 Sep 2009GPL34 min read 23.2K   445   6  
Retrieving the astronomy picture of the day

wearesnapshot.png

Introduction

I am always amazed with space-related images that NASA shares on a daily basis (see http://antwrp.gsfc.nasa.gov/apod/astropix.html). I am a frequent visitor to that site and it was very common (if not always) to download the images to my computer for later offline visualization (we still don't have an always-on world - at least a cost effective one). Moreover, I frequently had several images I wanted to download (all pictures of a month) and it was a tedious clicking process.

Hence, I developed my own automated software for that!

The software and lessons shared here consist of the following:

  • Perform HTTP requests to APOD website (for a selected date)
  • Retrieve and process HTML code
  • Identify and retrieve JPG images contained in HTML (currently only JPG)
  • Store JPG image in the same directory as the executable. Image is stored as <year><month><day>.jpg

Moreover, I tried to develop a user friendly window. However, only date selection is allowed at present.

Background

No specific background is required, other than basic knowledge of C# (or any other OO language and principles) and Microsoft Visual Studio.

Note that the code is 'quick' - hence short in documentation and cleanness.

Using the Code

The program is simple. The user is currently allowed to select a specific date. Then three commands are currently allowed:

  1. Get image
  2. Get all images from selected month (whose date is earlier than selected date)
  3. Exit

2 is actually an extension of 1, as I will explain later. 1 does the most complicated stuff.

But before I start, we need to understand how information and pages in APOD are structured - in a very simple and intuitive way: 

APOD base URL is:

  • http://antwrp.gsfc.nasa.gov/

The people who run the site are both smart and kind for they provide an extensive archive of pictures (current and past), totally free, which may be accessed as:

  • http://antwrp.gsfc.nasa.gov/apod/ap<2-digit year><2-digit month><2 digit day>.html  

For example, image for year 2009, month 09 and day 09 is accessed through the following URL: 

  • http://antwrp.gsfc.nasa.gov/apod/ap090916.html  

So, having the rule to fetch pages for any given day, it's a matter of starting using nice C#,.NET and HTTP stuff.  

Let's Start !

Actually action starts when a user presses the 'GET !' button. The click event calls the following code:  

C#
private void buttonGET_Click(object sender, EventArgs e)
{ 
    GetAPODImage(dateTimePicker.Value); 
} 

GetAPODimage method does the main work:

First, we generate the URL for the selected date, following the rule explained above:

C#
string url = GenerateAPOD_URL("http://antwrp.gsfc.nasa.gov/apod/ap",date);

This method builds the URL as follows:

C#
private string GenerateAPOD_URL(string rootURL, System.DateTime date)
{
    return rootURL
            + Get2DigitYear(date)
            + Get2DigitNumberAsString(date.Month)
            + Get2DigitNumberAsString(date.Day)
            + ".html";
}

Note that Get2DigitNumberAsString returns a two digit string. For example, if selected day is 1, it returns ‘01’.

Next, we are going to retrieve the HTML-page:

C#
GetHTTP(url,5000,ref resultHTML); 

GetHTTP method will fetch the HTML page from ‘url’ and store it to ‘resultHTML’. Note that we pass ‘5000’ (i.e., 5 seconds) which indicates the timeout period to wait to fetch the page – this is very important to prevent the possibility to wait a long time for a page. 

GetHTTP code is as follows: 

C#
// create HTTP request
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Timeout = timeout;
req.ReadWriteTimeout = timeout;

// get response
WebResponse resp = req.GetResponse();

// we will read data via the response stream
Stream resStream = resp.GetResponseStream();

int    count      = 0;
byte[] buf = new byte[8192];

resultHTML = "";

do
{
    // fill the buffer with data
    count = resStream.Read(buf, 0, buf.Length);

    // make sure we read some data
    if (count != 0)
    {
        // translate from bytes to ASCII text
        resultHTML += Encoding.ASCII.GetString(buf, 0, count);
    }
}
while (count > 0); // any more data to read
    resp.Close(); 

Straightforward. OK – now, if no exceptions were raised, we must parse ‘resultHTML’ and look for ‘JPGs’ (which are the nice pictures we wish to download): 

C#
GetHTTPFilesByTypeSuffix(resultHTML, ‘.JPG’, ref list); 

I will not go into excessive details in this function, except that work performed is to look for ‘href=’ and fetch the referenced file. It will only consider it valid if it is a ‘.JPG’.
For example: if var ‘resultHTML’ contains “<a href="image/0909/tarantula_gleason.jpg">”, image/0909/tarantula_gleason.jpg will be added to the list (var 'list'). 

Now that we have the image files, we should download and store them on disk (look at the code in bold): 

C#
try 
{
    ....
    //get and save images 
    foreach (string file in list) 
    {
        String source = "http://antwrp.gsfc.nasa.gov/apod/"+file;
        string dest = GetYYYYMMDD(date)+’.JPG’;
        WebClient Client = new WebClient();
        Client.DownloadFile(source, dest); 
        pictureBox.Image = Image.FromFile(dest);
    }

}//end try
catch (Exception ex)
{
    Console.WriteLine("An exception occurred: " + ex.Message);
    pictureBox.Image = Properties.Resources.g_close;
}

Note that:

  • After the picture is stored, I show it in pictureBox (in the main window)
  • If an error occurs, pictureBox shows an error image

Finally, how do you fetch all images for a selected month (which are earlier than the selected date)? Very simple:

C#
private void buttonGETMONTH_Click(object sender, EventArgs e)
{ 
    DateTime date = dateTimePicker.Value;
    for (int i = 1; date.Month == dateTimePicker.Value.Month; i++ )
    {
        GetAPODImage(date);
        date = dateTimePicker.Value.AddDays(-i);
    }
}

The trick is to initialize temporary variable date to selected date and then decrease n-days until the month is changed. 

That’s it ! I hope you enjoyed the article.

Final Remarks

You may download the win32 binary and run it directly (you need .NET 3.5 Framework). If you open the solution, you'll note a dependency on WeAreUtils (which is also included). This library actually has several of the utilities referred in the article. However, I decided to present a simplified version to make it easier to understand.

If you liked the software, you may find it at SourceForge (http://sourceforge.net/projects/weareapod/)!  Join the project!

History

  • 16th September, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Technical Lead
Portugal Portugal
He is the Head of R&D in a Portuguese IT Company operating in Space and Security markets.
His responsibilities include team coordination, project management and system conceptualization. He also works in close partnership with Universities and R&D Centres, promoting joint activities, common projects and transfer of knowledge and technology.
He actively cooperates in international study and advisory groups of engineers and scientists.
He is graduated in Electronics and Computer Sciences by a Portuguese University and is post-graduated in Information Warfare/Competitive Intelligence.
In his free time, he enjoys lauching new endeavors and challenges.

Comments and Discussions

 
-- There are no messages in this forum --