Codebase list imview / eba15666-00c2-4d63-af5d-caf07788990a/main imageIO.hxx
eba15666-00c2-4d63-af5d-caf07788990a/main

Tree @eba15666-00c2-4d63-af5d-caf07788990a/main (Download .tar.gz)

imageIO.hxx @eba15666-00c2-4d63-af5d-caf07788990a/mainraw · history · blame

/*
 * $Id: imageIO.hxx,v 4.9 2008/10/27 15:34:11 hut66au Exp $
 *
 * Imview, the portable image analysis application
 * http://www.cmis.csiro.au/Hugues.Talbot/imview
 * ----------------------------------------------------------
 *
 *  Imview is an attempt to provide an image display application
 *  suitable for professional image analysis. It was started in
 *  1997 and is mostly the result of the efforts of Hugues Talbot,
 *  Image Analysis Project, CSIRO Mathematical and Information
 *  Sciences, with help from others (see the CREDITS files for
 *  more information)
 *
 *  Imview is Copyrighted (C) 1997-2001 by Hugues Talbot and was
 *  supported in parts by the Australian Commonwealth Science and 
 *  Industry Research Organisation. Please see the COPYRIGHT file 
 *  for full details. Imview also includes the contributions of 
 *  many others. Please see the CREDITS file for full details.
 *
 *  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, USA.
 * */

/*------------------------------------------------------------------------
 *
 * the imageIO class
 *
 * This class allows to read image files, determines the image format
 * and loads the image into memory.
 *
 * At this point only RGB and grey-level images are allowed
 * the formats that are understood are:
 *    JPEG
 *    GIF
 *    TIFF
 *    Z-IMAGE
 *
 * Hugues Talbot    28 Oct 1997
 *      
 *-----------------------------------------------------------------------*/

#ifndef IMAGEIO_H
#define IMAGEIO_H

#include <imcfg.h>
#include <vector>    // STL
#include <string>
#include <stdlib.h>

#include "imnmspc.hxx" // namespace definition, if required

#ifdef HAVE_PTHREADS
#include "server/semaphore.hxx"
#endif

#include "machine.hxx"

using std::vector;
using std::string;

// recognized format

#define IMAGEIO_TOOSMALL    -4
#define IMAGEIO_NOTHERE     -3
#define IMAGEIO_UNREADABLE  -2
#define IMAGEIO_UNKNOWN     -1
#define IMAGEIO_RAW          0  // this means: no format at all
#define IMAGEIO_JPEG         1
#define IMAGEIO_TIFF         2
#define IMAGEIO_ZIMAGE       3  // the world-famous Zimage format
#define IMAGEIO_GIF          4
#define IMAGEIO_SCILIMAGE    5
#define IMAGEIO_PNM          6
#define IMAGEIO_PS           7  // postcript, thanks to GS.
#define IMAGEIO_MAT5         8  // MATLAB level 5 MAT-file format
#define IMAGEIO_PNG          9
#define IMAGEIO_SOCKET      10  // coming from a socket
#define IMAGEIO_MAGICK      11  // read through the ImageMagick library
#define IMAGEIO_METAIMAGE   12

#define HEADER_LENGTH       128 // number of bytes to read when
                                // determining the file format

typedef long (rot3dtransf)(int x, int y, int z);

// this is a base class.
class imageIO {
public:
    imageIO();
    ~imageIO();
    int imageFormat(const char *filename);
    int read(const char *filename, int frame=0); // reads the data in
    bool isOverlay(const char *filename); // decide whether a file is an overlay
    int readOverlay(const char *filename); // overlay on top of existing image
    int renderOverlay(const char *filename, void *p, int imspp, int start[3], int end[3], pixtype thepixtype);
    int getNbFrames(const char *filename); // go get the number of frames
    int applyCurrentCLUT(void); // apply the known clut is present
    int applyCLUTtoCurrentImage(const char *CLUTpath, bool useRaw = false);
    int saveToRawBuffers(bool keepGreyIfPossible);
    // double parameters and the maps are redundant only for
    // CHAR images.
    void setOverlay(uchar *buf);
    int setPixelInOverlay(int index, uchar value);
    int write(const char *filename, int format = 0);
    int wholeImage(uchar **R, uchar **G, uchar **B);
    int subsetImage(uchar **R, uchar **G, uchar **B, int &bx, int &by, int &bw, int &bh);
    int subsetForBH(vector<BHPoint> &v, int Xcomp, int Ycomp,
            double &minXval, double &minYval,
            double &maxXval, double &maxYval);
    unsigned char *imageData(void) {return imdata;}
    int imageWidth(void) {return currImgWidth;}
    int imageHeight(void) {return currImgHeight;}
    int imageThickness(void) {return currImgThickness;}
    int imageDepth(void) {return imspp;}
    char *getClutNameIfPresent(const char *impath);
    int checkForClut(const char *clutName, const char *imageName, uchar theCLUT[][256]);
    char *getRawDataInfo(int xpos, int ypos);
    char *getRawDataInfo(int xpos, int ypos, int zpos);
    double *getRawDataVector(int xpos, int ypos, int *nb);
    double *get3DRawDataVector(int xpos, int ypos, int *nb);
    void getLineDataVectors(int X2, int Y2, int X, int Y,
                double *&red, double *&green, double *&blue,
                int &nb);
    int  hasRawData(void);
    void setImData(unsigned char *p);
    void applyImageParameters(IMAGEPARM *p=0, const char *imname = 0, char *lutname = 0, bool keepgamma = false);
    // transforms
    void rotateRight(void);
    void rotateLeft(void);
    void rotate180(void);
    void flipv(void);
    void fliph(void);
    void rotate3Dup(void);
    void rotate3Ddown(void);
    // messaging to GUI <-> image server
    void pleaseDisplay(const string &us);
    int  checkDisplay(string &as);
    IMAGE_HEADER *findHeader(unsigned int id);
    IMAGE_HEADER *findHeader(const char *name);
    void closeHeader(unsigned int id);
    void closeHeader(const char *fname);
    
