Main Page Class Hierarchy Compound List File List Compound Members File Members

ImgView.cc

Go to the documentation of this file.
00001 /*
00002 File: ImgView.cc
00003 
00004 Function: Simple Image Viewer
00005 
00006 Author: Andrew Willmott
00007 
00008 Notes: 
00009 */
00010 
00011  #define GCL_WATCH_FILE
00012 
00013 #include "gcl/XGraphicsSystem.h"
00014 #include "gcl/VecUtil.h"
00015 #include "cl/Timer.h"
00016 
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <unistd.h>
00020 #include "cl/ArgParse.h"
00021 
00022  enum IPCmd 
00023 {
00024 ipNone,
00025 ipReload,
00026 ipNext,
00027 ipPrev
00028 };
00029 
00030  class ImagePane : public XBackedPane
00031 {
00032 public:
00033  ImagePane() : XBackedPane(), command(ipNone), offscreen(0), closed(false)
00034 {};
00035 
00036 Void HandleKey(Char c);
00037 Void PrintKeys();
00038 Void PrintInfo();
00039 Void CheckFile();
00040 Int Load(StrConst filename);
00041 
00042  IPCmd command;
00043  FileName imageFile;
00044  RGBAImage image;
00045  RGBEImage radImage;
00046  Long timeStamp;
00047  Int offWidth, offHeight;
00048  Bool closed;
00049  Bool loaded;
00050  Double alpha;
00051  XOffscreenPane *offscreen;
00052 
00053  static XGraphicsSystem *sXgs;
00054 };
00055 
00056 XGraphicsSystem *ImagePane::sXgs = 0;
00057 
00058  typedef ImagePane *ImagePanePtr;
00059 
00060 // XXX image stuff -- quick hack
00061 
00062  struct ImageStats
00063 {
00064  Double avgLum;
00065  Double avgLogLum;
00066  Double minLum;
00067  Double maxLum;
00068  Colour avgClr;
00069  Colour minClr;
00070  Colour maxClr;
00071  Int numSamples;
00072 };
00073 
00074  Void FindImageStats(Image &img, ImageStats &stats)
00075 { 
00076 Int x, y;
00077 Colour c;
00078 Double lum;
00079 
00080 stats.numSamples = 0;
00081 stats.avgLogLum = 0.0;
00082 stats.avgLum = 0.0;
00083 stats.minLum = vl_inf;
00084 stats.maxLum = -vl_inf;
00085 stats.avgClr.MakeZero();
00086 stats.minClr.MakeBlock(vl_inf);
00087 stats.maxClr.MakeBlock(-vl_inf);
00088 
00089 for (y = 0; y < img.Height(); y++)
00090 for (x = 0; x < img.Width(); x++)
00091 {
00092 c = img.GetPixel(x, y);
00093 lum = dot(cRGBToLum, c);
00094 
00095 if (lum > 0.0)
00096 {
00097 stats.avgClr += c;
00098 stats.avgLum += lum;
00099 stats.avgLogLum += log(lum);
00100 FindMinCmpts(c, stats.minClr, stats.minClr);
00101 FindMaxCmpts(c, stats.maxClr, stats.maxClr);
00102 stats.minLum = Min(lum, stats.minLum);
00103 stats.maxLum = Max(lum, stats.maxLum);
00104 stats.numSamples++;
00105 }
00106 }
00107 
00108 stats.avgLum /= stats.numSamples;
00109 stats.avgLogLum /= stats.numSamples;
00110 stats.avgClr /= stats.numSamples;
00111 }
00112 
00113  Void LinearMapImage(const Image &img, Double start, Double slope, Image &imgOut)
00114 { 
00115 Int x, y;
00116 Colour c, cStart;
00117 
00118 imgOut.SetSize(img.Width(), img.Height());
00119 cStart.MakeBlock(start);
00120 
00121 for (y = 0; y < img.Height(); y++)
00122 for (x = 0; x < img.Width(); x++)
00123 {
00124 c = img.GetPixel(x, y);
00125 c -= cStart;
00126 c *= slope;
00127 imgOut.SetPixel(x, y, ClipColour(c));
00128 }
00129 }
00130 
00131  Void DoToneMap(Image &radImage, Image &image)
00132 {
00133 ImageStats stats;
00134 Double scale, EV;
00135 
00136 FindImageStats(radImage, stats);
00137 
00138 // roughly approximate exposure value for ISO 100 film
00139 EV = stats.avgLogLum / log(2) - 1;
00140 // crop arbitrarily to "sensible" values
00141 EV = Clip(EV, 6.0, 17.0);
00142 // use this to scale irradiances so average level is 0.18,
00143 // a la most light meters
00144 scale = 0.18 * exp(-(EV + 1) * log(2));
00145 LinearMapImage(radImage, 0.0, scale, image);
00146 }
00147 
00148 // ----
00149 
00150  Int ImagePane::Load(StrConst filename)
00151 {
00152 Int err;
00153 Bool justCreated = false;
00154 
00155 loaded = false;
00156 imageFile.SetPath(filename);
00157 
00158 if (imageFile.GetExtension() == "pic")
00159 {
00160 err = radImage.LoadPIC(imageFile.GetPath());
00161 if (!err)
00162 DoToneMap(radImage, image);
00163 }
00164 else
00165 err = image.Load(imageFile);
00166 
00167 if (err != 0)
00168 {
00169 cerr << "image read failed." << endl;
00170 return(err);
00171 }
00172 
00173 if (!xgs)
00174 {
00175 sXgs->CreateWindow(this, imageFile.GetFile(), image.Width(), image.Height());
00176 justCreated = true;
00177 }
00178 
00179 if (!offscreen || image.Width() > offWidth || image.Height() > offHeight)
00180 {
00181 if (offscreen)
00182 delete offscreen;
00183 
00184 offscreen = new XOffscreenPane;
00185 xgs->CreateOffscreen(offscreen, image.Width(), image.Height());
00186 offWidth = image.Width();
00187 offHeight = image.Height();
00188 Attach(offscreen);
00189 }
00190 offscreen->PutImage(image);
00191 
00192 if (!justCreated)
00193 {
00194 SetTitle(imageFile.GetFile());
00195 Resize(image.Width(), image.Height());
00196 }
00197 HandleExpose();
00198 
00199 timeStamp = imageFile.GetTimeStamp();
00200 command = ipNone;
00201 loaded = true;
00202 
00203 return(0);
00204 }
00205 
00206  Void ImagePane::CheckFile()
00207 {
00208 if (loaded && imageFile.GetTimeStamp() > timeStamp)
00209 Load(imageFile.GetPath());
00210 }
00211 
00212  Void ImagePane::HandleKey(Char c)
00213 {
00214 switch (c)
00215 {
00216 case 'h':
00217 case '?':
00218 PrintKeys();
00219 break;
00220 case 'i':
00221 PrintInfo();
00222 break;
00223 case 'd':
00224 {
00225 FileName outFile;
00226 outFile = imageFile;
00227 outFile.SetExtension("tif");
00228 image.Save(outFile);
00229 }
00230 break;
00231 case 'r':
00232 Load(imageFile.GetPath());
00233 break;
00234 case '1':
00235 image.Transform(RGBSaturate(alpha)); 
00236 offscreen->PutImage(image);
00237 HandleExpose();
00238 break;
00239 case '2':
00240 image.Transform(RGBSaturate(2.0 - alpha));
00241 offscreen->PutImage(image);
00242 HandleExpose();
00243 break;
00244 case '3':
00245 image.Transform(RGBHueRotate(alpha));
00246 offscreen->PutImage(image);
00247 HandleExpose();
00248 break;
00249 case '4':
00250 image.Clear(cRed);
00251 offscreen->PutImage(image);
00252 HandleExpose();
00253 break;
00254 case ',':
00255 case 0x1D:
00256 command = ipPrev;
00257 xgs->SignalDone();
00258 break;
00259 case ' ':
00260 case '.':
00261 case 0x1C:
00262 command = ipNext;
00263 xgs->SignalDone();
00264 break;
00265 case 'w':
00266 Hide();
00267 closed = true;
00268 break;
00269 case 'q':
00270 case 0x1B:
00271 closed = true;
00272 xgs->SignalDone();
00273 break;
00274 
00275 default:
00276 XBackedPane::HandleKey(c);
00277 }
00278 }
00279 
00280  Void ImagePane::PrintKeys()
00281 {
00282 cout << "Viewer control:" << endl
00283 << " r - reload image" << endl
00284 << " d - dump tiff image" << endl
00285 << " . or <space> - move on to next image" << endl
00286 << " , - move back to previous image" << endl
00287 << " i - print image information" << endl
00288 << " q or <esc> - quit" << endl
00289 << " w - close window" << endl
00290 << endl;
00291 }
00292 
00293  Void ImagePane::PrintInfo()
00294 {
00295 cout << String().Printf("Image %s is %d x %d", imageFile.GetPath().CString(),
00296 image.Width(), image.Height()) << endl; 
00297 }
00298 
00299  class ImgViewApp
00300 {
00301 public:
00302 ImgViewApp();
00303 
00304 Void SetOptions(Int argc, Char **argv);
00305 Int Run();
00306 
00307 // options
00308 static Void GetFileArgs(Int argc, Char *argv[]);
00309 
00310  static Char **files;
00311  static Int numFiles;
00312  Int noFork;
00313  Int all;
00314 
00315  Double alpha;
00316  Int doSat;
00317 };
00318 
00319 Char **ImgViewApp::files = 0;
00320 Int ImgViewApp::numFiles = 0;
00321 
00322  ImgViewApp::ImgViewApp()
00323 {
00324 }
00325 
00326  Void ImgViewApp::GetFileArgs(Int argc, Char *argv[])
00327 {
00328 files = argv;
00329 numFiles = argc;
00330 }
00331 
00332 Void ImgViewApp::SetOptions(int argc, char **argv)
00333 {
00334 ArgForm *arg_format;
00335 Int formats;
00336 
00337 alpha = 1.0;
00338 
00339 arg_format = arg_to_form(0,
00340 "", 
00341 "Usage: imgview file1 file2 ... [options]",
00342 "", ARG_SUBR(GetFileArgs), 
00343 "",
00344 "-noFork", ARG_FLAG(&noFork),
00345 "Don't fork into background.",
00346 "-all", ARG_FLAG(&all),
00347 "Open all images at once.",
00348 "-alpha %F", &alpha,
00349 "Set alpha for image operation",
00350 "-sat", ARG_FLAG(&doSat),
00351 "Change saturation of the image",
00352 "-formats", ARG_FLAG(&formats), 
00353 "List supported file formats",
00354 0);
00355 
00356 if (argc == 1)
00357 {
00358 arg_form_print(arg_format);
00359 cout << endl;
00360 exit(0);
00361 }
00362 
00363 if (arg_parse_argv(argc, argv, arg_format) < 0)
00364 exit(1);
00365 
00366 #ifdef DEBUG
00367 noFork = true;
00368 #endif
00369 
00370 if (formats)
00371 {
00372 Image::PrintSupportedFormats(cout);
00373 exit(0);
00374 }
00375 }
00376 
00377  Int ImgViewApp::Run()
00378 {
00379 Int i;
00380 
00381 if (numFiles < 1)
00382 return(1);
00383 
00384 if (!noFork && fork())
00385 return(0);
00386 
00387 ImagePane::sXgs = new XGraphicsSystem;
00388 
00389 if (all)
00390 {
00391 ImagePanePtr *panes = new ImagePanePtr[numFiles];
00392 Int closed = 0;
00393 
00394 for (i = 0; i < numFiles; i++)
00395 {
00396 panes[i] = new ImagePane;
00397 panes[i]->alpha = alpha;
00398 panes[i]->Load(files[i]);
00399 }
00400 
00401 while (closed < numFiles)
00402 {
00403 if (ImagePane::sXgs->RunFor(1.0))
00404 break;
00405 for (i = 0; i < numFiles; i++)
00406 if (panes[i])
00407 {
00408 if (panes[i]->closed)
00409 {
00410 delete panes[i];
00411 panes[i] = 0;
00412 closed++;
00413 }
00414 else
00415 panes[i]->CheckFile();
00416 }
00417 }
00418 }
00419 else
00420 {
00421 Int curImage = 0;
00422 ImagePane *imagePane = new ImagePane;
00423 
00424 imagePane->Load(files[0]);
00425 imagePane->alpha = alpha;
00426 
00427 do
00428 {
00429 ImagePane::sXgs->RunFor(1.0);
00430 
00431 imagePane->CheckFile();
00432 
00433 switch (imagePane->command)
00434 {
00435 case ipPrev:
00436 if (curImage > 0)
00437 curImage--;
00438 else
00439 curImage = numFiles - 1;
00440 imagePane->Load(files[curImage]);
00441 break;
00442 case ipNext:
00443 curImage++;
00444 if (curImage == numFiles)
00445 curImage = 0;
00446 imagePane->Load(files[curImage]);
00447 break;
00448 }
00449 }
00450 while (!imagePane->closed);
00451 
00452 delete imagePane;
00453 }
00454 
00455 return(0);
00456 }
00457 
00458  int main(int argc, char **argv)
00459 {
00460 ImgViewApp app;
00461 
00462 app.SetOptions(argc, argv);
00463 
00464 return(app.Run());
00465 }

Generated at Sat Aug 5 00:17:00 2000 for Graphics Class Library by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000

AltStyle によって変換されたページ (->オリジナル) /