contrib/oul/ouml/image_database.cxx
Go to the documentation of this file.
00001 //:
00002 // \file
00003 //
00004 // An image database. Basically maintains a list of labels and
00005 // associated images. And allows for saving and loading a database.
00006 // Ideally, this would form an inheritance hierarchy or be a templated
00007 // class, but I'm looking for simplicity at the moment.
00008 //
00009 // The images inserted into the database WILL be deleted on
00010 // destruction of the database. So only insert things you don't want
00011 // to persist.
00012 //
00013 // \author Brendan McCane
00014 // \date 17 July 2001
00015 //
00016 // Copyright (c) 2001 Brendan McCane
00017 // University of Otago, Dunedin, New Zealand
00018 // Reproduction rights limited as described in the COPYRIGHT file.
00019 //----------------------------------------------------------------------
00020 
00021 #include "image_database.h"
00022 #include <vcl_iostream.h>
00023 #include <vcl_cerrno.h> // for EEXIST
00024 #include <vcl_cctype.h> // for tolower()
00025 #include <vcl_cstdio.h> // for fscanf()
00026 #include <vcl_algorithm.h> // for transform()
00027 #include <vpl/vpl.h> // for vpl_mkdir
00028 #include <vil1/vil1_load.h>
00029 #include <vil1/vil1_save.h>
00030 
00031 //----------------------------------------------------------------------
00032 //: destructor
00033 //
00034 // Iterate through all images in the database and delete them.
00035 //
00036 // \remark Memory is actually deallocated
00037 //
00038 // \author Brendan McCane
00039 //----------------------------------------------------------------------
00040 
00041 ImageDatabase::~ImageDatabase()
00042 {
00043   clear();
00044 }
00045 
00046 //----------------------------------------------------------------------
00047 //: clear
00048 //
00049 // clear all the images from the database (deletion is performed)
00050 //
00051 // \author Brendan McCane
00052 //----------------------------------------------------------------------
00053 void ImageDatabase::clear()
00054 {
00055   for (iterator i=begin(); i!=end(); i++)
00056   {
00057     delete (*i).second;
00058   }
00059   image_db.clear();
00060 }
00061 
00062 //----------------------------------------------------------------------
00063 //: save
00064 //
00065 // Save all images in the database. To do this, I create a single
00066 // database file that has a list of label/filename pairs. I also
00067 // create a subdirectory in which all the images are stored. The
00068 // images are stored based on the imagetype parameter, which should be
00069 // the extension of a valid image file type (eg "ppm", "pgm", "png",
00070 // etc).
00071 //
00072 // \param name  the name of the database file (a directory called name.d is also created).
00073 //
00074 // \param imagetype  a valid file extension type (eg "ppm");
00075 //
00076 // \author Brendan McCane
00077 //----------------------------------------------------------------------
00078 
00079 bool ImageDatabase::save(const char *name, const char *imagetype)
00080 {
00081   char dirname[200];
00082   vcl_sprintf(dirname, "%s.d", name);
00083 
00084   int err;
00085 
00086   err = vpl_mkdir( dirname, 0755 );
00087   if (err != 0 && err != EEXIST)
00088   {
00089     vcl_cerr << "can't open directory " << dirname << vcl_endl;
00090     return false;
00091   }
00092 
00093   // now open the database file
00094   FILE *dbfile;
00095   if (!(dbfile=vcl_fopen(name, "w")))
00096   {
00097     vcl_cerr << "Can't open database file " << name << vcl_endl;
00098     return false;
00099   }
00100 
00101   int index=0;
00102   for (iterator i=begin(); i!=end(); i++)
00103   {
00104     char filename[200];
00105     vcl_sprintf(filename, "%s/%s_%03d.%s", dirname, (*i).first, index++, imagetype);
00106     vil1_save(*((*i).second), filename);
00107 
00108     vcl_printf("db: %s %s\n", (*i).first, filename);
00109     vcl_fprintf(dbfile, "%s %s\n", (*i).first, filename);
00110   }
00111   vcl_fclose(dbfile);
00112   return true;
00113 }
00114 
00115 
00116 //----------------------------------------------------------------------
00117 //: load
00118 //
00119 // Load a database from file.
00120 //
00121 // \param name  the name of the database file (a directory called name.d should also exist).
00122 //
00123 // \author Brendan McCane
00124 //----------------------------------------------------------------------
00125 
00126 bool ImageDatabase::load(const char *name)
00127 {
00128   // now open the database file
00129   FILE *db;
00130   if (!(db=vcl_fopen(name, "r")))
00131   {
00132     vcl_cerr << "Can't open database file " << name << vcl_endl;
00133     return false;
00134   }
00135 
00136   char label[200], filename[200];
00137   while (vcl_fscanf(db, "%s%s", label, filename)!=EOF)
00138   {
00139     vil1_image im = vil1_load(filename);
00140     if (!im) return false;
00141     vil1_memory_image *image = new vil1_memory_image(im);
00142     insert(label, image);
00143   }
00144   vcl_fclose(db);
00145   return true;
00146 }
00147 
00148 bool ImageDatabase::ltstr::operator()(const char* s1, const char* s2) const
00149 {
00150   // do a case insensitive comparison. Can't use strcasecmp
00151   // because it's not standard.
00152   vcl_string tmp1( s1 );
00153   vcl_string tmp2( s2 );
00154   vcl_transform( tmp1.begin(), tmp1.end(), tmp1.begin(), ::tolower );
00155   vcl_transform( tmp2.begin(), tmp2.end(), tmp2.begin(), ::tolower );
00156   return vcl_strcmp( tmp1.c_str(), tmp2.c_str() ) < 0;
00157 }