2022-04-07 18:46:57 +02:00

1064 lines
30 KiB
C++

///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// exrdisplay -- a simple program to display Imf::Rgba multipart
// and deep images
// -- exrdisplay Window Mouse Control:
// LMB = Display a sample chart and print out values
// RMB = If it's a deep image, open a Deep 3D Window
// -- Deep 3D Window Mouse Control:
// LMB = Rotate
// RMB = Zoom
// MMB = Move
// -- Deep 3D Window Control Keys:
// a = scale z value up
// s = scale z value down
// f = reset to fit
// d = decrease pixel samples
// c = increase pixel samples
//
//-----------------------------------------------------------------------------
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Value_Slider.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_Output.H>
#include <ImfArray.h>
#include <ImfThreading.h>
#include <ImfMultiPartInputFile.h>
#include <ImathLimits.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <exception>
#include <string.h>
#include <stdlib.h>
#include "loadImage.h"
#include "scaleImage.h"
#include "applyCtl.h"
#include "ImageView.h"
#include "namespaceAlias.h"
using namespace IMF;
using namespace IMATH;
using namespace std;
struct MainWindow
{
Fl_Window * window;
Fl_Choice * multipartMenu;
Fl_Output * typeLabel;
Fl_Output * nameLabel;
Fl_Box * exposureLabel;
Fl_Value_Slider * exposureSlider;
Fl_Box * defogLabel;
Fl_Value_Slider * defogSlider;
Fl_Box * kneeLowLabel;
Fl_Value_Slider * kneeLowSlider;
Fl_Box * kneeHighLabel;
Fl_Value_Slider * kneeHighSlider;
Fl_Box * rgbaBox;
ImageView * image;
Array<Rgba> pixels;
Array<float*> dataZ;
Array<unsigned int> sampleCount;
const char* imageFile;
bool preview;
int lx;
int ly;
const char* channel;
const char* layer;
bool swap;
float farPlane;
bool deepComp;
static void multipartComboboxCallback (Fl_Widget *widget, void *data);
static void exposureSliderCallback (Fl_Widget *widget, void *data);
static void defogSliderCallback (Fl_Widget *widget, void *data);
static void kneeLowSliderCallback (Fl_Widget *widget, void *data);
static void kneeHighSliderCallback (Fl_Widget *widget, void *data);
};
void
MainWindow::multipartComboboxCallback (Fl_Widget *widget, void *data)
{
MainWindow *mainWindow = (MainWindow *) data;
int partnum = mainWindow->multipartMenu->value();
mainWindow->image->clearDataDisplay();
//
// reload pixels
//
Header header;
int zsize;
loadImage (mainWindow->imageFile,
mainWindow->channel,
mainWindow->layer,
mainWindow->preview,
mainWindow->lx,
mainWindow->ly,
partnum,
zsize,
header,
mainWindow->pixels,
mainWindow->dataZ,
mainWindow->sampleCount,
mainWindow->deepComp);
const Box2i &displayWindow = header.displayWindow();
const Box2i &dataWindow = header.dataWindow();
int dw = dataWindow.max.x - dataWindow.min.x + 1;
int dh = dataWindow.max.y - dataWindow.min.y + 1;
int dx = dataWindow.min.x - displayWindow.min.x;
int dy = dataWindow.min.y - displayWindow.min.y;
if (mainWindow->swap)
swapPixels (dw, dh, mainWindow->pixels);
if(mainWindow->preview)
{
int w = mainWindow->window->w();
int iw = displayWindow.max.x - displayWindow.min.x;
int ih = displayWindow.max.y - displayWindow.min.y;
mainWindow->window->size (w, (160 + ih));
mainWindow->image->resize ((w - iw) / 2, 155, iw, ih);
}
mainWindow->image->setPixels (mainWindow->pixels,
mainWindow->dataZ,
mainWindow->sampleCount,
zsize,
dw,dh,dx,dy);
//
// renew multipart data type
//
string type = "";
try{
type = header.type();
}
catch(IEX_NAMESPACE::BaseExc &e) {
type = "";
}
mainWindow->typeLabel->value(type.c_str());
//
// renew multipart part name
//
string name = "";
try{
name = header.name();
}
catch(IEX_NAMESPACE::BaseExc &e) {
name = "";
}
mainWindow->nameLabel->value(name.c_str());
}
void
MainWindow::exposureSliderCallback (Fl_Widget *widget, void *data)
{
MainWindow *mainWindow = (MainWindow *) data;
mainWindow->image->setExposure (mainWindow->exposureSlider->value());
}
void
MainWindow::defogSliderCallback (Fl_Widget *widget, void *data)
{
MainWindow *mainWindow = (MainWindow *) data;
mainWindow->image->setDefog (mainWindow->defogSlider->value());
}
void
MainWindow::kneeLowSliderCallback (Fl_Widget *widget, void *data)
{
MainWindow *mainWindow = (MainWindow *) data;
mainWindow->image->setKneeLow (mainWindow->kneeLowSlider->value());
}
void
MainWindow::kneeHighSliderCallback (Fl_Widget *widget, void *data)
{
MainWindow *mainWindow = (MainWindow *) data;
mainWindow->image->setKneeHigh (mainWindow->kneeHighSlider->value());
}
MainWindow *
makeMainWindow (const char imageFile[],
const char channel[],
const char layer[],
bool preview,
int lx,
int ly,
float farPlane,
bool noDisplayWindow,
bool noAspect,
bool zeroOneExposure,
bool normalize,
bool swap,
bool continuousUpdate,
const vector<string> &transformNames,
bool useCtl,
bool deepComp)
{
MainWindow *mainWindow = new MainWindow;
mainWindow->imageFile = imageFile;
mainWindow->preview = preview;
mainWindow->lx = lx;
mainWindow->ly = ly;
mainWindow->farPlane = farPlane;
mainWindow->channel = channel;
mainWindow->layer = layer;
mainWindow->swap = swap;
mainWindow->deepComp = deepComp;
//
// Read the image file.
//
int numparts = 0;
try
{
MultiPartInputFile *infile = new MultiPartInputFile(imageFile);
numparts = infile->parts();
delete infile;
}
catch(IEX_NAMESPACE::BaseExc &e)
{
cerr<<"\n"<<"ERROR:"<<endl;
cerr<<e.what()<<endl;
exit(1);
}
Header header;
int zsize;
//
//pass 0 as partnum for the first load
//
loadImage (imageFile,
channel,
layer,
preview,
lx, ly,
0,
zsize,
header,
mainWindow->pixels,
mainWindow->dataZ,
mainWindow->sampleCount,
mainWindow->deepComp);
const Box2i &displayWindow = header.displayWindow();
const Box2i &dataWindow = header.dataWindow();
float pixelAspectRatio = header.pixelAspectRatio();
int w = displayWindow.max.x - displayWindow.min.x + 1;
int h = displayWindow.max.y - displayWindow.min.y + 1;
int dw = dataWindow.max.x - dataWindow.min.x + 1;
int dh = dataWindow.max.y - dataWindow.min.y + 1;
int dx = dataWindow.min.x - displayWindow.min.x;
int dy = dataWindow.min.y - displayWindow.min.y;
if (noDisplayWindow)
{
w = dw;
h = dh;
dx = 0;
dy = 0;
}
if (noAspect)
{
pixelAspectRatio = 1;
}
//
// Normalize the pixel data if necessary.
//
if (normalize)
normalizePixels (dw, dh, mainWindow->pixels);
//
// If necessary, swap the top and bottom half and then the
// left and right half of the image.
//
if (swap)
swapPixels (dw, dh, mainWindow->pixels);
//
// Stretch the image horizontally or vertically to make the
// pixels square (assuming that we are going to display the
// image on a screen with square pixels).
//
if (pixelAspectRatio > 1)
scaleX (pixelAspectRatio, w, h, dw, dh, dx, dy, mainWindow->pixels);
else
scaleY (1 / pixelAspectRatio, w, h, dw, dh, dx, dy, mainWindow->pixels);
//
// Apply CTL transforms if requested.
//
// If we don't apply CTL transforms and we have loaded more than
// one image channel, then transform the pixels from the RGB space
// of the input file to into the RGB space of the display.
//
#if HAVE_CTL_INTERPRETER
if (useCtl)
{
applyCtl (transformNames,
header,
mainWindow->pixels,
dw, dh,
mainWindow->pixels);
}
else
#endif
if (!channel)
{
adjustChromaticities (header,
mainWindow->pixels,
dw, dh,
mainWindow->pixels);
}
//
// Build main window
//
int mw = max (500, w); // main window width
int vy = 0; // offset of image view from top of main window
float exposure = 0;
float defog = 0;
float kneeLow = 0;
float kneeHigh = 0;
#if HAVE_CTL_INTERPRETER
if (useCtl)
{
//
// Colors on the screeen are computed by CTL.
// No exposure defog and knee sliders are displayed.
//
mainWindow->window =
new Fl_Window (mw + 10, h + 35, imageFile);
//
// Add RGB value display
//
mainWindow->rgbaBox = new Fl_Box (80, 5, mw - 65, 20, "");
mainWindow->rgbaBox->align (FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
//
// Image view is below RGB value display
//
vy = 30;
//
// Map floating-point pixel values 0.0 and 1.0
// to the display's white and black respectively.
//
exposure = 1.02607;
defog = 0;
kneeLow = 0.0;
kneeHigh = 3.5;
}
else
#endif
{
mainWindow->window =
new Fl_Window (mw + 10, h + 160, imageFile);
//
// Add multipart combobox
//
mainWindow->multipartMenu =
new Fl_Choice (70, 5, 80, 20, "multipart");
for(int i=0; i<numparts; i++){
string displaynum;
ostringstream s;
s << i;
mainWindow->multipartMenu->add(s.str().c_str());
}
mainWindow->multipartMenu->value(0);
mainWindow->multipartMenu->callback
(MainWindow::multipartComboboxCallback, mainWindow);
if(numparts==1)
mainWindow->multipartMenu->deactivate();
else{
//
// Add type label
//
string type = "";
try{
type = header.type();
}
catch(IEX_NAMESPACE::BaseExc &e) {
type = "";
}
mainWindow->typeLabel =
new Fl_Output (190, 5, 110, 20, "type");
mainWindow->typeLabel->value(type.c_str());
//
// Add name label
//
string name = "";
try{
name = header.name();
}
catch(IEX_NAMESPACE::BaseExc &e) {
name = "";
}
mainWindow->nameLabel =
new Fl_Output (350, 5, 155, 20, "name");
mainWindow->nameLabel->value(name.c_str());
}
//
// Add exposure slider
//
mainWindow->exposureLabel =
new Fl_Box (5, 30, 60, 20, "exposure");
mainWindow->exposureSlider =
new Fl_Value_Slider (70, 30, mw - 65, 20, "");
enum Fl_When when = continuousUpdate?
FL_WHEN_CHANGED : FL_WHEN_RELEASE;
mainWindow->exposureSlider->type (FL_HORIZONTAL);
mainWindow->exposureSlider->range (-10.0, +10.0);
mainWindow->exposureSlider->step (1, 8);
exposure = zeroOneExposure? 1.02607: 0.0;
mainWindow->exposureSlider->value (exposure);
mainWindow->exposureSlider->when (when);
mainWindow->exposureSlider->callback
(MainWindow::exposureSliderCallback, mainWindow);
//
// Add defog slider
//
mainWindow->defogLabel =
new Fl_Box (5, 55, 60, 20, "defog");
mainWindow->defogSlider =
new Fl_Value_Slider (70, 55, mw - 65, 20, "");
mainWindow->defogSlider->type (FL_HORIZONTAL);
mainWindow->defogSlider->range (0.0, 0.01);
mainWindow->defogSlider->step (1, 10000);
defog = 0.0;
mainWindow->defogSlider->value (defog);
mainWindow->defogSlider->when (when);
mainWindow->defogSlider->callback
(MainWindow::defogSliderCallback, mainWindow);
//
// Add kneeLow slider
//
mainWindow->kneeLowLabel =
new Fl_Box (5, 80, 60, 20, "knee low");
mainWindow->kneeLowSlider =
new Fl_Value_Slider (70, 80, mw - 65, 20, "");
mainWindow->kneeLowSlider->type (FL_HORIZONTAL);
mainWindow->kneeLowSlider->range (-3.0, 3.0);
mainWindow->kneeLowSlider->step (1, 8);
kneeLow = 0.0;
mainWindow->kneeLowSlider->value (kneeLow);
mainWindow->kneeLowSlider->when (when);
mainWindow->kneeLowSlider->callback
(MainWindow::kneeLowSliderCallback, mainWindow);
//
// Add kneeHigh slider
//
mainWindow->kneeHighLabel =
new Fl_Box (5, 105, 60, 20, "knee high");
mainWindow->kneeHighSlider =
new Fl_Value_Slider (70, 105, mw - 65, 20, "");
mainWindow->kneeHighSlider->type (FL_HORIZONTAL);
mainWindow->kneeHighSlider->range (3.5, 7.5);
mainWindow->kneeHighSlider->step (1, 8);
kneeHigh = (preview | zeroOneExposure)? 3.5: 5.0;
mainWindow->kneeHighSlider->value (kneeHigh);
mainWindow->kneeHighSlider->when (when);
mainWindow->kneeHighSlider->callback
(MainWindow::kneeHighSliderCallback, mainWindow);
//
// Add RGB value display
//
mainWindow->rgbaBox = new Fl_Box (80, 130, mw - 65, 20, "");
mainWindow->rgbaBox->align (FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
//
// Image view is below RGB value display
//
vy = 155;
}
//
// Add image view:
//
// w, h width and height of the display window
//
// dw, dh width and height of the data window
//
// dx, dy offset of the data window's upper left
// corner from the display window's upper
// left corner
//
mainWindow->image =
new ImageView (5 + (mw - w) / 2, vy,
w, h,
"",
mainWindow->pixels,
mainWindow->dataZ,
mainWindow->sampleCount,
zsize,
dw, dh,
dx, dy,
mainWindow->rgbaBox,
mainWindow->farPlane,
displayVideoGamma(),
exposure,
defog,
kneeLow,
kneeHigh);
mainWindow->image->box (FL_ENGRAVED_BOX);
mainWindow->window->end();
return mainWindow;
}
void
usageMessage (const char argv0[], bool verbose = false)
{
cerr << "usage: " << argv0 << " [options] imagefile" << endl;
if (verbose)
{
cerr << "\n"
"Displays an OpenEXR image on the screen.\n"
"\n"
"Options:\n"
"\n"
"-p displays the preview (thumbnail)\n"
" image instead of the main image\n"
"\n"
"-L x displays layer x of a multilayer image\n"
"\n"
"-l lx ly displays level (lx,ly) of a tiled\n"
" multiresolution image\n"
"\n"
"-w displays all pixels in the data window,\n"
" ignoring the display window\n"
"\n"
"-a ignores the image's pixel aspect ratio,\n"
" and does not scale the image to make\n"
" the pixels square\n"
"\n"
"-c x loads only image channel x\n"
"\n"
"-1 sets exposure and knee sliders so that pixel\n"
" value 0.0 becomes black, and 1.0 becomes white\n"
"\n"
"-n normalizes the pixels so that the smallest\n"
" value becomes 0.0 and the largest value\n"
" becomes 1.0\n"
"\n"
"-A same as -c A -1 (displays alpha)\n"
"\n"
"-Z same as -c Z -n (displays depth)\n"
"\n"
"-s swaps the image's top and bottom half, then\n"
" swaps the left and right half, so that the\n"
" four corners of the image end up in the center.\n"
" (Useful for checking the seams of wrap-around\n"
" texture map images.)\n"
#if HAVE_CTL_INTERPRETER
"\n"
"-C s CTL transform s is applied to the image before\n"
" it is displayed. Option -C can be specified\n"
" multiple times to apply a series of transforms\n"
" to the image. The transforms are applied in the\n"
" order in which they appear on the command line.\n"
"\n"
"-T do not apply CTL transforms to the image; enable\n"
" interactive exposure and knee controls instead\n"
"\n"
"-u changing the exposure and knee controls\n"
" continuously updates the on-screen image\n"
" (the controls are enabled only when no CTL\n"
" transforms have been applied to the image)\n"
"\n"
"-t n use n parallel threads to read the image file\n"
" and to run the CTL transforms\n"
#else
"\n"
"-u changing the exposure and knee controls\n"
" continuously updates the on-screen image\n"
"\n"
"-t n use n parallel threads to read the image file\n"
#endif
"\n"
"-h prints this message\n"
#if HAVE_CTL_INTERPRETER
"\n"
"CTL transforms:\n"
"\n"
" CTL transforms are applied to the image unless\n"
" one of the following options is specified on the\n"
" command line: -c, -1, -n, -A, -Z, -T\n"
"\n"
" If one or more CTL transforms are specified on\n"
" the command line (using the -C flag), then those\n"
" transforms are applied to the image.\n"
" If no CTL transforms are specified on the command\n"
" line then an optional look modification transform\n"
" is applied, followed by a rendering transform and\n"
" a display transform.\n"
" The name of the look modication transform is taken\n"
" from the lookModTransform attribute in the header\n"
" of the image file. If the header contains no such\n"
" attribute, then no look modication transform is\n"
" applied. The name of the rendering transform is\n"
" taken from the renderingTransform attribute in the\n"
" header of the image file. If the header contains\n"
" no such attribute, then the name of the rendering\n"
" transform is \"transform_RRT.\" The name of the\n"
" display transform is taken from the environment\n"
" variable CTL_DISPLAY_TRANSFORM. If this environment\n"
" variable is not set, then the name of the display\n"
" transform is \"transform_display_video.\"\n"
" The files that contain the CTL code for the\n"
" transforms are located using the CTL_MODULE_PATH\n"
" environment variable.\n"
#endif
"\n"
"Deep Data Options:\n"
"\n"
"-farPlane(f) f OpenGL zFar clipping plane\n"
"-noDeepComp(d) Disable the compositing of deep images (def=ON)\n"
"\n"
"Exrdisplay Window Mouse Control:\n"
" LMB = Display a sample chart and print out values\n"
" RMB = If it's a deep image, open a Deep 3D Window\n"
"Deep 3D Window Mouse Control:\n"
" LMB = Rotate\n"
" RMB = Zoom\n"
" MMB = Move\n"
"Deep 3D Window Control Keys:\n"
" a = scale z value up\n"
" s = scale z value down\n"
" f = reset to fit\n"
" d = decrease pixel samples\n"
" c = increase pixel samples\n"
"\n";
cerr << endl;
}
exit (1);
}
void window_callback(Fl_Widget*, void*)
{
exit(0);
}
int
main(int argc, char **argv)
{
const char *imageFile = 0;
const char *channel = 0;
const char *layer = 0;
bool preview = false;
bool noDisplayWindow = false;
bool noAspect = false;
bool zeroOneExposure = false;
bool normalize = false;
bool swap = false;
bool continuousUpdate = false;
vector<string> transformNames;
bool useCtl = true;
int numThreads = 0;
int lx = -1;
int ly = -1;
float farPlane = limits<float>::max(); //default value of zfar plane
bool deepComp = true; // attempt to composite deep images together
//
// Parse the command line.
//
if (argc < 2)
usageMessage (argv[0], true);
int i = 1;
while (i < argc)
{
if (!strcmp (argv[i], "-p"))
{
//
// Show the preview image
//
preview = true;
i += 1;
}
else if (!strcmp (argv[i], "-L"))
{
//
// Assume that the image file has multiple
// layers, and show the specified layer.
//
if (i > argc - 2)
usageMessage (argv[0]);
layer = argv[i + 1];
i += 2;
}
else if (!strcmp (argv[i], "-l"))
{
//
// Assume that the image file is tiled,
// and show level (lx,ly) of the tiled image
//
if (i > argc - 3)
usageMessage (argv[0]);
lx = strtol (argv[i + 1], 0, 0);
ly = strtol (argv[i + 2], 0, 0);
i += 3;
}
else if (!strcmp (argv[i], "-w"))
{
//
// Ignore the file's display window
//
noDisplayWindow = true;
i += 1;
}
else if (!strcmp (argv[i], "-a"))
{
//
// Ignore the file's pixel aspect ratio
//
noAspect = true;
i += 1;
}
else if (!strcmp (argv[i], "-c"))
{
//
// Load only one image channel.
//
if (i > argc - 2)
usageMessage (argv[0]);
channel = argv[i + 1];
useCtl = false;
i += 2;
}
else if (!strcmp (argv[i], "-1"))
{
//
// Display 0.0 to 1.0 range.
//
zeroOneExposure = true;
useCtl = false;
i += 1;
}
else if (!strcmp (argv[i], "-n"))
{
//
// Normalize pixels.
//
zeroOneExposure = true;
normalize = true;
useCtl = false;
i += 1;
}
else if (!strcmp (argv[i], "-A"))
{
//
// Display alpha
//
zeroOneExposure = true;
normalize = false;
channel = "A";
useCtl = false;
i += 1;
}
else if (!strcmp (argv[i], "-Z"))
{
//
// Display depth
//
zeroOneExposure = true;
normalize = true;
channel = "Z";
useCtl = false;
i += 1;
}
else if (!strcmp (argv[i], "-s"))
{
//
// Swap top and bottom half, then left and right half.
//
swap = true;
i += 1;
}
else if (!strcmp (argv[i], "-u"))
{
//
// Continuous update.
//
continuousUpdate = true;
i += 1;
}
else if (!strcmp (argv[i], "-C"))
{
//
// Apply a CTL transform
//
if (i > argc - 2)
usageMessage (argv[0]);
transformNames.push_back (argv[i + 1]);
i += 2;
}
else if (!strcmp (argv[i], "-T"))
{
//
// No CTL transforms.
//
useCtl = false;
i += 1;
}
else if (!strcmp (argv[i], "-t"))
{
//
// Set number of threads
//
if (i > argc - 2)
usageMessage (argv[0]);
numThreads = strtol (argv[i + 1], 0, 0);
if (numThreads < 0)
{
cerr << "Number of threads cannot be negative." << endl;
return 1;
}
i += 2;
}
else if (!strcmp (argv[i], "-h"))
{
//
// Print help message
//
usageMessage (argv[0], true);
}
else if (!strcmp (argv[i], "-farPlane") || !strcmp (argv[i], "-f"))
{
//
// zFar plane for display deep data
//
if (i > argc - 2)
usageMessage (argv[0]);
farPlane = strtod (argv[i + 1], 0);
i += 2;
if (farPlane <= 0)
{
cerr << "Value of far Plane cannot be negative." << endl;
exit (1);
}
}
else if (!strcmp (argv[i], "-noDeepComp") || !strcmp (argv[i], "-d"))
{
//
// Toogle the option to composite deep images, else just use
// the first sample of each pixel
//
deepComp = false;
i += 1;
}
else
{
//
// image file name
//
imageFile = argv[i];
i += 1;
}
}
if (imageFile == 0)
usageMessage (argv[0]);
//
// Load the specified image file,
// open a window on the screen, and
// display the image.
//
int exitStatus = 0;
try
{
setGlobalThreadCount (numThreads);
MainWindow *mainWindow = makeMainWindow (imageFile,
channel,
layer,
preview,
lx, ly,
farPlane,
noDisplayWindow,
noAspect,
zeroOneExposure,
normalize,
swap,
continuousUpdate,
transformNames,
useCtl,
deepComp);
mainWindow->window->show (1, argv);
Fl::set_color (FL_GRAY, 240, 240, 240);
Fl::set_color (FL_GRAY0, 80, 80, 80);
mainWindow->window->callback(window_callback); // set main window exit
exitStatus = Fl::run();
}
catch (const exception &e)
{
cerr << e.what() << endl;
exitStatus = 1;
}
return exitStatus;
}