00001 /*!@file AppMedia/app-iiv.C Bare-bones image viewer (a minimal replacement for xv) */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppMedia/app-iiv.C $ 00035 // $Id: app-iiv.C 12074 2009-11-24 07:51:51Z itti $ 00036 // 00037 00038 #ifndef APPMEDIA_APP_IIV_C_DEFINED 00039 #define APPMEDIA_APP_IIV_C_DEFINED 00040 00041 #include "GUI/XWinManaged.H" 00042 #include "Image/ColorMap.H" 00043 #include "Image/ColorOps.H" // for colorize() 00044 #include "Image/Image.H" 00045 #include "Image/Pixels.H" 00046 #include "Image/ShapeOps.H" 00047 #include "Raster/GenericFrame.H" 00048 #include "Raster/Raster.H" 00049 #include "Util/log.H" 00050 #include "Util/sformat.H" 00051 #include "rutz/shared_ptr.h" 00052 00053 #include <X11/keysym.h> 00054 #include <iostream> 00055 #include <vector> 00056 #include <cstdio> 00057 00058 namespace 00059 { 00060 void usage(const char* argv0) 00061 { 00062 fprintf(stderr, "USAGE: %s [-d] [-geom WxH] [-w width] [-h height] [-crop l,t,r,b] [-cmapfile filename] imgfile1 [imgfile2 [imgfile3 ...]]\n", argv0); 00063 fprintf(stderr, " or: %s [-d] [-geom WxH] [-w width] [-h height] [-crop l,t,r,b] [-cmapfile filename] [-wait] -stdin-filenames\n", argv0); 00064 exit(1); 00065 } 00066 00067 Image<PixRGB<byte> > doRescale(const GenericFrame& in, 00068 const Rectangle& cropbox, 00069 const Dims& geom, 00070 const ColorMap& cmap) 00071 { 00072 Image<PixRGB<byte> > img = 00073 (cmap.initialized() 00074 && (in.nativeType() == GenericFrame::GRAY_U8 00075 || (in.nativeType() == GenericFrame::VIDEO 00076 && in.asVideo().getMode() == VIDFMT_GREY))) 00077 ? colorize(in.asGrayU8(), cmap) 00078 : in.asRgbU8(); 00079 00080 if (cropbox.isValid()) 00081 img = crop(img, cropbox.getOverlap(img.getBounds())); 00082 00083 const int w = img.getWidth(); 00084 const int h = img.getHeight(); 00085 00086 if (geom.w() != 0 && geom.h() != 0) 00087 return rescale(img, geom); 00088 else if (geom.w() != 0) 00089 return rescale(img, 00090 geom.w(), 00091 int(0.5 + geom.w() * double(h) / double(w))); 00092 else if (geom.h() != 0) 00093 return rescale(img, 00094 int(0.5 + geom.h() * double(w) / double(h)), 00095 geom.h()); 00096 // else ... 00097 return img; 00098 } 00099 } 00100 00101 int main(int argc, char** argv) 00102 { 00103 LOG_FLAGS &= ~LFATAL_PRINTS_ABORT; 00104 LOG_FLAGS &= ~LFATAL_THROWS; 00105 00106 MYLOGVERB = LOG_INFO; 00107 00108 if (argc == 1) 00109 { 00110 usage(argv[0]); 00111 } 00112 00113 std::vector<rutz::shared_ptr<XWinManaged> > windows; 00114 00115 bool wait = false; 00116 bool allowopts = true; 00117 Rectangle cropbox; 00118 Dims geom(0,0); 00119 ColorMap cmap; // empty 00120 00121 for (int i = 1; i < argc; ++i) 00122 { 00123 if (allowopts && strcmp(argv[i], "-d") == 0) 00124 { 00125 MYLOGVERB = LOG_DEBUG; 00126 } 00127 else if (allowopts && strcmp(argv[i], "-crop") == 0) 00128 { 00129 ++i; if (i >= argc) usage(argv[0]); 00130 convertFromString(argv[i], cropbox); 00131 } 00132 else if (allowopts && strcmp(argv[i], "-geom") == 0) 00133 { 00134 ++i; if (i >= argc) usage(argv[0]); 00135 convertFromString(argv[i], geom); 00136 } 00137 else if (allowopts && strcmp(argv[i], "-w") == 0) 00138 { 00139 ++i; if (i >= argc) usage(argv[0]); 00140 geom = Dims(atoi(argv[i]), geom.h()); 00141 } 00142 else if (allowopts && strcmp(argv[i], "-h") == 0) 00143 { 00144 ++i; if (i >= argc) usage(argv[0]); 00145 geom = Dims(geom.w(), atoi(argv[i])); 00146 } 00147 else if (allowopts && strcmp(argv[i], "-cmapfile") == 0) 00148 { 00149 ++i; if (i >= argc) usage(argv[0]); 00150 cmap = Raster::ReadRGB(argv[i]); 00151 } 00152 else if (allowopts && strcmp(argv[i], "-wait") == 0) 00153 { 00154 // whether to wait between images when showing images 00155 // serially, as with -stdin-filenames 00156 wait = true; 00157 } 00158 else if (allowopts && strcmp(argv[i], "--") == 0) 00159 { 00160 allowopts = false; 00161 } 00162 else if (allowopts && strcmp(argv[i], "-stdin-filenames") == 0) 00163 { 00164 std::string line; 00165 while (getline(std::cin, line)) 00166 { 00167 if (line.empty()) 00168 break; 00169 00170 const GenericFrame img = Raster::ReadFrame(line); 00171 const Image<PixRGB<byte> > rescaled = 00172 doRescale(img, cropbox, geom, cmap); 00173 00174 const int w = rescaled.getWidth(); 00175 const int h = rescaled.getHeight(); 00176 const std::string title = sformat("[%dx%d] %s", w, h, line.c_str()); 00177 00178 if (windows.size() == 0) 00179 { 00180 rutz::shared_ptr<XWinManaged> win 00181 (new XWinManaged(rescaled, title.c_str())); 00182 windows.push_back(win); 00183 } 00184 else 00185 { 00186 00187 windows.back()->setDims(rescaled.getDims()); 00188 windows.back()->drawImage(rescaled); 00189 windows.back()->setTitle(title.c_str()); 00190 } 00191 00192 if (wait) 00193 { 00194 fprintf(stderr, "%s\n", line.c_str()); 00195 00196 // wait until the user presses any key in the window 00197 while (windows.back()->getLastKeyPress() == -1) 00198 usleep(10000); 00199 } 00200 } 00201 00202 00203 return 0; 00204 } 00205 else 00206 { 00207 if (!Raster::fileExists(argv[i])) 00208 { 00209 if (allowopts) 00210 fprintf(stderr, "%s is neither a valid option " 00211 "nor a valid image filename\n", argv[i]); 00212 else 00213 fprintf(stderr, "%s is not a valid image filename\n", 00214 argv[i]); 00215 usage(argv[0]); 00216 } 00217 00218 const GenericFrame img = Raster::ReadFrame(argv[i]); 00219 const Image<PixRGB<byte> > rescaled = 00220 doRescale(img, cropbox, geom, cmap); 00221 const int w = rescaled.getWidth(); 00222 const int h = rescaled.getHeight(); 00223 const std::string title = sformat("[%dx%d] %s", w, h, argv[i]); 00224 rutz::shared_ptr<XWinManaged> win 00225 (new XWinManaged(rescaled, title.c_str())); 00226 windows.push_back(win); 00227 } 00228 } 00229 00230 if (windows.size() == 0) 00231 usage(argv[0]); 00232 00233 bool keepgoing = true; 00234 00235 while (keepgoing) 00236 { 00237 for (uint i = 0; i < windows.size(); ++i) 00238 { 00239 if (windows[i]->pressedCloseButton()) 00240 { keepgoing = false; break; } 00241 00242 const KeySym sym = windows[i]->getLastKeySym(); 00243 00244 if (sym == XK_Escape || sym == XK_Q || sym == XK_q) 00245 { keepgoing = false; break; } 00246 } 00247 00248 usleep(10000); 00249 } 00250 00251 return 0; 00252 } 00253 00254 // ###################################################################### 00255 /* So things look consistent in everyone's emacs... */ 00256 /* Local Variables: */ 00257 /* mode: c++ */ 00258 /* indent-tabs-mode: nil */ 00259 /* End: */ 00260 00261 #endif // APPMEDIA_APP_IIV_C_DEFINED