Logo Search packages:      
Sourcecode: pfstools version File versions  Download package

pfscat.cpp

/**
 * @brief Concatenate frames in PFS stream
 *
 * This file is a part of PFSTOOLS package.
 * ----------------------------------------------------------------------
 * Copyright (C) 2003,2004 Rafal Mantiuk and Grzegorz Krawczyk
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * ----------------------------------------------------------------------
 *
 * @author Dorota Zdrojewska, <dzdrojewska@wi.ps.pl>
 *
 */

#include <pfs.h>
#include <climits>
#include <iostream>
#include <getopt.h>
#include <fcntl.h>
#include <stdlib.h>

#define PROG_NAME "pfscat"
#define UNSP INT_MAX
#define HORIZONTAL 0
#define VERTICAL 1
#define MIN 0
#define MAX 1
#define PREV_MIN 2
#define PREV_MAX 3
#define X 0
#define Y 1
#define Z 2

using namespace std;

enum just {J_MIN, J_MAX, J_CENTER};

class QuietException
{
};


static struct option cmdLineOptions[] = {
    {"help", no_argument, NULL, 'h'},
    {"horizontal", no_argument, NULL, 'H'},
    {"vertical", no_argument, NULL, 'V'},
    {"justify", required_argument, NULL, 'j'},
    {"R", required_argument, NULL, 'R'},
    {"G", required_argument, NULL, 'G'},
    {"B", required_argument, NULL, 'B'},
    {"Y", required_argument, NULL, 'Y'},
    {NULL, 0, NULL, 0}

};


void printHelp()
{
fprintf( stderr, PROG_NAME ": \n"
      "\t[--vertical]\n"
      "\t[--horizontal]\n"
      "\t[-j <type>]\n"
      "\t[-R <val>]\n"
      "\t[-G <val>]\n"
      "\t[-B <val>]\n"
      "\t[-Y <val>]\n"
      "\t[--help]\n"
      "See man page for more information.\n");
}


void justification (enum just just, int inSize, int prevSize, int outSize, int *out)
{
switch (just) {

    case J_CENTER:
      
      if(inSize<prevSize)     {
    
          int diff=outSize-inSize;
          out[MIN]=diff/2;
          out[MAX]=outSize-(diff/2)-1;
          if (diff%2) out[MAX]--;
          out[PREV_MIN]=0;
          out[PREV_MAX]=outSize-1;
          }
      else {
      
          int diff=outSize-prevSize;
          out[PREV_MIN]=diff/2;
          out[PREV_MAX]=outSize-(diff/2)-1;
          if (diff%2) out[PREV_MAX]--;
          out[MIN]=0;
          out[MAX]=outSize-1;
          }
      break;

    case J_MIN:       
          
      out[MIN]=0;
      out[MAX]=inSize-1;
      out[PREV_MIN]=0;
      out[PREV_MAX]=prevSize-1;
      break;

    case J_MAX:      
          
      out[MIN]=outSize-inSize;
      out[MAX]=outSize-1;
      out[PREV_MIN]=outSize-prevSize;
      out[PREV_MAX]=outSize-1;
      break;
    }
}


float clamp(float val, float min, float max)
{
float out;
out = (val<min) ? min : val;
out = (val>max) ? max : val;
return out;
}


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

static const char optString[] =  "hHVj:R:G:B:Y:";
enum just just=J_CENTER; // type of justification
int alignment=UNSP; //vertical or horizontal alignment of frames in output image

float R=1e-4, G=1e-4, B=1e-4, luminance=1.0; // background color in RGB or luminance mode
float XYZ[3];
bool optLuminanceMode=false, RGB=false, optLuminance=false;
bool pipes = true;

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();
          break;
      case 'H':
          if (alignment==VERTICAL) throw pfs::Exception("You cannot specify both horizontal and vertical alignment");
          else alignment=HORIZONTAL;
          break;
      case 'V':
          if (alignment==HORIZONTAL) throw pfs::Exception("You cannot specify both horizontal and vertical alignment");
            else alignment=VERTICAL;
          break;
      case 'j':
            if (!strcmp(optarg,"min")) just=J_MIN;
          else if (!strcmp(optarg,"max")) just=J_MAX;
          else if (!strcmp(optarg,"center")) just=J_CENTER;
          else throw pfs::Exception("Unknown type of justification. Accepted types: 'min', 'max' or 'center')");
          break;
      case 'R':
          R=atof(optarg);
          if(R<=(1e-4)) R=1e-4;
          RGB=true;
          break;
      case 'G':
          G=atof(optarg);
          if(G<=(1e-4)) G=1e-4;
          RGB=true;
          break;
      case 'B':
          B=atof(optarg);
          if(B<=(1e-4)) B=1e-4;
          RGB=true;
          break;
      case 'Y':
          luminance=atof(optarg);
          if(luminance<=(1e-4)) luminance=1e-4;
          optLuminance=true;
          break;
      }
    }

