void extractChannels( int argc, char* argv[] )
{
  pfs::DOMIO pfsio;

  static struct option cmdLineOptions[] = {
    { "help", no_argument, NULL, 'h' },
    { NULL, 0, NULL, 0 }
  };

  std::set<const char*, ltstr> keepChannels;

  int optionIndex = 0;
  while( 1 ) {
    int c = getopt_long (argc, argv, "h", cmdLineOptions, &optionIndex);
    if( c == -1 ) break;
    switch( c ) {
    case 'h':
      printHelp();
      throw QuietException();
    case '?':
      throw QuietException();
    case ':':
      throw QuietException();
    }
  }

  errorCheck( optind < argc, "At least one channel must be specified" );

  for( ;optind < argc; optind++ )
    keepChannels.insert( argv[optind] );

  
  while( true ) {
    pfs::Frame *frame = pfsio.readFrame( stdin );
    if( frame == NULL ) break; // No more frames

    {                           // Check if the listed channels exist
      std::set<const char*, ltstr>::iterator it;
      for( it = keepChannels.begin(); it != keepChannels.end(); it++ )
        if( frame->getChannel( *it ) == NULL ) {
          fprintf( stderr, PROG_NAME " error: Channel %s does not exist\n", *it );
          throw QuietException();
        }
      
    }
    
    {                           // Remoe not listed channels
      pfs::ChannelIterator *it = frame->getChannels();
      while( it->hasNext() ) {
        pfs::Channel *channel = it->getNext();
        if( keepChannels.find(channel->getName() ) == keepChannels.end() )
          frame->removeChannel( channel );
      }
    }    
    
    pfsio.writeFrame( frame, stdout );
    pfsio.freeFrame( frame );        
  }
}
Beispiel #2
0
static void errorCheck( bool condition, const char *string )
{
    if( !condition ) {
	fprintf( stderr, PROG_NAME " error: %s\n", string );
	throw QuietException();
    }
}
int ClientConnection::LoadConnection_global(char *fname, bool fFromDialog,bool default_file)
{

	GetPrivateProfileString("connection", "host", "", m_host, MAX_HOST_NAME_LEN, fname);
	m_port = GetPrivateProfileInt("connection", "port", 0, fname);
	GetPrivateProfileString("connection", "proxyhost", "", m_proxyhost, MAX_HOST_NAME_LEN, fname);
	m_proxyport = GetPrivateProfileInt("connection", "proxyport", 0, fname);
	m_fUseProxy = GetPrivateProfileInt("options", "UseProxy", 0, fname) ? true : false;

	char buf[32];
	m_encPasswd[0] = '\0';
	if (GetPrivateProfileString("connection", "password", "", buf, 32, fname) > 0) {
		for (int i = 0; i < MAXPWLEN; i++)	{
			int x = 0;
			sscanf(buf+i*2, "%2x", &x);
			m_encPasswd[i] = (unsigned char) x;
		}
	}

	// The Connection Profile ".vnc" has been required from Connection Session Dialog Box
	// Load the rest of params
	char optionfile[MAX_PATH];
	char *tempvar=NULL;
	tempvar = getenv( "TEMP" );
	if (tempvar) strcpy(optionfile,tempvar);
	else strcpy(optionfile,"");
	strcat(optionfile,"\\options.vnc");
	
	if (strcmp(m_host, "") == 0 || 
			  strcmp(fname,optionfile)==0)
	{
		// Load the rest of params 
		strcpy(m_opts.m_proxyhost,m_proxyhost);
		m_opts.m_proxyport=m_proxyport;
		m_opts.m_fUseProxy=m_fUseProxy;
		m_opts.Load(fname);
		m_opts.Register();
		// Then display the session dialog to get missing params again
		SessionDialog sessdlg(&m_opts, this, m_pDSMPlugin); //sf@2002
		if (!sessdlg.DoDialog_global())
		{
			throw QuietException("");
		}
		_tcsncpy(m_host, sessdlg.m_host_dialog, MAX_HOST_NAME_LEN);
		m_port = sessdlg.m_port;
	
		_tcsncpy(m_proxyhost, sessdlg.m_proxyhost, MAX_HOST_NAME_LEN);
		m_proxyport = sessdlg.m_proxyport;
		m_fUseProxy = sessdlg.m_fUseProxy;

	};	
	//EndAaronP
	return 0;
}
Beispiel #4
0
BOOL CALLBACK AuthDialog::DlgProc(  HWND hwnd,  UINT uMsg,  
									   WPARAM wParam, LPARAM lParam ) {
	// This is a static method, so we don't know which instantiation we're 
	// dealing with. But we can get a pseudo-this from the parameter to 
	// WM_INITDIALOG, which we therafter store with the window and retrieve
	// as follows:
	AuthDialog *_this = (AuthDialog *) GetWindowLong(hwnd, GWL_USERDATA);

	switch (uMsg) {

	case WM_INITDIALOG:
		{
			SetWindowLong(hwnd, GWL_USERDATA, lParam);
			_this = (AuthDialog *) lParam;
			CentreWindow(hwnd);
			return TRUE;
		}
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDOK:
			{
				UINT res= GetDlgItemText( hwnd,  IDC_PASSWD_EDIT,
					_this->m_passwd, 256);
				
				EndDialog(hwnd, TRUE);

				return TRUE;
			}
		case IDCANCEL:
			EndDialog(hwnd, FALSE);
			throw QuietException("User canceled connection.");
			return TRUE;
		}
		break;
	case WM_DESTROY:
		EndDialog(hwnd, FALSE);
		return TRUE;
	}
	return 0;
}
Beispiel #5
0
void readFrames( int argc, char* argv[] )
{
  pfs::DOMIO pfsio;

  bool verbose = false;
  
  // Parse command line parameters
  static struct option cmdLineOptions[] = {
    { "help", no_argument, NULL, 'h' },
    { "verbose", no_argument, NULL, 'v' },
    { NULL, 0, NULL, 0 }
  };
  static const char optstring[] = "hv";
    
  pfs::FrameFileIterator it( argc, argv, "rb", NULL, NULL,
    optstring, cmdLineOptions );
    
  int optionIndex = 0;
  while( 1 ) {
    int c = getopt_long (argc, argv, optstring, cmdLineOptions, &optionIndex);
    if( c == -1 ) break;
    switch( c ) {
    case 'h':
      printHelp();
      throw QuietException();
    case 'v':
      verbose = true;
      break;
    case '?':
      throw QuietException();
    case ':':
      throw QuietException();
    }
  }

  GDALAllRegister();

  GDALDataset *poDataset;
  GDALRasterBand *poBand;
  double adfGeoTransform[6];
  size_t nBlockXSize, nBlockYSize, nBands;
  int bGotMin, bGotMax;
  double adfMinMax[2];
  float *pafScanline;

  while( true ) {
    pfs::FrameFile ff = it.getNextFrameFile();
    if( ff.fh == NULL ) break; // No more frames
    it.closeFrameFile( ff );

    VERBOSE_STR << "reading file '" << ff.fileName << "'" << std::endl;
    if( !( poDataset = (GDALDataset *) GDALOpen( ff.fileName, GA_ReadOnly ) ) ) {
      std::cerr << "input does not seem to be in a format supported by GDAL" << std::endl;
      throw QuietException();
    }
    VERBOSE_STR << "GDAL driver: " << poDataset->GetDriver()->GetDescription()
	<< " / " << poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) << std::endl;
    nBlockXSize = poDataset->GetRasterXSize();
    nBlockYSize = poDataset->GetRasterYSize();
    nBands = poDataset->GetRasterCount();
    VERBOSE_STR << "Data size " << nBlockXSize << "x" << nBlockYSize << "x" << nBands << std::endl;
    if( poDataset->GetProjectionRef() ) {
      VERBOSE_STR << "Projection " << poDataset->GetProjectionRef() << std::endl;
    }
    if( poDataset->GetGeoTransform( adfGeoTransform ) == CE_None ) {
      VERBOSE_STR << "Origin = (" << adfGeoTransform[0] << ", " << adfGeoTransform[3] << ")" << std::endl;
      VERBOSE_STR << "Pixel Size = (" << adfGeoTransform[1] << ", " << adfGeoTransform[5] << ")" << std::endl;
    }

    if( nBlockXSize==0  || nBlockYSize==0 
	    || ( SIZE_MAX / nBlockYSize < nBlockXSize ) 
	    || ( SIZE_MAX / (nBlockXSize * nBlockYSize ) < 4 ) ) {
      std::cerr << "input data has invalid size" << std::endl;
      throw QuietException();
    }
    if( !(pafScanline = (float *) CPLMalloc( sizeof(float) * nBlockXSize ) ) ) {
      std::cerr << "not enough memory" << std::endl;
      throw QuietException();
    }

    pfs::Frame *frame = pfsio.createFrame( nBlockXSize, nBlockYSize );
    pfs::Channel *C[nBands];
    char channel_name[32];

    frame->getTags()->setString( "X-GDAL_DRIVER_SHORTNAME", poDataset->GetDriver()->GetDescription() );
    frame->getTags()->setString( "X-GDAL_DRIVER_LONGNAME", poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) );
    frame->getTags()->setString( "X-PROJECTION", poDataset->GetProjectionRef() );
    if( poDataset->GetGeoTransform( adfGeoTransform ) == CE_None ) {
      frame->getTags()->setString( "X-ORIGIN_X", stringify(adfGeoTransform[0]).c_str() );
      frame->getTags()->setString( "X-ORIGIN_Y", stringify(adfGeoTransform[3]).c_str() );
      frame->getTags()->setString( "X-PIXEL_WIDTH", stringify(adfGeoTransform[1]).c_str() );
      frame->getTags()->setString( "X-PIXEL_HEIGHT", stringify(adfGeoTransform[5]).c_str() );
    }

    for ( size_t band = 1; band <= nBands; band++) {
      size_t nBandXSize, nBandYSize;
      VERBOSE_STR << "Band " << band << ": " << std::endl;
      snprintf( channel_name, 32, "X-GDAL%zu", band );
      C[band - 1] = frame->createChannel( channel_name );
      poBand = poDataset->GetRasterBand( band );
      nBandXSize = poBand->GetXSize();
      nBandYSize = poBand->GetYSize();
      VERBOSE_STR << "    " << nBandXSize << "x" << nBandYSize << std::endl;
      if( nBandXSize != (int)nBlockXSize || nBandYSize != (int)nBlockYSize ) {
        std::cerr << "data in band " << band << " has different size" << std::endl;
        throw QuietException();
      }
      VERBOSE_STR << "    Type " << GDALGetDataTypeName( poBand->GetRasterDataType() ) << ", "
	  << "Color Interpretation " << GDALGetColorInterpretationName( poBand->GetColorInterpretation() ) << std::endl;
      adfMinMax[0] = poBand->GetMinimum( &bGotMin );
      adfMinMax[1] = poBand->GetMaximum( &bGotMax );
      if( ! (bGotMin && bGotMax) ) {
      	  GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
      }
      VERBOSE_STR << "    Min " << adfMinMax[0] << ", Max " << adfMinMax[1] << std::endl;
      C[band - 1]->getTags()->setString( "X-TYPE", 
	      GDALGetDataTypeName( poBand->GetRasterDataType() ) );
      C[band - 1]->getTags()->setString( "X-COLOR_INTERPRETATION", 
	      GDALGetColorInterpretationName( poBand->GetColorInterpretation() ) );
      C[band - 1]->getTags()->setString( "X-MIN", stringify(adfMinMax[0]).c_str() );
      C[band - 1]->getTags()->setString( "X-MAX", stringify(adfMinMax[1]).c_str() );
      for( size_t y = 0; y < nBlockYSize; y++ ) {
        if( poBand->RasterIO( GF_Read, 0, y, nBlockXSize, 1, pafScanline, 
		    nBlockXSize, 1, GDT_Float32, 0, 0) != CE_None ) {
          std::cerr << "input error" << std::endl;
          throw QuietException();
	}
	memcpy( C[band - 1]->getRawData() + y * nBlockXSize, pafScanline, nBlockXSize * sizeof(float) );
      }
    }
    CPLFree( pafScanline );
    GDALClose( poDataset );

    const char *fileNameTag = strcmp( "-", ff.fileName )==0 ? "stdin" : ff.fileName;
    frame->getTags()->setString( "FILE_NAME", fileNameTag );
        
    pfsio.writeFrame( frame, stdout );
    pfsio.freeFrame( frame );
  }
}
// returns zero if successful
int ClientConnection::LoadConnection(char *fname, bool fFromDialog,bool default_file)
{
	// The Connection Profile ".vnc" has been required from Connection Session Dialog Box
	if (fFromDialog)
	{
		char tname[_MAX_FNAME + _MAX_EXT];
		ofnInit();
		ofn.hwndOwner = m_hSessionDialog;
		ofn.lpstrFile = fname;
		ofn.lpstrFileTitle = tname;
		ofn.Flags = OFN_HIDEREADONLY;

		// Open the FileSelection Dialog boxq
		if (GetOpenFileName(&ofn) == 0)
			return -1;
	}

	if (GetPrivateProfileString("connection", "host", "", m_host, MAX_HOST_NAME_LEN, fname) == 0) {
		//AaronP
//		MessageBox(m_hwnd, sz_K5, sz_K6, MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
//		return -1;
		//EndAaronP
	}
	if ( (m_port = GetPrivateProfileInt("connection", "port", 0, fname)) == 0)
	{
		//
		//MessageBox(m_hwnd, sz_K7, sz_K6, MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
		// in case options.vnc does not exist return to normal menu
		return -1;
	}

	GetPrivateProfileString("connection", "proxyhost", "", m_proxyhost, MAX_HOST_NAME_LEN, fname);
	m_proxyport = GetPrivateProfileInt("connection", "proxyport", 0, fname);
	m_fUseProxy = GetPrivateProfileInt("options", "UseProxy", 0, fname);

	char buf[32];
	m_encPasswd[0] = '\0';
	if (GetPrivateProfileString("connection", "password", "", buf, 32, fname) > 0) {
		for (int i = 0; i < MAXPWLEN; i++)	{
			int x = 0;
			sscanf(buf+i*2, "%2x", &x);
			m_encPasswd[i] = (unsigned char) x;
		}
	}

	// The Connection Profile ".vnc" has been required from Connection Session Dialog Box
	// Load the rest of params
	char optionfile[MAX_PATH];
	char *tempvar=NULL;
	tempvar = getenv( "TEMP" );
	if (tempvar) strcpy(optionfile,tempvar);
	else strcpy(optionfile,"");
	strcat(optionfile,"\\options.vnc");
	
//	if (fFromDialog)
	{
		m_opts.Load(fname);
		m_opts.Register();
	}
	//AaronP
	//else 
		if (strcmp(m_host, "") == 0 || 
			  strcmp(fname,optionfile)==0)
	{
		// Load the rest of params 
		strcpy(m_opts.m_proxyhost,m_proxyhost);
		m_opts.m_proxyport=m_proxyport;
		m_opts.m_fUseProxy=m_fUseProxy;
		m_opts.Load(fname);
		m_opts.Register();
		// Then display the session dialog to get missing params again
		SessionDialog sessdlg(&m_opts, this, m_pDSMPlugin); //sf@2002
		if (!sessdlg.DoDialog())
		{
			throw QuietException("");
		}
		_tcsncpy(m_host, sessdlg.m_host_dialog, MAX_HOST_NAME_LEN);
		m_port = sessdlg.m_port;
	
		_tcsncpy(m_proxyhost, sessdlg.m_proxyhost, MAX_HOST_NAME_LEN);
		m_proxyport = sessdlg.m_proxyport;
		m_fUseProxy = sessdlg.m_fUseProxy;

	};	
	//EndAaronP
	return 0;
}
void clampFrames( int argc, char* argv[] )
{
    pfs::DOMIO pfsio;

    float clampMin = 0.0001;    // default: 10^-4
    float clampMax = 100000000; // default: 10^8
    bool verbose = false;
    bool opt_percentile = false;
    bool opt_zeromode = false;
    bool opt_rgbmode = false;

    static struct option cmdLineOptions[] = {
        { "help", no_argument, NULL, 'h' },
        { "verbose", no_argument, NULL, 'v' },
        { "percentile", no_argument, NULL, 'p' },
        { "zero", no_argument, NULL, 'z' },
        { "rgb", no_argument, NULL, 'r' },
        { "min", required_argument, NULL, 'n' },
        { "max", required_argument, NULL, 'x' },
        { NULL, 0, NULL, 0 }
    };

    int optionIndex = 0;
    while( 1 ) {
        int c = getopt_long (argc, argv, "hvpz", cmdLineOptions, &optionIndex);
        if( c == -1 ) break;
        switch( c ) {
        case 'h':
            printHelp();
            throw QuietException();
        case 'v':
            verbose = true;
            break;
        case 'p':
            opt_percentile = true;
            break;
        case 'z':
            opt_zeromode = true;
            break;
        case 'r':
            opt_rgbmode = true;
            break;
        case 'n':
            clampMin = (float)strtod( optarg, NULL );
            break;
        case 'x':
            clampMax = (float)strtod( optarg, NULL );
            break;
        case '?':
            throw QuietException();
        case ':':
            throw QuietException();
        }
    }

    // check if clamping parameters make sense
    if( opt_percentile )
    {
        clampMin = (clampMin>1e-3) ? clampMin : 1e-3;
        clampMax = (clampMax<1) ? clampMax : 0.999f;
        if( clampMin >= clampMax )
            throw pfs::Exception("incorrect clamping range for percentile mode");
    }
    else
    {
        clampMin = (clampMin>1e-4) ? clampMin : 1e-4;
        clampMax = (clampMax<1e8) ? clampMax : 1e8;
        if( clampMin >= clampMax )
            throw pfs::Exception("incorrect clamping range");
    }


    if( verbose )
    {
        if( opt_rgbmode )
            fprintf(stderr, "Clamping in RGB color space.\n");
        if( opt_zeromode )
            fprintf(stderr, "Values out of clamp range will be set to zero.\n");
        if( opt_percentile )
            fprintf( stderr, "Clamping channels to [%g, %g] percentile.\n", clampMin, clampMax );
        else
            fprintf( stderr, "Clamping channels to [%g, %g] range.\n", clampMin, clampMax );
    }


    while( true ) {
        pfs::Frame *frame = pfsio.readFrame( stdin );
        if( frame == NULL ) break; // No more frames

        pfs::Channel *X, *Y, *Z;
        frame->getXYZChannels( X, Y, Z );

        if( X != NULL )
        {   // Color, XYZ
            if( opt_rgbmode )
                pfs::transformColorSpace( pfs::CS_XYZ, X, Y, Z, pfs::CS_RGB, X, Y, Z );

            clamp( X, clampMin, clampMax, opt_percentile, opt_zeromode );
            clamp( Y, clampMin, clampMax, opt_percentile, opt_zeromode );
            clamp( Z, clampMin, clampMax, opt_percentile, opt_zeromode );

            if( opt_rgbmode )
                pfs::transformColorSpace( pfs::CS_RGB, X, Y, Z, pfs::CS_XYZ, X, Y, Z );
        }
        else if( (Y = frame->getChannel( "Y" )) != NULL )
        {
            clamp( Y, clampMin, clampMax, opt_percentile, opt_zeromode );
        }
        else
            throw pfs::Exception( "Missing X, Y, Z channels in the PFS stream" );

        pfsio.writeFrame( frame, stdout );
        pfsio.freeFrame( frame );
    }
}
Beispiel #8
0
void resizeFrames( int argc, char* argv[] )
{
  pfs::DOMIO pfsio;

  float ratio = -1;
  int xSize = -1;
  int ySize = -1;
  int minX = -1;
  int maxX = -1;
  int minY = -1;
  int maxY = -1;
  bool verbose = false;
  ResampleFilter *filter = NULL;

  static struct option cmdLineOptions[] = {
    { "help", no_argument, NULL, 'h' },
    { "verbose", no_argument, NULL, 'v' },
    { "x", required_argument, NULL, 'x' },
    { "y", required_argument, NULL, 'y' },
    { "maxx", required_argument, NULL, '1' },
    { "maxy", required_argument, NULL, '2' },
    { "minx", required_argument, NULL, '3' },
    { "miny", required_argument, NULL, '4' },
    { "ratio", required_argument, NULL, 'r' },
    { "filter", required_argument, NULL, 'f' },
    { NULL, 0, NULL, 0 }
  };

  int optionIndex = 0;
  while( 1 ) {
    int c = getopt_long (argc, argv, "x:y:r:f:", cmdLineOptions, &optionIndex);
    if( c == -1 ) break;
    switch( c ) {
    case 'h':
      printHelp();
      throw QuietException();
    case 'v':
      verbose = true;
      break;
    case 'x':
      xSize = getIntParam( optarg, "x" );
      break;
    case 'y':
      ySize = getIntParam( optarg, "y" );
      break;
    case 'r':
      ratio = getFloatParam( optarg, "ratio" );
      break;
    case '1':
      maxX = getIntParam( optarg, "maxx" );
      break;
    case '2':
      maxY = getIntParam( optarg, "maxy" );
      break;
    case '3':
      minX = getIntParam( optarg, "minx" );
      break;
    case '4':
      minY = getIntParam( optarg, "miny" );
      break;
    case 'f':
      if( !strcasecmp( optarg, "LINEAR" ) ) {
        filter = new LinearFilter();
      } else if( !strcasecmp( optarg, "MITCHELL" ) ) {
        filter = new MitchellFilter();
      } else if( !strcasecmp( optarg, "BOX" ) ) {
        filter = new BoxFilter();
      } else {
        throw pfs::Exception( "Unknown filter. Possible values: LINEAR, BOX, MITCHELL" );     
      }
      break;
    case '?':
      throw QuietException();
    case ':':
      throw QuietException();
    }
  }

  if( filter == NULL ) filter = new LinearFilter();

  bool isMinMax = (minX!=-1) || (maxX!=-1) || (minY!=-1) || (maxY!=-1);

  errorCheck( (minX==-1 || maxX == -1 || minX <= maxX) &&
    (minY==-1 || maxY==-1 || minY <= maxY),
    "Min value must be lower than max value" );
  
  errorCheck( (ratio != -1) ^ (xSize != -1 || ySize != -1) ^ isMinMax, "Specify either size or ratio or min/max sizes" );
  errorCheck( ratio == -1 || ratio > 0 , "Wrong scaling ratio" );
  
//  bool firstFrame = true;

  pfs::Frame *resizedFrame = NULL;
  
  while( true ) {
    pfs::Frame *frame = pfsio.readFrame( stdin );
    if( frame == NULL ) break; // No more frames

    pfs::Channel *X, *Y, *Z;
    frame->getXYZChannels( X, Y, Z );

//    pfs::Channel *dX, *dY, *dZ;
    
//    if( firstFrame ) {

    int new_x, new_y;

    
      if( ratio != -1 ) {
        new_x = (int)(frame->getWidth()*ratio);
        new_y = (int)(frame->getHeight()*ratio);
      } else {
        if( isMinMax ) {        // Min/max sizes given
          new_x = frame->getWidth();
          new_y = frame->getHeight();
          float mm_ratio = (float)new_x/(float)new_y;
          if( minX != -1 && new_x < minX ) {
            new_x = minX;
            new_y = (int)((float)new_x/mm_ratio);
          }
          if( minY != -1 && new_y < minY ) {
            new_y = minY;
            new_x = (int)((float)new_y*mm_ratio);
          }
          if( maxX != -1 && new_x > maxX ) {
            new_x = maxX;
            new_y = (int)((float)new_x/mm_ratio);
          }
          if( maxY != -1 && new_y > maxY ) {
            new_y = maxY;
            new_x = (int)((float)new_y*mm_ratio);
          }
        } else {                // Size given
          new_x = xSize;
          new_y = ySize;
          if( new_x == -1 )
            new_x = (int)((float)frame->getWidth() * (float)ySize / (float)frame->getHeight());
          else if( new_y == -1 )
            new_y = (int)((float)frame->getHeight() * (float)xSize / (float)frame->getWidth());
        }
        
      }
      errorCheck( new_x > 0 && new_y > 0 && new_x <= 65536 && new_y <= 65536, "Wrong frame size" );
      errorCheck( ((frame->getWidth() <= new_x) && (frame->getHeight() <= new_y)) ||
        ((frame->getWidth() >= new_x) && (frame->getHeight() >= new_y)),
        "Can upsample / downsample image only in both dimensions simultaneously" );
      
      if( verbose ) fprintf( stderr, "New size: %d x %d \n", new_x, new_y );
      
      resizedFrame = pfsio.createFrame( new_x, new_y );
      
//      firstFrame = false;
//    }

    pfs::ChannelIterator *it = frame->getChannels();
    while( it->hasNext() ) {
      pfs::Channel *originalCh = it->getNext();
      pfs::Channel *newCh = resizedFrame->createChannel( originalCh->getName() );

      resampleArray( originalCh, newCh, filter );
    }

    pfs::copyTags( frame, resizedFrame );
    
    pfsio.writeFrame( resizedFrame, stdout );
    pfsio.freeFrame( frame );        
  }
  pfsio.freeFrame( resizedFrame );
  delete filter;
}
void applyAbsoluteOnFrames( int argc, char* argv[] )
{
  pfs::DOMIO pfsio;

  float destY = 1.0f;
  float srcY = 1.0f;  

  bool verbose = false;

  static struct option cmdLineOptions[] = {
    { "help", no_argument, NULL, 'h' },
    { "verbose", no_argument, NULL, 'v' },
    { NULL, 0, NULL, 0 }
  };

  int optionIndex = 0;
  while( 1 ) {
    int c = getopt_long (argc, argv, "", cmdLineOptions, &optionIndex);
    if( c == -1 ) break;
    switch( c ) {
    case 'h':
      printHelp();
      throw QuietException();
    case 'v':
      verbose = true;
      break;
    case '?':
      throw QuietException();
    case ':':
      throw QuietException();
    }
  } 

  if( optind == argc )
    throw pfs::Exception( "Destination luminance level <dest Y> must be specified" );
  if( optind < (argc - 2) )
    throw pfs::Exception( "Too many arguments" );

  destY = strtof( argv[optind++], NULL );
  if( optind != argc )
    srcY = strtof( argv[optind++], NULL );
  
  VERBOSE_STR << "rescale luminance to: " << destY << std::endl;
  if( srcY != 1.0f )
    VERBOSE_STR << "from: " << srcY << std::endl;

  float multY = destY/srcY;
  
  while( true ) {
    pfs::Frame *frame = pfsio.readFrame( stdin );
    if( frame == NULL ) break; // No more frames

    const char *lumType = frame->getTags()->getString( "LUMINANCE" );
    if( lumType != NULL && !strcmp( lumType, "ABSOLUTE" ) ) {
      VERBOSE_STR << "luminance is already absolute, skipping frame.";
    } else {
    
      pfs::Channel *X, *Y, *Z;
      frame->getXYZChannels( X, Y, Z );
    
      if( X != NULL ) {           // Color, XYZ

        if( lumType != NULL && !strcmp( lumType, "DISPLAY" ) ) {
          VERBOSE_STR << "converting from display-referred to linear luminance.";
          pfs::transformColorSpace( pfs::CS_XYZ, X, Y, Z, pfs::CS_RGB, X, Y, Z );
          pfs::transformColorSpace( pfs::CS_SRGB, X, Y, Z, pfs::CS_XYZ, X, Y, Z );
        }
        multiplyArray( X, X, multY );
        multiplyArray( Y, Y, multY );
        multiplyArray( Z, Z, multY );
        
      } else if( (Y = frame->getChannel( "Y" )) != NULL ) {
        // Luminance only

        if( lumType != NULL && !strcmp( lumType, "DISPLAY" ) ) 
          throw pfs::Exception( PROG_NAME ": Cannot handle gray-level display-referred images." );
        
        multiplyArray( Y, Y, multY );

      } else
        throw pfs::Exception( "Missing color channels in the PFS stream" );

      frame->getTags()->setString("LUMINANCE", "ABSOLUTE");
    }    
    
    pfsio.writeFrame( frame, stdout );
    pfsio.freeFrame( frame );        
  }
}
void readFrames( int argc, char* argv[] )
{
  pfs::DOMIO pfsio;

  bool verbose = false;
  bool opt_linear=false;
  float absoluteMaxLum = 0;
  
  // Parse command line parameters
  static struct option cmdLineOptions[] = {
    { "help", no_argument, NULL, 'h' },
    { "verbose", no_argument, NULL, 'v' },
    { "linear", no_argument, NULL, 'l' },
    { "absolute", required_argument, NULL, 'a' },
    { NULL, 0, NULL, 0 }
  };
  static const char optstring[] = "lhva:";
    
  pfs::FrameFileIterator it( argc, argv, "rb", NULL, NULL,
    optstring, cmdLineOptions );
    
  int optionIndex = 0;
  while( 1 ) {
    int c = getopt_long (argc, argv, optstring, cmdLineOptions, &optionIndex);
    if( c == -1 ) break;
    switch( c ) {
    case 'h':
      printHelp();
      throw QuietException();
    case 'v':
      verbose = true;
      break;
    case 'l':
      opt_linear = true;
      break;
    case 'a':
      absoluteMaxLum = (float)strtod( optarg, NULL );
      break;
    case '?':
      throw QuietException();
    case ':':
      throw QuietException();
    }
  }

  if( absoluteMaxLum != 0 && opt_linear )
    throw pfs::Exception( "'absolute' and 'linear' are conflicting options" );
  
  if( absoluteMaxLum < 0 )
    throw pfs::Exception( "maximum absolute luminance must be > 0" );

  VERBOSE_STR << "linearize input image: " << ((opt_linear || absoluteMaxLum!=0) ? "yes" : "no") << std::endl;
  if( absoluteMaxLum != 0 )
    VERBOSE_STR << "maximum absolute luminance: " << absoluteMaxLum << std::endl;
   
  while( true ) {
    pfs::FrameFile ff = it.getNextFrameFile();
    if( ff.fh == NULL ) break; // No more frames
    it.closeFrameFile( ff );

    VERBOSE_STR << "reading file '" << ff.fileName << "'" << std::endl;
    Magick::Image imImage( ff.fileName );

    VERBOSE_STR << "input image gamma:  " << imImage.gamma() << std::endl;
    bool hasAlpha = imImage.matte();
    if( hasAlpha )
      VERBOSE_STR << "alpha channel found" << std::endl;    
    
    pfs::Frame *frame = pfsio.createFrame( imImage.columns(),
      imImage.rows() );
    pfs::Channel *X, *Y, *Z;
    frame->createXYZChannels( X, Y, Z );

    pfs::Channel *alpha = NULL;
    if( hasAlpha )
      alpha = frame->createChannel( "ALPHA" );
    
    // Copy line by line to pfs::Frame
    int pixInd = 0;
    const float maxValue = (float)(1<<QuantumDepth) - 1;
    for( int r = 0; r < imImage.rows(); r++ ) {
      const Magick::PixelPacket *pixels =
        imImage.getConstPixels( 0, r, imImage.columns(), 1 );

      for( int c = 0; c < imImage.columns(); c++ ) {
        (*X)(pixInd) = (float)pixels[c].red / maxValue;
        (*Y)(pixInd) = (float)pixels[c].green / maxValue;
        (*Z)(pixInd) = (float)pixels[c].blue / maxValue;
        if( alpha != NULL )
          (*alpha)(pixInd) = (float)pixels[c].opacity / maxValue;
        pixInd++;
      } 
    }    

    // Linearize data is necessary
    if( opt_linear || absoluteMaxLum != 0 )
    {
      pfs::transformColorSpace( pfs::CS_SRGB, X, Y, Z, pfs::CS_XYZ, X, Y, Z );
      if( absoluteMaxLum != 0 ) {
        // Rescale to absolute luminance level
        const int pixCount = X->getWidth()*X->getHeight();
        for( int i = 0; i < pixCount; i++ ) {
          (*X)(i) *= absoluteMaxLum;
          (*Y)(i) *= absoluteMaxLum;
          (*Z)(i) *= absoluteMaxLum;
        }        
        frame->getTags()->setString("LUMINANCE", "ABSOLUTE");
      } else
        frame->getTags()->setString("LUMINANCE", "RELATIVE");
    }
    else
    {
      pfs::transformColorSpace( pfs::CS_RGB, X, Y, Z, pfs::CS_XYZ, X, Y, Z );
      frame->getTags()->setString("LUMINANCE", "DISPLAY");
    }

    // This is the luminance / luma perceived as reference white
    // Some tone-mappers may need this
    frame->getTags()->setString("WHITE_Y", "1");    

    const char *fileNameTag = strcmp( "-", ff.fileName )==0 ? "stdin" : ff.fileName;
    frame->getTags()->setString( "FILE_NAME", fileNameTag );
 
    char strbuf[3];
    snprintf( strbuf, 3, "%d", (int)imImage.depth() );
    frame->getTags()->setString("BITDEPTH", strbuf );    
   
    pfsio.writeFrame( frame, stdout );
    pfsio.freeFrame( frame );
        
  }
}