    // quick functions
    int  getCurrZpos(void) { return currZpos; }
    int  getCurrImgThickness(void) { return currImgThickness; }
    int  getXOffset(void) { return xOffset;}
    int  getYOffset(void) { return yOffset;}
    int  getZOffset(void) { return zOffset;}
    int  getCurrImgNbComps(void) { return currImgNbComps; }
    int  getCurrImgNbFrames(void) { return currImgNbFrames; }
    int  getCurrImgFrame(void) { return currFrame;}
    int  getCurrImgNbSamples(void) { return currImgNbSamples;}
    const char *getImgDesc(void) {return imgDesc; }
    pixtype getCurrImgPixType(void) { return currPixType; }
    imgtype getCurrImgImgType(void) { return currImgType; }
    void **getCurrBuffp(void) { return currBuffp; }
    const char *getImName() const {return imName;}
    void setImName(const char *Name) {imName = Name;}
    void setCurrBuffp(void **p, bool untouchable=false) {
    if (currBuffp != 0) freeCurrentBuffers();
    currBuffp = p;
    dontFreeBuffers = untouchable; // are these buffer freeable?
    }
    void setCurrImgWidth(int w) {currImgWidth = w;}
    void setCurrImgHeight(int h) {currImgHeight = h;}
    void setCurrImgThickness(int t) {currImgThickness = t;}
    void setXOffset(int x) {xOffset = x;}
    void setYOffset(int y) {yOffset = y;}
    void setZOffset(int z) {zOffset = z;}
    void setCurrZPos(int z) {currZpos = z;}
    void setCurrImgType(imgtype i) {currImgType = i;}
    void setCurrPixType(pixtype p) {currPixType = p;}
    void setCurrImgNbComps(int n) {currImgNbComps = n;}
    void setCurrImgNbFrames(int f) {currImgNbFrames = f;}
    void setCurrFrame(int ff) {currFrame = ff;}
    void setCurrImgSpp(int n) { imspp = n; }
    void setCurrImgNbSamples(int n) {   currImgNbSamples = n; }
    void setCurrImgColourMap(unsigned short **cmap) {currImgColourMap = cmap;}
    void setCurrImgNbColours(long nbcols) {currImgNbColours = nbcols;}
    void setImgDesc(const char *str) { imgDesc = str; }
    /* avoid lengthy calculation at each change of slice diaplay */
    void flush_minmax_cache(void) {minval_cache=maxval_cache=0.0;}
    void minmax_set_cache(double amin, double amax) {
        minval_cache = amin;
        maxval_cache = amax;
    }
    void minmax_get_cache(double &amin, double &amax) {
        amin = minval_cache;
        amax = maxval_cache;
    }
    
    bool minmax_iscached(void) {
        return ((minval_cache != maxval_cache) || (minval_cache != 0.0));
    }