if (alignment==UNSP) throw pfs::Exception("You must specify an alignment - --horizontal or --vertical option");

pfs::FrameFileIterator it ( argc, argv, "rb", NULL, NULL, optString, cmdLineOptions);
int pipe_no = 0;
pfs::FrameFile * ff;
ff = (pfs::FrameFile *) malloc ((pipe_no+1) * sizeof(pfs::FrameFile));

while (1) {
    ff[pipe_no] = it.getNextFrameFile();
    if (ff[pipe_no].fh == NULL) break; // no more files
    pipe_no++;
    ff=(pfs::FrameFile *) realloc(ff, (pipe_no+1)*sizeof(pfs::FrameFile));
    }
    
if(pipe_no == 0) { // no named pipes
    pipe_no = 1;
    pipes = false;
}

//color transformation
if(optLuminance && !RGB) {
    R=1;
    G=1;
    B=1;
    }

XYZ[X]=luminance*(0.4124*R + 0.3576*G + 0.1805*B);
XYZ[Y]=luminance*(0.2126*R + 0.7152*G + 0.0722*B);
XYZ[Z]=luminance*(0.0193*R + 0.1192*G + 0.9505*B);
for (int i=0; i<3; i++) XYZ[i]=clamp(XYZ[i], 1e-4, 100000000.0);

bool finish = false;
int frame_no=0;
int tRow=0, bRow=0, lCol=0, rCol=0, prevtRow=0, prevbRow=0, prevlCol=0, prevrCol=0;
int inWidth=0, inHeight=0, outWidth=0, outHeight=0, prevWidth=0, prevHeight=0;
pfs::Frame *inFrame, *outFrame, *prevFrame;
pfs::Channel *inX, *inY, *inZ, *outX, *outY, *outZ, *prevX, *prevY, *prevZ;

