public Image GetImage(int minX, int minY)
        {
            Image image = null;
            while (image == null) {
                try {
                    if (photos == null || index >= photos.PhotoCollection.Length) {
                        if (photos == null || photos.TotalPhotos == 0 || photos.PageNumber >= photos.TotalPages - 1) {
                            page = 0;
                        }
                        else {
                            ++page;
                        }
                        PhotoSearchOptions op = new PhotoSearchOptions();
                        op.SortOrder = PhotoSearchSortOrder.DatePostedDesc;
                        op.Page = page;
                        op.PerPage = 100;
                        if (!String.IsNullOrEmpty(tags))
                            op.Tags = tags;
                        op.TagMode = tagsAndLogic ? TagMode.AllTags : TagMode.AnyTag;
                        if (!String.IsNullOrEmpty(userId))
                            op.UserId = userId;
                        if (!String.IsNullOrEmpty(text))
                            op.Text = text;
                        if (String.IsNullOrEmpty(tags) && String.IsNullOrEmpty(userId) && String.IsNullOrEmpty(text)) {
                            op.MinUploadDate = DateTime.Now - TimeSpan.FromDays(10);
                            op.MaxUploadDate = DateTime.Now - TimeSpan.FromHours(1);
                        }
                        photos = f.PhotosSearch(op);
                        if (photos.TotalPhotos == 0) {
                            if (tagsAndLogic)
                                tagsAndLogic = false;
                            else if (!String.IsNullOrEmpty(tags))
                                tags = null;
                            else if (!String.IsNullOrEmpty(text))
                                text = null;
                            else if (!String.IsNullOrEmpty(userId))
                                userId = null;
                            else
                                throw new ImageSourceFailedException("Flickr search returned no images");
                            continue;
                        }
                        index = 0;
                    }

                    // choose the smallest photo larger than the requested size
                    Photo photo = photos.PhotoCollection[index++];
                    FlickrNet.Size[] sizes = f.PhotosGetSizes(photo.PhotoId).SizeCollection;
                    String url = null;
                    for (int i = sizes.Length - 1; i >= 0; --i) {
                        FlickrNet.Size s = sizes[i];
                        if (!crop && s.Label == "Square")
                            continue;
                        if (s.Width >= minX && s.Height >= minY)
                            url = s.Source;
                    }
                    if (url == null)
                        continue; // nothing large enough

                    image = Image.FromStream(f.DownloadPicture(url));
                }
                catch (Exception ex) {
                    if (++errorCount <= MaxErrorCount) {
                        Log.Instance.Write(string.Format("Failure {0} of {1} loading Flickr photo(s)", errorCount, MaxErrorCount), ex);
                        // try next photo
                    }
                    else {
                        throw new ImageSourceFailedException("Maximum error count reached, failing Flickr image source", ex);
                    }
                }
            }
            errorCount = 0;
            return image;
        }
        void Initialize()
        {
            flowView = new OpenFlowView (UIScreen.MainScreen.Bounds, this);
            View = flowView;

            using (var alertView = new UIAlertView ("OpenFlowSharp Demo Data Source",
                "Would you like to download images from Flickr or use 30 sample images included with this project?",
                null, "Flickr",
                "Samples (all at once)",
                "Samples (using threads)")){
                alertView.Dismissed += delegate(object sender, UIButtonEventArgs e) {
                    switch (e.ButtonIndex){
                    // Flickr
                    case 0:
                        flickr = new Flickr (apiKey, sharedSecret);
                        tasks.Enqueue (delegate {
                            try {
                                Network = true;
                                photos = flickr.InterestingnessGetList ();
                                Network = false;
                                InvokeOnMainThread (delegate {
                                    flowView.NumberOfImages = photos.Count;
                                });
                            } catch {
                                InvokeOnMainThread (delegate {
                                    using (var alert = new UIAlertView ("Error", "While accessing Flickr", null, "Ok")){
                                        alert.Show ();
                                    }
                                });
                            }
                        });
                        break;

                        // Load images on demand on a worker thread
                    case 2:
                        flowView.NumberOfImages = 30;
                        break;

                        // Sync case, load all images at startup
                    case 1:
                        LoadAllImages ();
                        return;
                    }

                    // Start our thread queue system
                    new Thread (Worker).Start ();
                    signal.Set ();
                };
                alertView.Show ();
            }
        }