
/* autopano-sift, Automatic panorama image creation
 * Copyright (C) 2004 -- Sebastian Nowozin
 *
 * This program is free software released under the GNU General Public
 * License, which is included in this software package (doc/LICENSE).
 */

/* GenerateKeys.cs
 *
 * SIFT feature detector keypoint file generator
 *
 * (C) Copyright 2004 -- Sebastian Nowozin (nowozin@cs.tu-berlin.de)
 *
 * "This software is provided for non-commercial use only. The University of
 * British Columbia has applied for a patent on the SIFT algorithm in the
 * United States. Commercial applications of this software may require a
 * license from the University of British Columbia."
 * For more information, see the LICENSE file supplied with the distribution.
 */

#if USING_GTK
using Gtk;
using GtkSharp;
#endif
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;


public class GenerateKeys
{
	public static void Main (string[] args)
	{
#if USING_GTK
		Application.Init ();
#endif

		Console.WriteLine ("SIFT Keypoint Generation\n");

		if (args.Length < 2 || args.Length > 3) {
			Console.WriteLine ("usage: generatekeys.exe image output.key [minDim]\n");

			Console.WriteLine ("image: Image file (any common format: JPEG, PNG, TIFF, ..)");
			Console.WriteLine ("output.key: Output keypoint file");
			Console.WriteLine ("    The output file can be stored in gzip compressed format by appending\n    \".gz\" to the filename.");
			Console.WriteLine ("minDim: (optional) Downscale resolution");
			Console.WriteLine ("    The image is repeatedly halfed in size until both width and height\n    are below 'minDim'.");
			Console.WriteLine ("");

			return;
		}

		// 1. load the image file
		//Console.WriteLine ("opening {0}", args[0]);
		BasicImagingInterface pic = new DisplayImage (args[0]);
		int pW = pic.Width;
		int pH = pic.Height;

		double startScale = 1.0;
		if (args.Length >= 3) {
			int downRes;
			try {
				downRes = Int32.Parse (args[2]);
			} catch (Exception ex) {
				Console.WriteLine ("Downscale resolution \"{0}\" is not valid.\nUse a positive integer.", args[2]);
				return;
			}

			if (downRes > 0) {
				startScale = pic.ScaleWithin (downRes);

				Console.WriteLine ("Scaled picture, starting with scale {0:N4}",
					startScale);
			}
		}
		ImageMap picMap = pic.ConvertToImageMap (null);

		// Ugly hack to save memory. A better way would be to add IDisposable
		// to the DisplayImage class and dispose the Gdk.Pixbuf object there.
		pic = null;
		GC.Collect ();

		// 2. find the features
		LoweFeatureDetector lf = new LoweFeatureDetector ();
		if (args.Length >= 3) {
			lf.DetectFeaturesDownscaled (picMap, 0, 1.0 / startScale);
		} else
			lf.DetectFeatures (picMap);

		Console.WriteLine ("found {0} global keypoints",
			lf.GlobalNaturalKeypoints.Count);

		KeypointXMLWriter.WriteComplete (args[0], pW, pH, args[1],
			lf.GlobalNaturalKeypoints);
	}
}


