/*
* $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