while (1) {
    
    if(pipes) {
      inWidth=0;   inHeight=0; 
      outWidth=0;  outHeight=0; 
      prevWidth=0; prevHeight=0;
      }
    
    for (int i=0; i<pipe_no; i++) {

      if(pipes) inFrame = pfsio.readFrame(ff[i].fh);    
      else inFrame = pfsio.readFrame(stdin);
      
      if (inFrame==NULL) {
          finish = true;      
          break; // no more frames
          }

      inFrame->getXYZChannels(inX, inY, inZ);
      inWidth=inFrame->getWidth();
      inHeight=inFrame->getHeight();

        if (frame_no) { // save previous frame
      
          prevWidth=outWidth;
            prevHeight=outHeight;
          prevFrame=pfsio.createFrame(prevWidth, prevHeight);
          if (!optLuminanceMode) prevFrame->createXYZChannels(prevX, prevY, prevZ);
          else prevY=prevFrame->createChannel("Y");
          int size=prevWidth*prevHeight;
      
          for (int i=0; i<size; i++) {
            (*prevY)(i)=(*outY)(i);
            if (!optLuminanceMode) {
                (*prevX)(i)=(*outX)(i);
                (*prevZ)(i)=(*outZ)(i);
                }
            }
          pfsio.freeFrame(outFrame);
          }
        
      int leftRight[4], topBottom[4];
      
        if (alignment==VERTICAL) {
      
          if(inWidth>outWidth) outWidth=inWidth;
          outHeight+=inHeight;
      
          justification (just, inWidth, prevWidth, outWidth, leftRight);

          lCol=leftRight[MIN];
          rCol=leftRight[MAX];
          tRow=outHeight-inHeight;
          bRow=outHeight-1;
          prevlCol=leftRight[PREV_MIN];
          prevrCol=leftRight[PREV_MAX];
          prevtRow=0;
          prevbRow=prevHeight-1;
          }

      else if (alignment==HORIZONTAL) {
      
          outWidth+=inWidth;
          if(inHeight>outHeight) outHeight=inHeight;

          justification (just, inHeight, prevHeight, outHeight, topBottom);
          lCol=outWidth-inWidth;
          rCol=outWidth-1;
          tRow=topBottom[MIN];
          bRow=topBottom[MAX];
          prevlCol=0;
          prevrCol=prevWidth-1;
          prevtRow=topBottom[PREV_MIN];
          prevbRow=topBottom[PREV_MAX];
          }
     
      if(inX != NULL) { //XYZ mode

          if (frame_no==0) optLuminanceMode=false; // first frame
      
          if(!optLuminanceMode) {
      
            outFrame = pfsio.createFrame(outWidth, outHeight);
            outFrame->createXYZChannels(outX, outY, outZ);
    
            for (int i=0; i<outHeight; i++)
                for (int j=0; j<outWidth; j++) {
          
                if (i>=tRow && i<=bRow && j>=lCol && j<=rCol) {
                  (*outX)(j,i)=(*inX)(j-lCol,i-tRow);
                  (*outY)(j,i)=(*inY)(j-lCol,i-tRow);
                  (*outZ)(j,i)=(*inZ)(j-lCol,i-tRow);
                  }
      
                else if (i>=prevtRow && i<=prevbRow && j>=prevlCol && j<=prevrCol) {
                  (*outX)(j,i)=(*prevX)(j-prevlCol,i-prevtRow);
                  (*outY)(j,i)=(*prevY)(j-prevlCol,i-prevtRow);
                  (*outZ)(j,i)=(*prevZ)(j-prevlCol,i-prevtRow);
                  }
            
                else {
                  (*outX)(j, i)=XYZ[X];
                  (*outY)(j, i)=XYZ[Y];
                  (*outZ)(j, i)=XYZ[Z];
                  }
                
                }
            }
          else {
            outFrame = pfsio.createFrame(prevWidth, prevHeight);
            outY=outFrame->createChannel("Y");
            int size=prevWidth*prevHeight;
            for (int i=0; i<size; i++ ) (*outY)(i)=(*prevY)(i);
            outHeight=prevHeight;
            outWidth=prevWidth;
            }
          }
      else if (inY=inFrame->getChannel("Y")) {// luminance mode
      
          if (frame_no==0) optLuminanceMode=true; // first frame
      
          if (optLuminanceMode) {
            outFrame = pfsio.createFrame(outWidth, outHeight);
            outY=outFrame->createChannel("Y");
      
            for (int i=0; i<outHeight; i++)
                for (int j=0; j<outWidth; j++) {
          
                  if (i>=tRow && i<=bRow && j>=lCol && j<=rCol) 
                      (*outY)(j,i)=(*inY)(j-lCol,i-tRow);
                
                  else if (i>=prevtRow && i<=prevbRow && j>=prevlCol && j<=prevrCol) 
                      (*outY)(j,i)=(*prevY)(j-prevlCol,i-prevtRow);
            
                  else (*outY)(j, i)=luminance;
                  }
            }
          else {
            outFrame = pfsio.createFrame(prevWidth, prevHeight);
            outFrame->createXYZChannels(outX, outY, outZ);
            int size=prevWidth*prevHeight;
            for (int i=0; i<size; i++ ) {
                (*outX)(i)=(*prevX)(i);
                (*outY)(i)=(*prevY)(i);
                (*outZ)(i)=(*prevZ)(i);
                }
            outHeight=prevHeight;
            outWidth=prevWidth;
            }
          }
      else throw pfs::Exception("Missing X, Y, Z channels in the PFS stream");

        pfsio.freeFrame(inFrame);
      if(frame_no) pfsio.freeFrame(prevFrame);
      frame_no++;
   
      } // end for

    if(finish) break;
    if(pipes) {
      pfsio.writeFrame(outFrame, stdout);
      pfsio.freeFrame(outFrame);
      frame_no=0;
      }
    } // end while

if(!pipes) {
    pfsio.writeFrame(outFrame, stdout);
    pfsio.freeFrame(outFrame);
    }

for (int i=0; i<pipe_no; i++) it.closeFrameFile(ff[i]);
free(ff);
}


int main (int argc, char* argv[])
{
try {
    pfscat(argc, argv);
    }

catch (pfs::Exception ex) {
    fprintf (stderr, PROG_NAME " error: %s\n", ex.getMessage());
    return EXIT_FAILURE;
    }

catch (QuietException ex) {
    return EXIT_FAILURE;
    }
     
return EXIT_SUCCESS;

}

Generated by  Doxygen 1.6.0   Back to index