    const char *typeName(pixtype atype);
    const char *imgTypeName(imgtype atype);
    size_t typeSize(pixtype whatType);
    void  freeRawBuffers(void *p, int imspp); // a helper function for I/O
    void  saveGammaParameters(double *x0, double *y0,
                  double *x1, double *y1,
                  double *gamma,
                  uchar *Rmap, uchar *Gmap, uchar *Bmap);
    
private:
    unsigned char   *imdata; // for display
    unsigned char   *overlay; // to display things on top of images.
    const char      *imgDesc, *imName, *currImgCLUTPath;
    int              imspp, ovlspp;
    // messaging GUI <-> server
    vector <string>     imgToDisplay;
    Semaphore           access_imgvect;
    void             freeCurrentBuffers(void);
    int              xOffset, yOffset, zOffset;
    int              currImgNbFrames;
    int              currImgNbComps; // number of components =  # of independent images in one file ; imview supports 1
    int              currImgNbSamples; // number of samples per pixels (usually 1, 3 or many)
    int              currImgWidth, currImgHeight, currImgThickness;
    int              currZpos;
    int              currComp, currFrame;
    long             buffZOffset;
    imgtype          currImgType;
    pixtype          currPixType;
    unsigned short **currImgColourMap;
    long             currImgNbColours;
    void           **currBuffp;
    // some bools
    bool             currImgHasCLUT, currImgHasGamma, currImgHasOverlay;
    bool             dontFreeBuffers, imageHasNoFile; // for sockets, their data is memory only.
    // for keeping the gamma information
    double           mx0[3], my0[3], mx1[3], my1[3], mgammas[3];
    uchar             mRmap[256], mGmap[256], mBmap[256];
    bool             hasGmap;
    // min/max value cache
    double           minval_cache, maxval_cache;

    // private methods
//private:
    // needed for Bresenham
    int              dx_, dy_, incx_, incy_, xpos_, ypos_;
    int              e_, i_, inc1_, inc2_, sizex_;
    // utility functions
    int  renderPSFile(const char *filename, int frame);
    // line functions
    int  getRawDataPoint(long delta, double &G);
    int  getRawDataPoint(long delta, double &R, double &G, double &B);
    int  bresinit(int x1, int y1, int x2, int y2);
    int  bresgetnext(void);
    // the conversion methods
    void translateForDisplay(bool keepOverlay = false);
    void convertBINARY(int *imDepth, uchar **outbuf);
    void convertUINT1(int *imDepth, uchar **outbuf, bool freeBuffers=true, bool interpretRGB=true);
    void convertUINT1withLUT(int *imDepth, uchar **outbuf, uchar CLUT[][256]);
    void convertDirectLUT(int *imDepth, uchar **outbuf, uchar CLUT[][256]);
    void convertINT4withLUT_wraparound(int *imDepth, uchar **outbuf, uchar CLUT[][256]);

    // rotations
    void rotate3Dgeneric(rot3dtransf *myrotf, long nbplanepix);

#ifdef HAVE_MEMBER_TEMPLATES
#  ifdef HAVE_TEMPLATE_KEYWORD_QUALIFIER
    template <class T> void convertWithLUT_wraparound(int *imDepth, uchar **outbuf, void *CLUT);
    template <class T> void convert(int *imDepth, uchar **outbuf,
                                    bool freeBuffers=true, bool makeChar=true,
                                    bool interpretRGB=true, bool minmaxAllSamples=true,
                                    bool minmaxAllSlices=true
                                    );
    template <class T> void applyGamma(int *imDepth, uchar **outbuf,
                       double *startX, double *startY,
                       double *endX, double *endY, double *gamma);
#  else
    template <class T> void convertWithLUT_wraparound(int *imDepth, uchar **outbuf, void *CLUT, T dummy = 0);
    template <class T> void convert(int *imDepth, uchar **outbuf,
                    bool freeBuffers=true, bool makeChar=true,
                    bool interpretRGB=true, bool minmaxAllSamples=true,
                                    bool minmaxAllSlices=true,
                    T dummy = 0);
    template <class T> void applyGamma(int *imDepth, uchar **outbuf,
                       double *startX, double *startY,
                       double *endX, double *endY, double *gamma, T dummy = 0);

#  endif
#else // HAVE_MEMBER_TEMPLATES
    // these will go eventually
    void convertINT2(int *imDepth, uchar **outbuf); 
    void convertUINT2(int *imDepth, uchar **outbuf);
    void convertINT4(int *imDepth, uchar **outbuf);
    void convertUINT4(int *imDepth, uchar **outbuf);
    void convertDOUBLE(int *imDepth, uchar **outbuf);
    void applyGamma_UINT2(int *imDepth, uchar **outbuf,
                          double *startX, double *startY,
                          double *endX, double *endY, double *gamma);

    void applyGamma_INT4(int *imDepth, uchar **outbuf,
             double *startX, double *startY,
             double *endX, double *endY, double *gamma);
    
    void applyGamma_DBL(int *imDepth, uchar **outbuf,
            double *startX, double *startY,
            double *endX, double *endY, double *gamma);
#endif  //   HAVE_MEMBER_TEMPLATES

    int applyGammaToCurrentImage(void);
    int applyGammaToCurrentImage(double *x0, double *y0,
                 double *x1, double *y1,
                 double *gammas,
                 uchar *Rmap, uchar *Gmap = 0, uchar *Bmap = 0);
    void applyGamma_UINT1(int *imDepth, uchar **outbuf, uchar *Rmap, uchar *Gmap, uchar *Bmap);
    int applyOverlayToCurrentImage(void);

};

#endif