TPCCLIB
Loading...
Searching...
No Matches
libtpcimgp.h File Reference

Header file for libtpcimgp. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
#include <float.h>
#include <unistd.h>
#include <locale.h>
#include <time.h>
#include "libtpcmisc.h"
#include "libtpcimgio.h"

Go to the source code of this file.

Data Structures

struct  point
 

Macros

#define PET_GRAYSCALE   1
 
#define PET_GRAYSCALE_INV   2
 
#define PET_RAINBOW   3
 
#define PET_RAINBOW_WB   4
 

Functions

int imgArithm (IMG *img1, IMG *img2, char operation, float ulimit, int verbose)
 
int imgArithmConst (IMG *img, float operand, char operation, float ulimit, int verbose)
 
int imgArithmFrame (IMG *img1, IMG *img2, char operation, float ulimit, int verbose)
 
int imgLn (IMG *img)
 
int imgLog10 (IMG *img)
 
int imgAbs (IMG *img)
 
int imgInv (IMG *img)
 
int imgFrameIntegral (IMG *img, int first, int last, IMG *iimg, int verbose)
 
int imgRawCountsPerTime (IMG *img, int operation)
 
int imgConvertUnit (IMG *img, char *unit)
 
int imgAUMC (IMG *img, IMG *oimg, int verbose)
 
int imgMRT (IMG *img, IMG *oimg, int verbose)
 
int imgAverageTAC (IMG *img, float *tac)
 
int imgAverageMaskTAC (IMG *img, IMG *timg, float *tac)
 
int imgAverageAUC (IMG *img, float *avgauc)
 
int imgMaskTAC (IMG *img, IMG *mask, double *tac, int verbose)
 
int imgMaskRoiNr (IMG *img, INTEGER_LIST *list)
 
int imgVoiMaskTAC (IMG *img, IMG *mask, int mv, double *tac, int verbose)
 
int imgGaussianFIRFilter (IMG *img, float xsd, float ysd, float zsd, double tolerance, int verbose)
 
int imgGaussianAMFilter (IMG *img, float xsd, float ysd, float zsd, int passNr, double tolerance, int verbose)
 
int filterAMGaussian (double *a, int n, int passNr, double nu, double scale, int termNr)
 
int filterHSSBE (int n, int r)
 
double filterAMLB (double *a, int n, double nu, int termNr)
 
int imgGaussianEBoxFilter (IMG *img, float xsd, float ysd, float zsd, int passNr, int verbose)
 
int filterEbox (double *a, int n, double wob, double wib, int rib, int passNr)
 
int fMean1DFilter (float *data, const int n, const int s)
 
int imgMeanFilter (IMG *img, int xn, int yn, int zn, int tn, int verbose)
 
void imgFlipHorizontal (IMG *img)
 
void imgFlipVertical (IMG *img)
 
void imgFlipPlanes (IMG *img)
 
int imgFlipRight (IMG *img)
 
int imgFlipAbove (IMG *img)
 
int imgMeanZ (IMG *img1, IMG *img2)
 
int imgFramesCheck (IMG *img, int verbose)
 
int imgFrameGapFill (IMG *img, int verbose)
 
int imgDeleteFrameOverlap_old (IMG *img)
 
int imgDeleteFrameOverlap (IMG *img)
 
int imgSmoothOverFrames (IMG *img, int n)
 
int imgGetFrameDiff (IMG *img, IMG *dimg, IMG *mimg, int verbose)
 
int imgGetFrameDyn (IMG *img, IMG *iimg, IMG *dimg, int verbose)
 
int imgSetScanner (IMG *img, int scanner_type)
 
int imgsegmThresholdMask (IMG *img, float minValue, float maxValue, IMG *timg)
 
int imgsegmThresholdByMask (IMG *img, IMG *template, float minValue, float maxValue)
 
int imgsegmThreshold (IMG *img, float minValue, float maxValue)
 
int imgsegmMaskToCluster (IMG *img)
 
int imgsegmFindMaxOutsideClusters (IMG *sumimg, IMG *cluster, float *max, int *plane, int *row, int *col)
 
int imgsegmClusterExpand (IMG *cluster, IMG *sum, IMG *dynamic, int clusterID, int pi, int ri, int ci, int pj, int rj, int cj, float CVlim, float CClim, int verbose)
 
float imgsegmPearson (float *x, float *y, long long nr)
 
int imgsegmClusterMean (IMG *dimg, IMG *cimg, int clusterID, float *avg, int verbose)
 
int imgsegmCheckNeighbours (IMG *cimg, int pi, int ri, int ci)
 
int imgsegmFindBestNeighbour (IMG *dimg, IMG *cimg, int pi, int ri, int ci)
 
int imgsegmSimilar (IMG *input, int smoothDim, int smoothNr, IMG *output, int verbose)
 
int imgsegmCalcMRL (float y1[], float y2[], long long n)
 
int imgThresholding (IMG *img, float threshold_level, long long *thr_nr)
 
int imgThresholdingLowHigh (IMG *img, float lower_threshold_level, float upper_threshold_level, IMG *timg, long long *lower_thr_nr, long long *upper_thr_nr)
 
int imgOutlierFilter (IMG *img, float limit)
 
int imgThresholdMaskCount (IMG *img, float minValue, float maxValue, IMG *timg, long long *count)
 
int imgThresholdMask (IMG *img, float minValue, float maxValue, IMG *timg)
 
int imgThresholdByMask (IMG *img, IMG *templt, float thrValue)
 
void imgCutoff (IMG *image, float cutoff, int mode)
 
int imgRegionGrowingByThreshold (IMG *img, const int sz, const int sy, const int sx, float lthr, float uthr, IMG *mask, int verbose)
 
int tiffWriteImg (IMG *img, int plane, int frame, float *maxvalue, int colorscale, char *fname, int matXdim, int matYdim, int verbose, char *status)
 
int img2cube (IMG *img1, int dim, IMG *img2)
 
void imgScale (IMG *src, IMG *targ, float zoom, int method)
 
void integerScale (int frame, float ***src, float **targ, int width, int height, int zoom)
 
int imgShrink (IMG *img1, IMG *img2, int doz)
 
int imgSwell (IMG *img1, IMG *img2, int doz)
 
long long imgMaskCount (IMG *img)
 
int imgMaskErode (IMG *img, IMG *se)
 
int imgMaskDilate (IMG *img, IMG *se)
 
int imgStructuringElement (IMG *img, const int structuring_element, int verbose)
 
void imgMaskInvert (IMG *img)
 
int imgMaskConjunction (IMG *mask1, IMG *mask2)
 
int imgMaskRegionLabeling (IMG *mask1, IMG *mask2, int *n, int verbose)
 
int imgMaskFloodFill (IMG *m, int sz, int sy, int sx, int label, long long *n, int verbose)
 
int imgMaskCloak (IMG *img, int dim, float id)
 
int pRound (float)
 
float getDistance (point, point)
 
float getAngle (point, point)
 

Detailed Description

Header file for libtpcimgp.

Author
Vesa Oikonen

Definition in file libtpcimgp.h.

Macro Definition Documentation

◆ PET_GRAYSCALE

#define PET_GRAYSCALE   1

PET image color scale

Definition at line 32 of file libtpcimgp.h.

Referenced by tiffWriteImg().

◆ PET_GRAYSCALE_INV

#define PET_GRAYSCALE_INV   2

PET image color scale

Definition at line 34 of file libtpcimgp.h.

◆ PET_RAINBOW

#define PET_RAINBOW   3

PET image color scale

Definition at line 36 of file libtpcimgp.h.

Referenced by tiffWriteImg().

◆ PET_RAINBOW_WB

#define PET_RAINBOW_WB   4

PET image color scale

Definition at line 38 of file libtpcimgp.h.

Referenced by tiffWriteImg().

Function Documentation

◆ filterAMGaussian()

int filterAMGaussian ( double * a,
int n,
int passNr,
double nu,
double scale,
int termNr )
extern

1D Alvarez-Mazorra Gaussian filtering.

See also
imgGaussianAMFilter
Returns
If an error is encountered, function returns a non-zero value. Otherwise 0 is returned.
Parameters
aPointer to source data array, overwritten by the results.
nSample number.
passNrNumber of filtering passes; usually 4.
nuFilter coefficient.
scaleFilter scale.
termNrNumber of terms needed to approximate the sum with required accuracy for the left boundary.

Definition at line 314 of file imgfilter.c.

327 {
328 if(a==NULL || n<3) return(1);
329 if(!(nu>0.0)) return(2);
330 if(passNr<1) passNr=4;
331 if(termNr<6) termNr=6;
332
333 /* Scale the data. */
334 for(int i=0; i<n; i++) a[i]*=scale;
335
336 /* Loop through the passes of filtering */
337 for(int pass=0; pass<passNr; pass++) {
338 a[0]=filterAMLB(a, n, nu, termNr);
339 for(int i=1; i<n; i++) a[i]+=nu*a[i-1]; // causal filter
340 a[n-1]/=(1.0-nu);
341 for(int i=n-1; i>0; i--) a[i-1]+=nu*a[i]; // anti-causal filter
342 }
343 return(0);
344}
double filterAMLB(double *a, int n, double nu, int termNr)
Definition imgfilter.c:372

Referenced by imgGaussianAMFilter().

◆ filterAMLB()

double filterAMLB ( double * a,
int n,
double nu,
int termNr )
extern

Left boundary for 1D Alvarez-Mazorra Gaussian filtering.

See also
filterAMGaussian, filterHSSBE
Returns
The sum approximating the first filtered sample value, or NaN in case of an error.
Parameters
aPointer to source data array; not modified.
nSample number.
nuFiltering parameter.
termNrNumber of terms.

Definition at line 372 of file imgfilter.c.

381 {
382 if(a==NULL || n<1) return(nan(""));
383 double h=1.0, sum=a[0];
384 for(int m=1; m<termNr; m++) {
385 h*=nu;
386 sum+=h*a[filterHSSBE(n, -m)];
387 }
388 return(sum);
389}
int filterHSSBE(int n, int r)
Definition imgfilter.c:352

Referenced by filterAMGaussian().

◆ filterEbox()

int filterEbox ( double * a,
int n,
double wob,
double wib,
int rib,
int passNr )
extern

1D extended box filtering .

See also
imgFast1DGaussianFilter
Returns
If an error is encountered, function returns a non-zero value. Otherwise 0 is returned.
Parameters
aPointer to source data array.
nSample number.
wobWeight of the outer box.
wibWeight of the inner box.
ribRadius of the inner box.
passNrNumber of filtering passes.

Definition at line 558 of file imgfilter.c.

571 {
572 if(a==NULL || n<3 || wob<=0.0 || wib<=0.0 || rib<0) return(1);
573 double buf[n];
574 for(int pass=0; pass<passNr; pass++) {
575 double accum=0.0;
576 for(int i=-rib; i<=rib; i++) accum+=a[filterHSSBE(n, i)];
577 buf[0]=wob*(a[filterHSSBE(n, rib+1)] + a[filterHSSBE(n, -rib-1)]) + (wob+wib)*accum;
578 accum=buf[0];
579 for(int i=1; i<n; i++) {
580 accum += wob*(a[filterHSSBE(n, i+rib+1)] - a[filterHSSBE(n, i-rib-2)])
581 + wib*(a[filterHSSBE(n, i+rib)] - a[filterHSSBE(n, i-rib-1)]);
582 buf[i]=accum;
583 }
584 for(int i=0; i<n; i++) a[i]=buf[i];
585 }
586 return(0);
587}

Referenced by imgGaussianEBoxFilter().

◆ filterHSSBE()

int filterHSSBE ( int n,
int r )
externinline

Half-sample symmetric boundary extension.

See also
filterEbox, filterAMLB
Returns
Reflected sample in array[0..n-1].
Parameters
nSample number.
rRequested sample, possibly outside array[0..N-1].

Definition at line 352 of file imgfilter.c.

357 {
358 while(1) {
359 if(r<0) r=-1-r;
360 else if(r>=n) r=2*n-1-r;
361 else break;
362 }
363 return(r);
364}

Referenced by filterAMLB(), filterEbox(), and imgGaussianFIRFilter().

◆ fMean1DFilter()

int fMean1DFilter ( float * data,
const int n,
const int s )
extern

In-place mean 1D-filtering.

See also
imgMeanFilter
Returns
If an error is encountered, function returns a non-zero value. Otherwise 0 is returned.
Parameters
dataPointer to array to be filtered.
nArray size.
sFilter size; should be odd number 3,5,7,... but not verified here.

Definition at line 595 of file imgfilter.c.

602 {
603 if(data==NULL || n<1 || s<1) return(1);
604 float buf[n];
605 for(int i=0; i<n; i++) buf[i]=data[i];
606 for(int i=0; i<n; i++) {
607 data[i]=0.0;
608 int a=i-(s-1)/2; if(a<0) a=0;
609 int b=i+(s-1)/2; if(b>=n) b=n-1;
610 int m=1+b-a;
611 for(int j=a; j<=b; j++) data[i]+=buf[j];
612 data[i]/=(float)m;
613 }
614 return(0);
615}

Referenced by imgMeanFilter().

◆ getAngle()

float getAngle ( point begin,
point center )
extern

Calculates xy-projection of angle FCX in degrees, where F=first point, C=centre point and X=point with higher x coordinate (y and z coordinate remain the same).

This is used to calculate polar angle with two dimensional points (z=constant).

Returns
Angle first - centre - x in degrees (0-360) and -360.0 if first point is equal to centre point.
See also
getDistance
Parameters
beginFirst point.
centerCentre point.

Definition at line 55 of file point.c.

60 {
61 float dx, dy;
62 dx = begin.x - center.x; // Difference in x coordinates.
63 dy = begin.y - center.y; // Difference in y coordinates.
64
65 // Check trivial cases.
66 if(dx == 0.0){
67 if(dy == 0.0) return -360.0;
68 if(dy > 0.0) return 90.0;
69 else return 270.0;
70 }
71 if(dy==0.0){
72 if(dx > 0.0) return 0.0;
73 else return 180.0;
74 }
75
76 // If it was not a trivial case, then calculate angle in...
77 // ...the second and the third quarter.
78 if(dx<0.0) return 180.0 + atan(dy/dx)*180.0/M_PI;
79
80 // ...the first quarter.
81 if(dy>0.0) return atan(dy/dx)*180.0/M_PI;
82
83 // ...the fourth quarter.
84 return 360.0 + atan(dy/dx)*180.0/M_PI;
85}
float y
Definition libtpcimgp.h:45
float x
Definition libtpcimgp.h:43

◆ getDistance()

float getDistance ( point begin,
point end )
extern

Calculate distance between points

See also
getAngle
Returns
Distance.
Parameters
beginFirst point
endSecond point

Definition at line 31 of file point.c.

36 {
37 float dx, dy, dz;
38
39 dx = begin.x - end.x; // Difference in x coordinates.
40 dy = begin.y - end.y; // Difference in y coordinates.
41 dz = begin.z - end.z; // Difference in z coordinates.
42 return sqrt(dx*dx + dy*dy + dz*dz);
43}
float z
Definition libtpcimgp.h:47

◆ img2cube()

int img2cube ( IMG * img1,
int dim,
IMG * img2 )
extern

Resample image to cubic image volume, where all three dimensions are the same, with cubic voxel sizes. Note that some smoothing occurs in the process, therefore the use of this function should be limited to illustrations of image data.

See also
imgFlipHorizontal, imgFlipVertical, imgFlipAbove, imgScale, imgSwell, imgShrink
Returns
Returns 0 if successful, otherwise <>0.
Parameters
img1Pointer to IMG to be resliced; this image is not modified.
dimNew dimension; enter 0 to use the largest dimension in image.
img2Pointer to initiated IMG where resliced data will be stored.

Definition at line 16 of file imgtransform.c.

23 {
24 int ret, n, testf;
25 int xi, yi, zi, xj, yj, zj, fi, xp, yp, zp;
26 double xsize, ysize, zsize, newsize;
27 double xdist, ydist, zdist;
28 double xpc, ypc, zpc, xd, yd, zd;
29 double w, wsum, d;
30
31 if(IMG_TEST>0) printf("img2cube(img1, img2)\n");
32 if(img1->status!=IMG_STATUS_OCCUPIED) return(1);
33 if(img2->status==IMG_STATUS_OCCUPIED) imgEmpty(img2);
34
35 if(IMG_TEST>1)
36 printf("original dimensions (x,y,z) := %d,%d,%d\n", img1->dimx, img1->dimy, img1->dimz);
37 if(dim<1) {
38 /* Get the largest dimension of original image volume */
39 dim=img1->dimz; n=0;
40 if(img1->dimx>dim) {dim=img1->dimx; n++;}
41 if(img1->dimy>dim) {dim=img1->dimy; n++;}
42 }
43 if(IMG_TEST>1) printf("new dimensions (x,y,z) := %d,%d,%d\n", dim, dim, dim);
44 testf=dim*dim*dim/10;
45
46 /* Allocate memory for the new IMG */
47 ret=imgAllocate(img2, dim, dim, dim, img1->dimt);
48 if(ret) return(10+ret);
49 imgCopyhdr(img1, img2);
50
51 /* Calculate the physical extensions of original image volume */
52 xsize=img1->dimx*(img1->sizex + img1->gapx);
53 ysize=img1->dimy*(img1->sizey + img1->gapy);
54 zsize=img1->dimz*(img1->sizez + img1->gapz);
55 if(IMG_TEST>1) printf("original image size (x,y,z) in mm := %g,%g,%g\n", xsize, ysize, zsize);
56 /* New image volume will be a cube of highest size of those */
57 newsize=xsize; n=0;
58 if(ysize>newsize) {newsize=ysize; n++;}
59 if(zsize>newsize) {newsize=zsize; n++;}
60 if(IMG_TEST>1) {
61 printf("original image size (x,y,z) in mm := %g,%g,%g\n",
62 xsize, ysize, zsize);
63 if(n>0) printf("new image size (x,y,z) in mm:= %g,%g,%g\n",
64 newsize, newsize, newsize);
65 else printf("original image size needs not to be changed.\n");
66 }
67 img2->gapx=img2->gapy=img2->gapz=0.0;
68 img2->sizex=img2->sizey=img2->sizez=newsize/(double)dim;
69
70 /* Resample the image volume */
71 n=0;
72 for(zj=0; zj<dim; zj++) for(yj=0; yj<dim; yj++) for(xj=0; xj<dim; xj++) {
73 if(IMG_TEST>3 && n%testf==0) printf("zj=%d yj=%d xj=%d\n", zj, yj, xj);
74 /* Calculate the distance of this voxel from the mid of new image volume */
75 xdist=((double)xj+0.5)*img2->sizex - 0.5*newsize;
76 ydist=((double)yj+0.5)*img2->sizey - 0.5*newsize;
77 zdist=((double)zj+0.5)*img2->sizez - 0.5*newsize;
78 if(IMG_TEST>3 && n%testf==0)
79 printf(" xdist=%g ydist=%g zdist=%g\n", xdist, ydist, zdist);
80 /* The place in coordinates of original image */
81 xpc=(0.5*xsize+xdist)/(img1->sizex + img1->gapx);
82 ypc=(0.5*ysize+ydist)/(img1->sizey + img1->gapy);
83 zpc=(0.5*zsize+zdist)/(img1->sizez + img1->gapz);
84 /* Inside which voxel it resides? */
85 xp=(int)(xpc+0.5); yp=(int)(ypc+0.5); zp=(int)(zpc+0.5);
86 if(IMG_TEST>3 && n%testf==0)
87 printf(" inside pixel %d,%d,%d\n", xp, yp, zp);
88 /* Calculate 1/distance-weighted average of 3x3x3 pixels around it */
89 for(fi=0; fi<img1->dimt; fi++) img2->m[zj][yj][xj][fi]=0.0;
90 wsum=0.0;
91 for(zi=zp-1; zi<=zp+1; zi++)
92 for(yi=yp-1; yi<=yp+1; yi++) for(xi=xp-1; xi<=xp+1; xi++) {
93 /* Distance between voxels */
94 xd=(0.5+xi)-xpc; yd=(0.5+yi)-ypc; zd=(0.5+zi)-zpc;
95 d=xd*xd+yd*yd+zd*zd; //if(d>0.0) d=sqrt(d); else d=0.0;
96 if(IMG_TEST>3 && n%testf==0)
97 printf(" distance^2 from (%d,%d,%d) := %g\n", xi, yi, zi, d);
98 /* Add weight to the weight sum */
99 w=exp(-d); wsum+=w;
100 if(IMG_TEST>3 && n%testf==0) printf(" weight := %g\n", w);
101 /* If voxel is inside the image, add value to the sum */
102 if(zi>=0 && yi>=0 && xi>=0 && zi<img1->dimz && yi<img1->dimy && xi<img1->dimx) {
103 for(fi=0; fi<img1->dimt; fi++) {
104 img2->m[zj][yj][xj][fi]+=w*img1->m[zi][yi][xi][fi];
105 }
106 }
107 }
108 /* Divide the sum with sum weight */
109 for(fi=0; fi<img1->dimt; fi++) img2->m[zj][yj][xj][fi]/=wsum;
110 if(IMG_TEST>3 && n%testf==0)
111 printf(" weighted avg in 1st frame := %g\n", img2->m[zj][yj][xj][0]);
112 n++;
113 }
114
115 return 0;
116}
int IMG_TEST
Definition img.c:6
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
Definition img.c:194
int imgCopyhdr(IMG *image1, IMG *image2)
Definition img.c:471
void imgEmpty(IMG *image)
Definition img.c:121
#define IMG_STATUS_OCCUPIED
float sizex
unsigned short int dimx
float gapx
float **** m
char status
unsigned short int dimt
float sizey
unsigned short int dimz
unsigned short int dimy
float gapy
float gapz
float sizez

◆ imgAbs()

int imgAbs ( IMG * img)
extern

Replace IMG data values by their absolute values.

See also
imgLog10, imgLn, imgArithm, imgMatch
Returns
Returns 0, if ok.
Parameters
imgPointer to IMG data.

Definition at line 292 of file imgarithm.c.

295 {
296 if(img->status<IMG_STATUS_OCCUPIED) return(1);
297 if(img->dimt<1 || img->dimz<1 || img->dimy<1 || img->dimx<1) return(2);
298 for(int pi=0; pi<img->dimz; pi++)
299 for(int yi=0; yi<img->dimy; yi++)
300 for(int xi=0; xi<img->dimx; xi++)
301 for(int fi=0; fi<img->dimt; fi++)
302 img->m[pi][yi][xi][fi]=fabsf(img->m[pi][yi][xi][fi]);
303 return(0);
304}

◆ imgArithm()

int imgArithm ( IMG * img1,
IMG * img2,
char operation,
float ulimit,
int verbose )
extern

Simple arithmetics between matching IMG planes and frames. Specify the operation as one of characters +, -, /, :, *, ., x. Results that are higher than ulimit are set to ulimit.

See also
imgArithmConst, imgArithmFrame, imgRawCountsPerTime, imgConvertUnit, imgSS
Returns
Returns 0, if ok.
Parameters
img1The first IMG data.
img2The second IMG data.
operationOperation, one of the characters +, -, /, :, *, ., x.
ulimitResults that are higher than ulimit are set to ulimit; set to <=0 if not needed.
verboseVerbose level; if <=0, then nothing is printed into stderr.

Definition at line 16 of file imgarithm.c.

27 {
28 if(verbose>0) printf("%s(img1, img2, '%c', %g, %d)\n", __func__, operation, ulimit, verbose);
29
30 /* Check the arguments */
32 if(verbose>0) fprintf(stderr, "Invalid image status.\n");
33 return(1);
34 }
35 int ret=0;
36 if(img1->dimx!=img2->dimx || img1->dimy!=img2->dimy) ret=1;
37 /* Check the plane numbers */
38 if(img1->dimz!=img2->dimz) ret=2;
39 if(ret==0) for(int pi=0; pi<img1->dimz; pi++)
40 if(img1->planeNumber[pi]!=img2->planeNumber[pi]) ret=2;
41 /* Check the frame numbers */
42 if(img1->dimt!=img2->dimt) ret=3;
43 if(ret>0) {
44 if(verbose>0) fprintf(stderr, "Image dimensions do not match.\n");
45 return(ret);
46 }
47
48 /* Operate */
49 switch(operation) {
50 case '+':
51 for(int pi=0; pi<img1->dimz; pi++) for(int yi=0; yi<img1->dimy; yi++)
52 for(int xi=0; xi<img1->dimx; xi++) for(int fi=0; fi<img1->dimt; fi++)
53 img1->m[pi][yi][xi][fi]+=img2->m[pi][yi][xi][fi];
54 break;
55 case '-':
56 for(int pi=0; pi<img1->dimz; pi++) for(int yi=0; yi<img1->dimy; yi++)
57 for(int xi=0; xi<img1->dimx; xi++) for(int fi=0; fi<img1->dimt; fi++)
58 img1->m[pi][yi][xi][fi]-=img2->m[pi][yi][xi][fi];
59 break;
60 case '/':
61 case ':':
62 for(int pi=0; pi<img1->dimz; pi++) for(int yi=0; yi<img1->dimy; yi++)
63 for(int xi=0; xi<img1->dimx; xi++) for(int fi=0; fi<img1->dimt; fi++) {
64 if(fabs(img2->m[pi][yi][xi][fi])>1.0E-5)
65 img1->m[pi][yi][xi][fi]/=img2->m[pi][yi][xi][fi];
66 else img1->m[pi][yi][xi][fi]=0.0;
67 }
68 break;
69 case '*':
70 case 'x':
71 case '.':
72 for(int pi=0; pi<img1->dimz; pi++) for(int yi=0; yi<img1->dimy; yi++)
73 for(int xi=0; xi<img1->dimx; xi++) for(int fi=0; fi<img1->dimt; fi++)
74 img1->m[pi][yi][xi][fi]*=img2->m[pi][yi][xi][fi];
75 break;
76 default:
77 if(verbose>0) fprintf(stderr, "Invalid operation.\n");
78 return(10);
79 }
80
81 /* Check for limits */
82 if(ulimit>0.0) {
83 for(int pi=0; pi<img1->dimz; pi++) for(int yi=0; yi<img1->dimy; yi++)
84 for(int xi=0; xi<img1->dimx; xi++) for(int fi=0; fi<img1->dimt; fi++)
85 if(img1->m[pi][yi][xi][fi]>ulimit) img1->m[pi][yi][xi][fi]=ulimit;
86 }
87
88 return(0);
89}
int * planeNumber

◆ imgArithmConst()

int imgArithmConst ( IMG * img,
float operand,
char operation,
float ulimit,
int verbose )
extern

Simple arithmetic between IMG and specified constant.

Specify the operation as one of characters +, -, /, :, *, ., x. Results that are higher than ulimit are set to ulimit.

See also
imgArithm, imgScale, imgInv, imgArithmFrame, imgRawCountsPerTime, imgConvertUnit
Returns
Returns 0, if ok.
Parameters
imgIMG data which is modified.
operandConstant value which is used to modify the data.
operationOperation, one of the characters +, -, /, :, *, ., x.
ulimitResults that are higher than ulimit are set to ulimit; set to <=0 if not needed.
verboseVerbose level; if <=0, then nothing is printed into stderr.

Definition at line 100 of file imgarithm.c.

111 {
112 if(verbose>0) printf("%s(img, %g, '%c', %g, %d)\n", __func__, operand, operation, ulimit, verbose);
113
114 /* Check the arguments */
115 if(img->status!=IMG_STATUS_OCCUPIED) {
116 if(verbose>0) fprintf(stderr, "Invalid image status.\n");
117 return(1);
118 }
119 switch(operation) {
120 case '+':
121 for(int pi=0; pi<img->dimz; pi++) for(int yi=0; yi<img->dimy; yi++)
122 for(int xi=0; xi<img->dimx; xi++) for(int fi=0; fi<img->dimt; fi++)
123 img->m[pi][yi][xi][fi]+=operand;
124 break;
125 case '-':
126 for(int pi=0; pi<img->dimz; pi++) for(int yi=0; yi<img->dimy; yi++)
127 for(int xi=0; xi<img->dimx; xi++) for(int fi=0; fi<img->dimt; fi++)
128 img->m[pi][yi][xi][fi]-=operand;
129 break;
130 case '/':
131 case ':':
132 if(fabs(operand)<1.0e-100) return(2);
133 for(int pi=0; pi<img->dimz; pi++) for(int yi=0; yi<img->dimy; yi++)
134 for(int xi=0; xi<img->dimx; xi++) for(int fi=0; fi<img->dimt; fi++)
135 img->m[pi][yi][xi][fi]/=operand;
136 break;
137 case '*':
138 case 'x':
139 case '.':
140 for(int pi=0; pi<img->dimz; pi++) for(int yi=0; yi<img->dimy; yi++)
141 for(int xi=0; xi<img->dimx; xi++) for(int fi=0; fi<img->dimt; fi++)
142 img->m[pi][yi][xi][fi]*=operand;
143 break;
144 default:
145 if(verbose>0) fprintf(stderr, "Invalid operation.\n");
146 return(10);
147 }
148
149 /* Check for limits */
150 if(ulimit>0.0) {
151 for(int pi=0; pi<img->dimz; pi++) for(int yi=0; yi<img->dimy; yi++)
152 for(int xi=0; xi<img->dimx; xi++) for(int fi=0; fi<img->dimt; fi++)
153 if(img->m[pi][yi][xi][fi]>ulimit) img->m[pi][yi][xi][fi]=ulimit;
154 }
155
156 return(0);
157}

Referenced by imgConvertUnit(), and imgTimeIntegral().

◆ imgArithmFrame()

int imgArithmFrame ( IMG * img1,
IMG * img2,
char operation,
float ulimit,
int verbose )
extern

Simple arithmetic between matching IMG planes and the first frame of img2.

Specify the operation as one of characters +, -, /, :, *, ., x. Results that are higher than ulimit are set to ulimit.

See also
imgArithmConst, imgArithm, imgFrameIntegral
Returns
Returns 0, if ok.
Parameters
img1IMG data which is modified.
img2Operand IMG data, only the first frame is used.
operationOperation, one of the characters +, -, /, :, *, ., x.
ulimitResults that are higher than ulimit are set to ulimit; set to <=0 if not needed.
verboseVerbose level; if <=0, then nothing is printed into stderr.

Definition at line 168 of file imgarithm.c.

179 {
180 if(verbose>0) printf("%s(img1, img2, '%c', %g, %d)\n", __func__, operation, ulimit, verbose);
181
182 /* Check the arguments */
184 if(verbose>0) fprintf(stderr, "Invalid image status.\n");
185 return(1);
186 }
187 int ret=0;
188 if(img1->dimx!=img2->dimx || img1->dimy!=img2->dimy) ret=1;
189 /* Check the plane numbers */
190 if(img1->dimz!=img2->dimz) ret=2;
191 if(ret==0) for(int pi=0; pi<img1->dimz; pi++)
192 if(img1->planeNumber[pi]!=img2->planeNumber[pi]) ret=2;
193 if(ret>0) {
194 if(verbose>0) fprintf(stderr, "Image dimensions do not match.\n");
195 return(ret);
196 }
197
198 /* Operate */
199 switch(operation) {
200 case '+':
201 for(int pi=0; pi<img1->dimz; pi++) for(int yi=0; yi<img1->dimy; yi++)
202 for(int xi=0; xi<img1->dimx; xi++) for(int fi=0; fi<img1->dimt; fi++)
203 img1->m[pi][yi][xi][fi]+=img2->m[pi][yi][xi][0];
204 break;
205 case '-':
206 for(int pi=0; pi<img1->dimz; pi++) for(int yi=0; yi<img1->dimy; yi++)
207 for(int xi=0; xi<img1->dimx; xi++) for(int fi=0; fi<img1->dimt; fi++)
208 img1->m[pi][yi][xi][fi]-=img2->m[pi][yi][xi][0];
209 break;
210 case '/':
211 case ':':
212 for(int pi=0; pi<img1->dimz; pi++) for(int yi=0; yi<img1->dimy; yi++)
213 for(int xi=0; xi<img1->dimx; xi++) {
214 if(fabs(img2->m[pi][yi][xi][0])>1.0E-8)
215 for(int fi=0; fi<img1->dimt; fi++)
216 img1->m[pi][yi][xi][fi]/=img2->m[pi][yi][xi][0];
217 else for(int fi=0; fi<img1->dimt; fi++) img1->m[pi][yi][xi][fi]=0.0;
218 }
219 break;
220 case '*':
221 case 'x':
222 case '.':
223 for(int pi=0; pi<img1->dimz; pi++) for(int yi=0; yi<img1->dimy; yi++)
224 for(int xi=0; xi<img1->dimx; xi++) for(int fi=0; fi<img1->dimt; fi++)
225 img1->m[pi][yi][xi][fi]*=img2->m[pi][yi][xi][0];
226 break;
227 default:
228 if(verbose>0) fprintf(stderr, "Invalid operation.\n");
229 return(10);
230 }
231
232 /* Check for limits */
233 if(ulimit>0.0) {
234 for(int pi=0; pi<img1->dimz; pi++) for(int yi=0; yi<img1->dimy; yi++)
235 for(int xi=0; xi<img1->dimx; xi++) for(int fi=0; fi<img1->dimt; fi++)
236 if(img1->m[pi][yi][xi][fi]>ulimit) img1->m[pi][yi][xi][fi]=ulimit;
237 }
238
239 return(0);
240}

◆ imgAUMC()

int imgAUMC ( IMG * img,
IMG * oimg,
int verbose )
extern

Calculate (incomplete) area under moment curve (AUMC) for every pixel in a dynamic image.

Data is not extrapolated. Frame gaps or overlaps are not accepted.

See also
imgMRT, imgGetMaxTime, imgGetPeak, imgGetMaxFrame, imgFramesCheck, imgMaxDifference, imgSS
Returns
Returns 0, if ok.
Parameters
imgPointer to dynamic image; not modified. Frame times are obligatory.
oimgPointer to empty IMG struct in which the AUMC will be written; any old contents are deleted.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 540 of file imgarithm.c.

548 {
549 if(verbose>0) printf("%s(*img, *oimg)\n", __func__);
550
551 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) return(1);
552 if(img->dimt<2) {
553 if(verbose>1) fprintf(stderr, "Error: dynamic image required.\n");
554 return(2);
555 }
556 if(!imgExistentTimes(img)) {
557 if(verbose>1) fprintf(stderr, "Error: unknown frame times.\n");
558 return(2);
559 }
560 if(oimg==NULL) return(3);
561 if(oimg->status==IMG_STATUS_OCCUPIED) imgEmpty(oimg);
562
563 if(imgFramesCheck(img, verbose-1)>0) {
564 if(verbose>1) fprintf(stderr, "Error: gaps or overlap between time frames.\n");
565 return(4);
566 }
567
568 /* Allocate memory for one frame */
569 int ret;
570 if(verbose>1) printf("allocating memory for %dx%dx%d pixels\n", img->dimz, img->dimy, img->dimx);
571 ret=imgAllocate(oimg, img->dimz, img->dimy, img->dimx, 1);
572 if(ret) return(ret);
573 /* set image header information */
574 imgCopyhdr(img, oimg);
575 oimg->start[0]=img->start[0]; oimg->end[0]=img->end[img->dimt-1];
576 oimg->mid[0]=(oimg->start[0]+oimg->end[0])/2.0;
577 oimg->unit=CUNIT_UNKNOWN;
578
579 /* Calculate sum of (frame time * pixel value) */
580 for(int zi=0; zi<img->dimz; zi++) {
581 for(int yi=0; yi<img->dimy; yi++) {
582 for(int xi=0; xi<img->dimx; xi++) {
583 oimg->m[zi][yi][xi][0]=0.0;
584 for(int ti=0; ti<img->dimt; ti++) {
585 if(isnan(img->m[zi][yi][xi][ti])) continue;
586 float fdur=img->end[ti]-img->start[ti]; if(!(fdur>0.0)) fdur=0.0;
587 oimg->m[zi][yi][xi][0]+=img->m[zi][yi][xi][ti]*img->mid[ti]*fdur;
588 }
589 }
590 }
591 }
592
593 return(0);
594}
int imgExistentTimes(IMG *img)
Definition img.c:613
int imgFramesCheck(IMG *img, int verbose)
Definition imgframe.c:15
char unit
float * start
float * end
float * mid

◆ imgAverageAUC()

int imgAverageAUC ( IMG * img,
float * avgauc )
extern

Calculates the Area-Under-Curve of an average time-activity curve of all pixels or bins in the specified IMG data.

See also
imgAverageMaskTAC, imgAverageTAC, imgAvg
Returns
Returns 0, if ok.
Parameters
img(Dynamic) IMG data.
avgaucPointer to a float were the average TAC AUC will be written.

Definition at line 91 of file imgeval.c.

96 {
97
98 if(img->status<IMG_STATUS_OCCUPIED) return(1);
99 if(avgauc==NULL) return(2);
100 *avgauc=0.0;
101 unsigned long long pxlNr=img->dimz*img->dimy*img->dimx;
102 if(pxlNr<1) return(3);
103 for(int fi=0; fi<img->dimt; fi++) {
104 float fv=0.0;
105 float fl=img->end[fi]-img->start[fi]; if(fl<=0.0) return(4);
106 for(int pi=0; pi<img->dimz; pi++)
107 for(int yi=0; yi<img->dimy; yi++)
108 for(int xi=0; xi<img->dimx; xi++)
109 fv+=img->m[pi][yi][xi][fi];
110 fv/=(float)pxlNr;
111 *avgauc+=fv*fl;
112 }
113 return(0);
114}

◆ imgAverageMaskTAC()

int imgAverageMaskTAC ( IMG * img,
IMG * timg,
float * tac )
extern

Calculates an average time-activity curve of pixels or bins in the specified IMG data.

Mask image specifies the pixels that are included in the average. If all pixels are to be averaged, then NULL can be given instead of mask image.

See also
imgMaskTAC, imgThresholdingLowHigh, imgThresholdMaskCount, imgAverageAUC, imgAverageTAC
Returns
Returns 0, if ok.
Parameters
img(Dynamic) IMG data from which cluster TAC is computed.
timgMask: 0=excluded, otherwise included. Enter NULL to include all pixels in the average.
tacAllocated float array for the TAC.

Definition at line 34 of file imgeval.c.

42 {
43 unsigned long long int pxlNr;
44
45 if(img==NULL || img->status<IMG_STATUS_OCCUPIED) return(1);
46 if(tac==NULL) return(2);
47 if(timg!=NULL) {
48 if(timg->status<IMG_STATUS_OCCUPIED) return(3);
49 /* check that image dimensions are the same */
50 if(timg->dimz!=img->dimz || timg->dimz<1) return(5);
51 if(timg->dimy!=img->dimy || timg->dimy<1) return(5);
52 if(timg->dimx!=img->dimx || timg->dimx<1) return(5);
53 }
54 /* compute the nr of pixels in the mask */
55 if(timg==NULL) {
56 pxlNr=img->dimz*img->dimy*img->dimx;
57 } else {
58 pxlNr=0;
59 for(int zi=0; zi<timg->dimz; zi++)
60 for(int yi=0; yi<timg->dimy; yi++)
61 for(int xi=0; xi<timg->dimx; xi++)
62 if(timg->m[zi][yi][xi][0]!=0.0) pxlNr++;
63 }
64 if(pxlNr<1) return(4);
65
66 /* compute the TAC */
67 for(int fi=0; fi<img->dimt; fi++) {
68 tac[fi]=0.0;
69 for(int zi=0; zi<img->dimz; zi++) {
70 for(int yi=0; yi<img->dimy; yi++) {
71 for(int xi=0; xi<img->dimx; xi++) {
72 if(timg==NULL) tac[fi]+=img->m[zi][yi][xi][fi];
73 else if(timg->m[zi][yi][xi][0]!=0.0) tac[fi]+=img->m[zi][yi][xi][fi];
74 }
75 }
76 }
77 tac[fi]/=(float)pxlNr;
78 //printf("pxlNr=%llu/%llu\n", pxlNr, (unsigned long long)img->dimz*img->dimy*img->dimx);
79 }
80 return(0);
81}

Referenced by imgAverageTAC().

◆ imgAverageTAC()

int imgAverageTAC ( IMG * img,
float * tac )
extern

Calculates an average time-activity curve of all pixels or bins in the specified IMG data.

See also
imgAverageMaskTAC, imgAverageAUC, imgRangeMinMax
Returns
Returns 0, if ok.
Parameters
img(Dynamic) IMG data from which TAC is computed.
tacAllocated float array for the TAC.

Definition at line 15 of file imgeval.c.

20 {
21 return(imgAverageMaskTAC(img, NULL, tac));
22}
int imgAverageMaskTAC(IMG *img, IMG *timg, float *tac)
Definition imgeval.c:34

Referenced by imgNoiseTemplate(), and sifAllocateWithIMG().

◆ imgConvertUnit()

int imgConvertUnit ( IMG * img,
char * unit )
extern

Converts the unit of pixel values in IMG based to specified unit string.

See also
imgArithmConst, imgArithm, imgFrameIntegral
Returns
Returns 0 if successful.
Parameters
imgPointer to IMG struct.
unitString containing the new unit.

Definition at line 480 of file imgarithm.c.

485 {
486 int ret, new_unit=0;
487 float conversion_factor=1.0;
488
489 if(img==NULL || unit==NULL) return(1);
490 if(img->unit==CUNIT_UNKNOWN) return(1);
491 /* Try to identify requested unit */
492 new_unit=imgUnitId(unit); if(new_unit<0) return(1-new_unit);
493 /* Check if unit needs no conversion */
494 if(img->unit==new_unit) return(0);
495 /* Get conversion factor */
496 if(img->unit==CUNIT_KBQ_PER_ML && new_unit==CUNIT_BQ_PER_ML)
497 conversion_factor=1000.0;
498 else if(img->unit==CUNIT_BQ_PER_ML && new_unit==CUNIT_KBQ_PER_ML)
499 conversion_factor=0.001;
500 else if(img->unit==CUNIT_KBQ_PER_ML && new_unit==CUNIT_NCI_PER_ML)
501 conversion_factor=27.027;
502 else if(img->unit==CUNIT_NCI_PER_ML && new_unit==CUNIT_KBQ_PER_ML)
503 conversion_factor=0.037;
504 else if(img->unit==CUNIT_NCI_PER_ML && new_unit==CUNIT_BQ_PER_ML)
505 conversion_factor=37.0;
506 else if(img->unit==CUNIT_KBQ_PER_ML && new_unit==CUNIT_MBQ_PER_ML)
507 conversion_factor=0.001;
508 else if(img->unit==CUNIT_MBQ_PER_ML && new_unit==CUNIT_KBQ_PER_ML)
509 conversion_factor=1000.0;
510 else if(img->unit==CUNIT_PER_SEC && new_unit==CUNIT_PER_MIN)
511 conversion_factor=60.0;
512 else if(img->unit==CUNIT_PER_MIN && new_unit==CUNIT_PER_SEC)
513 conversion_factor=1.0/60.0;
514 else if(img->unit==CUNIT_ML_PER_ML && new_unit==CUNIT_ML_PER_DL)
515 conversion_factor=0.01;
516 else if(img->unit==CUNIT_ML_PER_DL && new_unit==CUNIT_ML_PER_ML)
517 conversion_factor=100.0;
518 else
519 return(10);
520
521 /* Convert pixel values */
522 ret=imgArithmConst(img, conversion_factor, '*', FLT_MAX, 0);
523 if(ret) return(10+ret);
524
525 /* Set the unit id */
526 img->unit=new_unit;
527
528 return(0);
529}
int imgArithmConst(IMG *img, float operand, char operation, float ulimit, int verbose)
Definition imgarithm.c:100
int imgUnitId(char *unit)
Definition imgunits.c:14

◆ imgCutoff()

void imgCutoff ( IMG * image,
float cutoff,
int mode )
extern

Pixel values that exceed or go under a user-defined limit are set to that limit value.

See also
imgFast3DGaussianFilter, imgThresholdingLowHigh, imgAverageAUC, imgsegmThreshold, imgAverageTAC, imgMinMax
Parameters
imagePointer to IMG struct which will be filtered here.
cutoffCut-off value.
modeMode of operation: 0=pixels exceeding the limit are cut off, 1=pixels which go under the limit are cut off.

Definition at line 306 of file imgthreshold.c.

314 {
315 int zi, yi, xi, ti;
316
317 if(mode==0) {
318 for(zi=0; zi<image->dimz; zi++)
319 for(yi=0; yi<image->dimy; yi++)
320 for(xi=0; xi<image->dimx; xi++)
321 for(ti=0; ti<image->dimt; ti++)
322 if(image->m[zi][yi][xi][ti]>cutoff) image->m[zi][yi][xi][ti]=cutoff;
323 } else {
324 for(zi=0; zi<image->dimz; zi++)
325 for(yi=0; yi<image->dimy; yi++)
326 for(xi=0; xi<image->dimx; xi++)
327 for(ti=0; ti<image->dimt; ti++)
328 if(image->m[zi][yi][xi][ti]<cutoff) image->m[zi][yi][xi][ti]=cutoff;
329 }
330 return;
331}

◆ imgDeleteFrameOverlap()

int imgDeleteFrameOverlap ( IMG * img)
extern

Correct frame times if frames are slightly overlapping or have small gaps in between. Large gap is not corrected and it does not lead to an error.

See also
imgFramesCheck, imgFrameGapFill, imgTimeIntegral
Returns
If overlap is considerable (>1 s), or other error is encountered, function returns a non-zero value. Otherwise 0 is returned.
Parameters
imgPointer to IMG struct containing the 4D image data.

Definition at line 77 of file imgframe.c.

80 {
81 int fi;
82 float overlap, overlap_limit=1.8, flen1, flen2;
83
84 if(IMG_TEST) {fprintf(stdout, "%s()\n", __func__); fflush(stdout);}
85 if(img->status!=IMG_STATUS_OCCUPIED || img->dimt<1) return(1);
86 for(fi=0; fi<img->dimt-1; fi++) {
87 overlap=img->end[fi] - img->start[fi+1];
88 if(overlap==0.0) continue; // no gap or overlap
89 else if(overlap<-overlap_limit) continue; // gap is large, then do nothing
90 else if(overlap>overlap_limit) return(2); // overlap is large: error
91 /* Correct the small gap/overlap by making frame durations more similar */
92 flen1=img->end[fi]-img->start[fi]; flen2=img->end[fi+1]-img->start[fi+1];
93 if(overlap>0.0) { // overlap
94 if(flen1>flen2) img->end[fi]=img->start[fi+1]; else img->start[fi+1]=img->end[fi];
95 } else { // gap
96 if(flen1>flen2) img->start[fi+1]=img->end[fi]; else img->end[fi]=img->start[fi+1];
97 }
98 }
99 return(0);
100}

Referenced by imgReadModelingData().

◆ imgDeleteFrameOverlap_old()

int imgDeleteFrameOverlap_old ( IMG * img)
extern

Correct frame times so that frames are not overlapping.

See also
imgDeleteFrameOverlap, imgTimeIntegral
Returns
If overlap is considerable (>1 s), or other error is encountered, function returns a non-zero value. Otherwise 0 is returned.
Parameters
imgPointer to IMG struct containing the 4D image data.

Definition at line 109 of file imgframe.c.

112 {
113 int fi;
114 float overlap;
115
116 if(IMG_TEST) {fprintf(stdout, "%s()\n", __func__); fflush(stdout);}
117 if(img->status!=IMG_STATUS_OCCUPIED || img->dimt<1) return(1);
118 for(fi=0; fi<img->dimt-1; fi++) {
119 overlap=img->end[fi] - img->start[fi+1];
120 if(overlap==0.0) continue;
121 else if(overlap>1.0) return(2);
122 img->end[fi]=img->start[fi+1];
123 }
124 return(0);
125}

◆ imgFlipAbove()

int imgFlipAbove ( IMG * img)
extern

Flip IMG data like viewed from above.

See also
imgFlipHorizontal, imgFlipVertical, imgFlipPlanes, imgFlipRight, img2cube, imgMeanZ
Returns
Returns 0 if successful.
Parameters
imgPointer to IMG which will be flipped.

Definition at line 115 of file imgflips.c.

118 {
119 int xi, yi, zi, fi, ret;
120 IMG omg;
121
122 /* Make copy of the original image */
123 imgInit(&omg); ret=imgDup(img, &omg); if(ret!=0) return(100+ret);
124
125 /* Empty the user-specified image structure. */
126 imgEmpty(img);
127 /* Allocate it again with new dimensions */
128 ret=imgAllocateWithHeader(img, omg.dimy, omg.dimz, omg.dimx, omg.dimt, &omg);
129 if(ret!=0) {imgEmpty(&omg); return(200+ret);}
130
131 /* Copy the voxel values */
132 for(zi=0; zi<omg.dimz; zi++)
133 for(yi=0; yi<omg.dimy; yi++)
134 for(xi=0; xi<omg.dimx; xi++)
135 for(fi=0; fi<omg.dimt; fi++) {
136 img->m[yi][img->dimy-1-zi][xi][fi]=omg.m[zi][yi][xi][fi];
137 }
138
139 /* Switch pixel sizes */
140 img->sizey=omg.sizez;
141 img->sizez=omg.sizey;
142 img->resolutiony=omg.resolutionz;
143 img->resolutionz=omg.resolutiony;
144
145 /* Free the memory of the copy of original image */
146 imgEmpty(&omg);
147
148 return(0);
149}
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
Definition img.c:279
int imgDup(IMG *img1, IMG *img2)
Definition img.c:304
void imgInit(IMG *image)
Definition img.c:60
float resolutiony
float resolutionz

◆ imgFlipHorizontal()

void imgFlipHorizontal ( IMG * img)
extern

Flip IMG data horizontally (left-right).

See also
imgFlipRight, imgFlipVertical, imgFlipPlanes, imgFlipAbove, img2cube

Definition at line 13 of file imgflips.c.

14{
15 int zi, yi, from, to;
16 float *col_ptr;
17
18 for(zi=0; zi<img->dimz; zi++) {
19 for(yi=0; yi<img->dimy; yi++) {
20 for(from=0, to=img->dimx-1; from<to; from++, to--) {
21 col_ptr=img->m[zi][yi][from];
22 img->m[zi][yi][from]=img->m[zi][yi][to];
23 img->m[zi][yi][to]=col_ptr;
24 }
25 }
26 }
27}

◆ imgFlipPlanes()

void imgFlipPlanes ( IMG * img)
extern

Flip IMG data planes (head-toes).

To work properly, the plane numbers must be contiguous.

See also
imgFlipHorizontal, imgFlipVertical, imgFlipRight, imgFlipAbove

Definition at line 55 of file imgflips.c.

56{
57 int from, to;
58 float ***plane_ptr;
59
60 for(from=0, to=img->dimz-1; from<to; from++, to--) {
61 plane_ptr=img->m[from];
62 img->m[from]=img->m[to];
63 img->m[to]=plane_ptr;
64 }
65}

Referenced by imgAnalyzeToEcat().

◆ imgFlipRight()

int imgFlipRight ( IMG * img)
extern

Flip IMG data like viewed from right side.

See also
imgFlipHorizontal, imgFlipVertical, imgFlipPlanes, imgFlipAbove
Returns
Returns 0 if successful.
Parameters
imgPointer to IMG which will be flipped

Definition at line 73 of file imgflips.c.

76 {
77 int xi, yi, zi, fi, ret;
78 IMG omg;
79
80 /* Make copy of the original image */
81 imgInit(&omg); ret=imgDup(img, &omg); if(ret!=0) return(100+ret);
82
83 /* Empty the user-specified image struct */
84 imgEmpty(img);
85 /* Allocate it again with new dimensions */
86 ret=imgAllocateWithHeader(img, omg.dimx, omg.dimy, omg.dimz, omg.dimt, &omg);
87 if(ret!=0) {imgEmpty(&omg); return(200+ret);}
88
89 /* Copy the voxel values */
90 for(zi=0; zi<omg.dimz; zi++)
91 for(yi=0; yi<omg.dimy; yi++)
92 for(xi=0; xi<omg.dimx; xi++)
93 for(fi=0; fi<omg.dimt; fi++) {
94 img->m[xi][yi][zi][fi]=omg.m[zi][yi][xi][fi];
95 }
96
97 /* Switch pixel sizes */
98 img->sizex=omg.sizez;
99 img->sizez=omg.sizex;
100 img->resolutionx=omg.resolutionz;
101 img->resolutionz=omg.resolutionx;
102
103 /* Free the memory of the copy of original image */
104 imgEmpty(&omg);
105
106 return(0);
107}
float resolutionx

◆ imgFlipVertical()

void imgFlipVertical ( IMG * img)
extern

Flip IMG data vertically (up-down).

See also
imgFlipHorizontal, imgFlipRight, imgFlipPlanes, imgFlipAbove

Definition at line 34 of file imgflips.c.

35{
36 int zi, from, to;
37 float **row_ptr;
38
39 for(zi=0; zi<img->dimz; zi++) {
40 for(from=0, to=img->dimy-1; from<to; from++, to--) {
41 row_ptr=img->m[zi][from];
42 img->m[zi][from]=img->m[zi][to];
43 img->m[zi][to]=row_ptr;
44 }
45 }
46}

◆ imgFrameGapFill()

int imgFrameGapFill ( IMG * img,
int verbose )
extern

Fill gaps between time frames by extending adjacent frames over the gap. Overlaps, and gap before the first frame is ignored.

See also
imgFramesCheck, imgDeleteFrameOverlap, imgExistentTimes, imgTimeIntegral
Returns
0 if successful, >0 in case of an error.
Parameters
imgPointer to IMG struct containing the 4D image data.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 50 of file imgframe.c.

55 {
56 if(verbose>0) {printf("%s(*img)\n", __func__); fflush(stdout);}
57 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED || img->dimt<2) return(0);
58
59 for(int fi=1; fi<img->dimt; fi++) {
60 float gap=img->start[fi] - img->end[fi-1];
61 if(gap<1.0E-07) continue;
62 if(verbose>2) printf("gap between frames %d and %d: %g\n", fi, fi+1, gap);
63 img->start[fi] -= 0.5*gap; img->mid[fi]=0.5*(img->start[fi]+img->end[fi]);
64 img->end[fi-1]=img->start[fi]; img->mid[fi-1]=0.5*(img->start[fi-1]+img->end[fi-1]);
65 }
66 return(0);
67}

◆ imgFrameIntegral()

int imgFrameIntegral ( IMG * img,
int first,
int last,
IMG * iimg,
int verbose )
extern

Integration from first frame (0..last) to last frame (first..dimt) to iimg, which is allocated here.

Frames do not have to be continuous in time. Time unit in integral is sec. Raw data (sinogram) must be divided by frame durations before calling this. If dynamic image data does not contain frame times (e.g. Analyze image) then just the sum is calculated.

See also
imgArithm, imgRawCountsPerTime, imgTimeIntegral, imgAUMC
Returns
Returns 0 if ok, otherwise >0.
Parameters
img(Dynamic) IMG data.
firstFirst frame to include in AUC; 0..dimt-1.
lastLast frame to include in AUC; 0..dimt-1.
iimgPointer to initiated and empty AUC IMG data.
verboseVerbose level; if <=0, then nothing is printed into stderr.

Definition at line 346 of file imgarithm.c.

357 {
358 if(verbose>0) printf("%s(img, %d, %d, iimg, %d)\n", __func__, first, last, verbose);
359
360 int zi, yi, xi, fi, ret, times_exist;
361 float fstart, fend, dur, x, y, k;
362
363 /* Check the arguments */
364 if(img==NULL || iimg==NULL || first<0 || first>last) return(1);
365 if(img->status!=IMG_STATUS_OCCUPIED) return(2);
366 times_exist=imgExistentTimes(img);
367 fstart=img->start[first]; fend=img->end[last];
368 if(verbose>1) printf(" time_range := %g - %g\n", fstart, fend);
369
370 /* Allocate memory for the integral */
371 imgEmpty(iimg);
372 ret=imgAllocateWithHeader(iimg, img->dimz, img->dimy, img->dimx, 1, img);
373 if(ret) {
374 if(verbose>0) fprintf(stderr, "Error %d in allocating memory for sum image.\n", ret);
375 imgEmpty(iimg); return(3);
376 }
377
378 /* Set header information */
379 iimg->start[0]=fstart; iimg->end[0]=fend;
380 iimg->mid[0]=0.5*(iimg->start[0]+iimg->end[0]);
383 iimg->decayCorrFactor[0]=0.0;
384 /* Change also the unit, if possible */
385 if(img->type==IMG_TYPE_IMAGE) {
386 if(img->unit==CUNIT_KBQ_PER_ML) iimg->unit=CUNIT_SEC_KBQ_PER_ML;
387 }
388
389 /* Integrate the first frame */
390 fi=first;
391 if(times_exist) {
392 dur=img->end[fi]-img->start[fi]; if(dur<0.0) {imgEmpty(iimg); return(4);}
393 } else dur=1.0;
394 for(zi=0; zi<img->dimz; zi++)
395 for(yi=0; yi<img->dimy; yi++)
396 for(xi=0; xi<img->dimx; xi++)
397 iimg->m[zi][yi][xi][0]=dur*img->m[zi][yi][xi][fi];
398 /* Add integrals of the following frames */
399 for(fi=first+1; fi<=last; fi++) {
400 if(times_exist) {
401 dur=img->end[fi]-img->start[fi]; if(dur<0.0) {imgEmpty(iimg); return(4);}
402 } else dur=1.0;
403 /* Add the integral of this frame to the previous integral */
404 for(zi=0; zi<img->dimz; zi++)
405 for(yi=0; yi<img->dimy; yi++)
406 for(xi=0; xi<img->dimx; xi++)
407 iimg->m[zi][yi][xi][0]+=dur*img->m[zi][yi][xi][fi];
408 if(times_exist) {
409 /* Check whether frames are contiguous */
410 dur=img->start[fi]-img->end[fi-1]; if(dur<=1.0E-10) continue;
411 /* When not, calculate the integral between frames */
412 x=0.5*(img->start[fi]+img->end[fi-1]);
413 for(zi=0; zi<img->dimz; zi++)
414 for(yi=0; yi<img->dimy; yi++)
415 for(xi=0; xi<img->dimx; xi++) {
416 k=(img->m[zi][yi][xi][fi]-img->m[zi][yi][xi][fi-1])
417 /(img->mid[fi]-img->mid[fi-1]);
418 y=img->m[zi][yi][xi][fi-1]+k*(x-img->mid[fi-1]);
419 iimg->m[zi][yi][xi][0]+=dur*y;
420 }
421 }
422 } /* next frame */
423
424 /* Set frame times */
425 iimg->start[0]=img->start[first];
426 iimg->end[0]=img->end[last];
427 iimg->mid[0]=0.5*(iimg->start[0]+iimg->end[0]);
428
429 return(0);
430}
#define IMG_TYPE_RAW
#define IMG_DC_CORRECTED
#define IMG_DC_NONCORRECTED
#define IMG_TYPE_IMAGE
char type
char decayCorrection
float * decayCorrFactor

Referenced by imgsegmSimilar(), imgThresholding(), imgThresholdingLowHigh(), and imgTimeIntegral().

◆ imgFramesCheck()

int imgFramesCheck ( IMG * img,
int verbose )
extern

Check for gaps or overlap between frame times. Gap before the first frame is ignored.

See also
imgExistentTimes, imgDeleteFrameOverlap, imgTimeIntegral, imgFrameGapFill
Returns
0, if no overlaps or gaps are found, 1 if overlaps are found, 2 if gaps are found, and 3 if both overlaps and gaps are found.
Parameters
imgPointer to IMG struct containing the 4D image data. Data is not modified.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 15 of file imgframe.c.

20 {
21 if(verbose>0) {printf("%s(*img)\n", __func__); fflush(stdout);}
22 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED || img->dimt<2) return(0);
23
24 int gapNr=0, overlapNr=0;
25 for(int fi=1; fi<img->dimt; fi++) {
26 float gap=img->start[fi] - img->end[fi-1];
27 if(verbose>2 && fabs(gap)>1.0E-06)
28 printf("gap between frames %d and %d: %g\n", fi, fi+1, gap);
29 if(gap>1.0E-06) gapNr++;
30 else if(gap<-1.0E-06) overlapNr++;
31 }
32 if(verbose>1) {
33 printf(" %d overlap(s)\n", overlapNr);
34 printf(" %d gap(s)\n", gapNr);
35 fflush(stdout);
36 }
37 int ret=0;
38 if(overlapNr>0) ret+=1;
39 if(gapNr>0) ret+=2;
40 return(ret);
41}

Referenced by imgAUMC(), and imgMRT().

◆ imgGaussianAMFilter()

int imgGaussianAMFilter ( IMG * img,
float xsd,
float ysd,
float zsd,
int passNr,
double tolerance,
int verbose )
extern

Alvarez-Mazorra approximate Gaussian image filtering in 1-3 dimensions.

References:

See also
imgGaussianFIRFilter, imgSS
Returns
If an error is encountered, function returns a non-zero value. Otherwise 0 is returned.
Parameters
imgImage data to be processed; data is overwritten with filtered image. All image frames are processed.
xsdGaussian S.D. in pixels in x dimension; SD=FWHM/2.355. Enter 0 to not filter in x dimension.
ysdGaussian S.D. in pixels in y dimension; SD=FWHM/2.355. Enter 0 to not filter in y dimension.
zsdGaussian S.D. in pixels in z dimension; SD=FWHM/2.355. Enter 0 to not filter in z dimension.
passNrNumber of filtering passes, usually 4 or more; enter 0 to use the default steps (4).
toleranceTolerance; enter 0.0 to use the default (1.0E-06).
verboseVerbose level; if zero, then only warnings are printed into stderr.

Definition at line 173 of file imgfilter.c.

189 {
190 if(verbose>0) printf("%s(*img, %g, %g, %g, %d, %d)\n", __func__, xsd, ysd, zsd, passNr, verbose);
191
192 if(img==NULL || img->dimz<1 || img->dimy<1 || img->dimx<1 || img->dimt<1) return 1;
193 int dimx=img->dimx, dimy=img->dimy, dimz=img->dimz, dimt=img->dimt;
194 if(dimx==1) xsd=0.0;
195 if(dimy==1) ysd=0.0;
196 if(dimz==1) zsd=0.0;
197 if(xsd>0.0 && (dimx<4 || !(img->sizex>0.0))) return(2);
198 if(ysd>0.0 && (dimy<4 || !(img->sizey>0.0))) return(3);
199 if(zsd>0.0 && (dimz<4 || !(img->sizez>0.0))) return(4);
200 if(!(xsd>0.0) && !(ysd>0.0) && !(zsd>0.0)) {
201 if(verbose>1) printf(" no filtering done.\n");
202 fflush(stdout); return(0);
203 }
204 if(passNr<=0) passNr=4;
205 if(!(tolerance>0.0)) tolerance=1.0E-06;
206
207
208 /*
209 * Filtering in x dimension
210 */
211 if(xsd>0.0) {
212 if(verbose>1) {printf(" filtering in x dimension\n"); fflush(stdout);}
213 double q=xsd;
214 if(0) { // Adjust SD for improved accuracy at low step numbers
215 double f=0.7818+(double)passNr;
216 q*= 1.0 + (0.3165*(double)passNr + 0.5695)/(f*f);
217 }
218 double lambda=(q*q)/(2.0*(double)passNr);
219 double nu=(1.0 + 2.0*lambda - sqrt(1.0 + 4.0*lambda))/(2.0*lambda);
220 double scale=pow(nu/lambda, passNr);
221 int termNr=ceil(log((1.0-nu)*tolerance)/log(nu));
222 if(verbose>2) printf(" nu=%g scale=%g termNr=%d\n", nu, scale, termNr);
223
224 for(int t=0; t<dimt; t++) { // Image time frames are processed as separate images
225 if(verbose>5) {printf(" frame %d\n", 1+t); fflush(stdout);}
226 double sum1=0.0, sum2=0.0;
227 for(int z=0; z<dimz; z++) for(int y=0; y<dimy; y++) {
228 double d[dimx];
229 for(int x=0; x<dimx; x++) sum1+=d[x]=img->m[z][y][x][t];
230 filterAMGaussian(d, dimx, passNr, nu, scale, termNr);
231 for(int x=0; x<dimx; x++) sum2+=img->m[z][y][x][t]=d[x];
232 }
233 double f=sum1/sum2;
234 if(verbose>1 && fabs(1.0-f)>1.0E-10) {
235 printf(" frame %d: sum of voxels differs pre/post filtering %g/%g=%g\n", 1+t, sum1, sum2, f);
236 }
237 }
238 }
239
240 /*
241 * Filtering in y dimension
242 */
243 if(ysd>0.0) {
244 if(verbose>1) {printf(" filtering in y dimension\n"); fflush(stdout);}
245 double q=ysd;
246 if(0) { // Adjust SD for improved accuracy at low step numbers
247 double f=0.7818+(double)passNr;
248 q*= 1.0 + (0.3165*(double)passNr + 0.5695)/(f*f);
249 }
250 double lambda=(q*q)/(2.0*(double)passNr);
251 double nu=(1.0 + 2.0*lambda - sqrt(1.0 + 4.0*lambda))/(2.0*lambda);
252 double scale=pow(nu/lambda, passNr);
253 int termNr=ceil(log((1.0-nu)*tolerance)/log(nu));
254 if(verbose>2) printf(" nu=%g scale=%g termNr=%d\n", nu, scale, termNr);
255
256 for(int t=0; t<dimt; t++) { // Image time frames are processed as separate images
257 if(verbose>5) {printf(" frame %d\n", 1+t); fflush(stdout);}
258 double sum1=0.0, sum2=0.0;
259 for(int z=0; z<dimz; z++) for(int x=0; x<dimx; x++) {
260 double d[dimy];
261 for(int y=0; y<dimy; y++) sum1+=d[y]=img->m[z][y][x][t];
262 filterAMGaussian(d, dimy, passNr, nu, scale, termNr);
263 for(int y=0; y<dimy; y++) sum2+=img->m[z][y][x][t]=d[y];
264 }
265 double f=sum1/sum2;
266 if(verbose>1 && fabs(1.0-f)>1.0E-10) {
267 printf(" frame %d: sum of voxels differs pre/post filtering %g/%g=%g\n", 1+t, sum1, sum2, f);
268 }
269 }
270 }
271
272 /*
273 * Filtering in z dimension
274 */
275 if(zsd>0.0) {
276 if(verbose>1) {printf(" filtering in z dimension\n"); fflush(stdout);}
277 double q=xsd;
278 if(0) { // Adjust SD for improved accuracy at low step numbers
279 double f=0.7818+(double)passNr;
280 q*= 1.0 + (0.3165*(double)passNr + 0.5695)/(f*f);
281 }
282 double lambda=(q*q)/(2.0*(double)passNr);
283 double nu=(1.0 + 2.0*lambda - sqrt(1.0 + 4.0*lambda))/(2.0*lambda);
284 double scale=pow(nu/lambda, passNr);
285 int termNr=ceil(log((1.0-nu)*tolerance)/log(nu));
286 if(verbose>2) printf(" nu=%g scale=%g termNr=%d\n", nu, scale, termNr);
287
288 for(int t=0; t<dimt; t++) { // Image time frames are processed as separate images
289 if(verbose>5) {printf(" frame %d\n", 1+t); fflush(stdout);}
290 double sum1=0.0, sum2=0.0;
291 for(int y=0; y<dimy; y++) for(int x=0; x<dimy; x++) {
292 double d[dimz];
293 for(int z=0; z<dimz; z++) sum1+=d[z]=img->m[z][y][x][t];
294 filterAMGaussian(d, dimz, passNr, nu, scale, termNr);
295 for(int z=0; z<dimz; z++) sum2+=img->m[z][y][x][t]=d[z];
296 }
297 double f=sum1/sum2;
298 if(verbose>1 && fabs(1.0-f)>1.0E-10) {
299 printf(" frame %d: sum of voxels differs pre/post filtering %g/%g=%g\n", 1+t, sum1, sum2, f);
300 }
301 }
302 }
303
304
305 return(0);
306}
int filterAMGaussian(double *a, int n, int passNr, double nu, double scale, int termNr)
Definition imgfilter.c:314

◆ imgGaussianEBoxFilter()

int imgGaussianEBoxFilter ( IMG * img,
float xsd,
float ysd,
float zsd,
int passNr,
int verbose )
extern

Gaussian extended box image filtering in 1-3 dimensions.

References:

See also
imgFast2DGaussianFilter, imgGaussianFilter, imgSS
Returns
If an error is encountered, function returns a non-zero value. Otherwise 0 is returned.
Parameters
imgImage data to be processed; data is overwritten with filtered image. All image frames are processed.
xsdGaussian S.D. in pixels in x dimension; SD=FWHM/2.355. Enter 0 to not filter in x dimension.
ysdGaussian S.D. in pixels in y dimension; SD=FWHM/2.355. Enter 0 to not filter in y dimension.
zsdGaussian S.D. in pixels in z dimension; SD=FWHM/2.355. Enter 0 to not filter in z dimension.
passNrNumber of filtering passes, usually 3-5; enter 0 to use the default steps (4).
verboseVerbose level; if zero, then only warnings are printed into stderr.

Definition at line 408 of file imgfilter.c.

422 {
423 if(verbose>0) printf("%s(*img, %g, %g, %g, %d, %d)\n", __func__, xsd, ysd, zsd, passNr, verbose);
424
425 if(img==NULL || img->dimz<1 || img->dimy<1 || img->dimx<1 || img->dimt<1) return 1;
426 int dimx=img->dimx, dimy=img->dimy, dimz=img->dimz, dimt=img->dimt;
427 if(dimx==1) xsd=0.0;
428 if(dimy==1) ysd=0.0;
429 if(dimz==1) zsd=0.0;
430 if(xsd>0.0 && (dimx<4 || !(img->sizex>0.0))) return(2);
431 if(ysd>0.0 && (dimy<4 || !(img->sizey>0.0))) return(3);
432 if(zsd>0.0 && (dimz<4 || !(img->sizez>0.0))) return(4);
433 if(!(xsd>0.0) && !(ysd>0.0) && !(zsd>0.0)) {
434 if(verbose>1) printf(" no filtering done.\n");
435 return(0);
436 }
437 if(passNr<=0) passNr=4;
438
439
440 /*
441 * Filtering in x dimension
442 */
443 if(xsd>0.0) {
444 if(verbose>1) {printf(" filtering in x dimension\n"); fflush(stdout);}
445 int rib;
446 double wob, wib, s2p=xsd*xsd/(double)passNr;
447 /* Calculate inner box radius (by Wells) */
448 rib=0.5*sqrt(1.0 + 12.0*s2p) - 0.5;
449 if(verbose>3) printf(" precise_r := %f\n", 0.5*sqrt(1.0+12.0*s2p));
450 /* Alpha */
451 double a=(2*rib+1)*(rib*(rib+1) - 3.0*s2p) / (6.0*(s2p - (rib+1)*(rib+1)));
452 /* Outer box weight */
453 wob = a/(2.0*(a+rib)+1.0);
454 /* Inner box weight */
455 wib = 1.0-wob;
456 if(verbose>2) {printf(" rib=%d wob=%g wib=%g a=%g\n", rib, wob, wib, a); fflush(stdout);}
457
458 for(int t=0; t<dimt; t++) { // Image time frames are processed as separate images
459 if(verbose>5) {printf(" frame %d\n", 1+t); fflush(stdout);}
460 double sum1=0.0, sum2=0.0;
461 for(int z=0; z<dimz; z++) for(int y=0; y<dimy; y++) {
462 double d[dimx];
463 for(int x=0; x<dimx; x++) sum1+=d[x]=img->m[z][y][x][t];
464 filterEbox(d, dimx, wob, wib, rib, passNr);
465 for(int x=0; x<dimx; x++) sum2+=img->m[z][y][x][t]=d[x];
466 }
467 double f=sum1/sum2;
468 if(fabs(1.0-f)>1.0E-10) {
469 if(verbose>1)
470 printf(" frame %d: sum of voxels differs pre/post filtering %g/%g=%g\n", 1+t, sum1, sum2, f);
471 for(int z=0; z<dimz; z++) for(int y=0; y<dimy; y++) for(int x=0; x<dimx; x++)
472 img->m[z][y][x][t]*=f;
473 }
474 }
475 }
476
477 /*
478 * Filtering in y dimension
479 */
480 if(ysd>0.0) {
481 if(verbose>1) {printf(" filtering in y dimension\n"); fflush(stdout);}
482 int rib;
483 double wob, wib, s2p=ysd*ysd/(double)passNr;
484 /* Calculate inner box radius */
485 rib=0.5*sqrt(1.0 + 12.0*s2p) - 0.5;
486 /* Alpha */
487 double a=(2*rib+1)*(rib*(rib+1) - 3.0*s2p) / (6.0*(s2p - (rib+1)*(rib+1)));
488 /* Outer box weight */
489 wob = a/(2.0*(a+rib)+1);
490 /* Inner box weight */
491 wib = 1.0-wob;
492 if(verbose>2) {printf(" rib=%d wob=%g wib=%g a=%g\n", rib, wob, wib, a); fflush(stdout);}
493
494 for(int t=0; t<dimt; t++) { // Image time frames are processed as separate images
495 if(verbose>5) {printf(" frame %d\n", 1+t); fflush(stdout);}
496 double sum1=0.0, sum2=0.0;
497 for(int z=0; z<dimz; z++) for(int x=0; x<dimx; x++) {
498 double d[dimy];
499 for(int y=0; y<dimy; y++) sum1+=d[y]=img->m[z][y][x][t];
500 filterEbox(d, dimy, wob, wib, rib, passNr);
501 for(int y=0; y<dimy; y++) sum2+=img->m[z][y][x][t]=d[y];
502 }
503 double f=sum1/sum2;
504 if(fabs(1.0-f)>1.0E-10) {
505 if(verbose>1)
506 printf(" frame %d: sum of voxels differs pre/post filtering %g/%g=%g\n", 1+t, sum1, sum2, f);
507 for(int z=0; z<dimz; z++) for(int y=0; y<dimy; y++) for(int x=0; x<dimx; x++)
508 img->m[z][y][x][t]*=f;
509 }
510 }
511 }
512
513 /*
514 * Filtering in z dimension
515 */
516 if(zsd>0.0) {
517 if(verbose>1) {printf(" filtering in z dimension\n"); fflush(stdout);}
518 int rib;
519 double wob, wib, s2p=zsd*zsd/(double)passNr;
520 /* Calculate inner box radius */
521 rib=0.5*sqrt(1.0 + 12.0*s2p) - 0.5;
522 /* Alpha */
523 double a=(2*rib+1)*(rib*(rib+1) - 3.0*s2p) / (6.0*(s2p - (rib+1)*(rib+1)));
524 /* Outer box weight */
525 wob = a/(2.0*(a+rib)+1);
526 /* Inner box weight */
527 wib = 1.0-wob;
528 if(verbose>2) {printf(" rib=%d wob=%g wib=%g a=%g\n", rib, wob, wib, a); fflush(stdout);}
529
530 for(int t=0; t<dimt; t++) { // Image time frames are processed as separate images
531 if(verbose>5) {printf(" frame %d\n", 1+t); fflush(stdout);}
532 double sum1=0.0, sum2=0.0;
533 for(int y=0; y<dimy; y++) for(int x=0; x<dimx; x++) {
534 double d[dimz];
535 for(int z=0; z<dimz; z++) sum1+=d[z]=img->m[z][y][x][t];
536 filterEbox(d, dimz, wob, wib, rib, passNr);
537 for(int z=0; z<dimz; z++) sum2+=img->m[z][y][x][t]=d[z];
538 }
539 double f=sum1/sum2;
540 if(fabs(1.0-f)>1.0E-10) {
541 if(verbose>1)
542 printf(" frame %d: sum of voxels differs pre/post filtering %g/%g=%g\n", 1+t, sum1, sum2, f);
543 for(int z=0; z<dimz; z++) for(int y=0; y<dimy; y++) for(int x=0; x<dimx; x++)
544 img->m[z][y][x][t]*=f;
545 }
546 }
547 }
548
549 return(0);
550}
int filterEbox(double *a, int n, double wob, double wib, int rib, int passNr)
Definition imgfilter.c:558

◆ imgGaussianFIRFilter()

int imgGaussianFIRFilter ( IMG * img,
float xsd,
float ysd,
float zsd,
double tolerance,
int verbose )
extern

Gaussian finite impulse response (FIR) isotropic or anisotropic image filtering in 1-3 dimensions.

Based on the code in: Getreuer P. A survey of Gaussian convolution algorithms. Image Processing On Line 2013;3:286–310. https://doi.org/10.5201/ipol.2013.87

See also
imgGaussianAMFilter, imgSS
Returns
If an error is encountered, function returns a non-zero value. Otherwise 0 is returned.
Parameters
imgImage data to be processed; data is overwritten with filtered image. All image frames are processed.
xsdGaussian S.D. in pixels in x dimension; SD=FWHM/2.355. Enter 0 to not filter in x dimension.
ysdGaussian S.D. in pixels in y dimension; SD=FWHM/2.355. Enter 0 to not filter in y dimension.
zsdGaussian S.D. in pixels in z dimension; SD=FWHM/2.355. Enter 0 to not filter in z dimension.
toleranceTolerance; enter 0.0 to use the default (1.0E-03).
verboseVerbose level; if zero, then only warnings are printed into stderr.

Definition at line 18 of file imgfilter.c.

32 {
33 if(verbose>0) printf("%s(*img, %g, %g, %g, %g, %d)\n", __func__, xsd, ysd, zsd, tolerance, verbose);
34
35 if(img==NULL || img->dimz<1 || img->dimy<1 || img->dimx<1 || img->dimt<1) return 1;
36 int dimx=img->dimx, dimy=img->dimy, dimz=img->dimz, dimt=img->dimt;
37 if(dimx==1) xsd=0.0;
38 if(dimy==1) ysd=0.0;
39 if(dimz==1) zsd=0.0;
40 if(xsd>0.0 && (dimx<4 || !(img->sizex>0.0))) return(2);
41 if(ysd>0.0 && (dimy<4 || !(img->sizey>0.0))) return(3);
42 if(zsd>0.0 && (dimz<4 || !(img->sizez>0.0))) return(4);
43 if(!(xsd>0.0) && !(ysd>0.0) && !(zsd>0.0)) {
44 if(verbose>1) printf(" no filtering done.\n");
45 return(0);
46 }
47 if(!(tolerance>0.0)) tolerance=1.0E-03;
48 if(tolerance>=1.0) return(5);
49
50 double sqrt_pi2=sqrt(M_PI)/M_SQRT2; // sqrt(pi)/sqrt(2)
51
52 /*
53 * Filtering in x dimension
54 */
55 if(xsd>0.0) {
56 if(verbose>1) {printf(" filtering in x dimension\n"); fflush(stdout);}
57 int r=ceil(M_SQRT2*xsd*inverfc(0.5*tolerance)); // Radius of the filter
58 double gtrunc[r+1]; // Truncated Gaussian filter for FIR convolution
59 double sdsqrt2=M_SQRT2*xsd;
60 gtrunc[0]=1.0;
61// for(int i=1; i<=r; i++) gtrunc[i]=exp(-0.5*((double)i/xsd)*((double)i/xsd));
62 for(int i=1; i<=r; i++)
63 gtrunc[i]=sqrt_pi2*xsd*(erf(((double)i+0.5)/sdsqrt2) - erf(((double)i-0.5)/sdsqrt2));
64 double sum=gtrunc[0]; for(int i=1; i<=r; i++) sum+=2.0*gtrunc[i];
65 for(int i=0; i<=r; i++) gtrunc[i]/=sum;
66 if(verbose>2) printf(" r=%d \n", r);
67 if(verbose>3) {
68 printf(" gtrunc[]= %g", gtrunc[0]); for(int i=1; i<=r; i++) printf(",%g", gtrunc[i]);
69 printf("\n");
70 }
71
72 for(int t=0; t<dimt; t++) { // Image time frames are processed as separate images
73 if(verbose>5) {printf(" frame %d\n", 1+t); fflush(stdout);}
74 for(int z=0; z<dimz; z++) for(int y=0; y<dimy; y++) {
75 double a[dimx];
76 for(int x=0; x<dimx; x++) a[x]=img->m[z][y][x][t];
77 for(int x=0; x<dimx; x++) {
78 double v=gtrunc[0]*a[x];
79 for(int m=1; m<=r; m++)
80 v+=gtrunc[m]*(a[filterHSSBE(dimx, x-m)] + a[filterHSSBE(dimx, x+m)]);
81 img->m[z][y][x][t]=v;
82 }
83 }
84 }
85 }
86
87
88 /*
89 * Filtering in y dimension
90 */
91 if(ysd>0.0) {
92 if(verbose>1) {printf(" filtering in y dimension\n"); fflush(stdout);}
93 int r=ceil(M_SQRT2*ysd*inverfc(0.5*tolerance)); // Radius of the filter
94 double gtrunc[r+1]; // Truncated Gaussian filter for FIR convolution
95 double sdsqrt2=M_SQRT2*ysd;
96 gtrunc[0]=1.0;
97// for(int i=1; i<=r; i++) gtrunc[i]=exp(-0.5*((double)i/ysd)*((double)i/ysd));
98 for(int i=1; i<=r; i++)
99 gtrunc[i]=sqrt_pi2*ysd*(erf(((double)i+0.5)/sdsqrt2) - erf(((double)i-0.5)/sdsqrt2));
100 double sum=gtrunc[0]; for(int i=1; i<=r; i++) sum+=2.0*gtrunc[i];
101 for(int i=0; i<=r; i++) gtrunc[i]/=sum;
102 if(verbose>2) printf(" r=%d \n", r);
103 if(verbose>3) {
104 printf(" gtrunc[]= %g", gtrunc[0]); for(int i=1; i<=r; i++) printf(",%g", gtrunc[i]);
105 printf("\n");
106 }
107
108 for(int t=0; t<dimt; t++) { // Image time frames are processed as separate images
109 if(verbose>5) {printf(" frame %d\n", 1+t); fflush(stdout);}
110 for(int z=0; z<dimz; z++) for(int x=0; x<dimx; x++) {
111 double a[dimy];
112 for(int y=0; y<dimy; y++) a[y]=img->m[z][y][x][t];
113 for(int y=0; y<dimy; y++) {
114 double v=gtrunc[0]*a[y];
115 for(int m=1; m<=r; m++)
116 v+=gtrunc[m]*(a[filterHSSBE(dimy, y-m)] + a[filterHSSBE(dimy, y+m)]);
117 img->m[z][y][x][t]=v;
118 }
119 }
120 }
121 }
122
123
124 /*
125 * Filtering in z dimension
126 */
127 if(zsd>0.0) {
128 if(verbose>1) {printf(" filtering in z dimension\n"); fflush(stdout);}
129 int r=ceil(M_SQRT2*zsd*inverfc(0.5*tolerance)); // Radius of the filter
130 double gtrunc[r+1]; // Truncated Gaussian filter for FIR convolution
131 double sdsqrt2=M_SQRT2*zsd;
132 gtrunc[0]=1.0;
133// for(int i=1; i<=r; i++) gtrunc[i]=exp(-0.5*((double)i/zsd)*((double)i/zsd));
134 for(int i=1; i<=r; i++)
135 gtrunc[i]=sqrt_pi2*zsd*(erf(((double)i+0.5)/sdsqrt2) - erf(((double)i-0.5)/sdsqrt2));
136 double sum=gtrunc[0]; for(int i=1; i<=r; i++) sum+=2.0*gtrunc[i];
137 for(int i=0; i<=r; i++) gtrunc[i]/=sum;
138 if(verbose>2) printf(" r=%d \n", r);
139 if(verbose>3) {
140 printf(" gtrunc[]= %g", gtrunc[0]); for(int i=1; i<=r; i++) printf(",%g", gtrunc[i]);
141 printf("\n");
142 }
143
144 for(int t=0; t<dimt; t++) { // Image time frames are processed as separate images
145 if(verbose>5) {printf(" frame %d\n", 1+t); fflush(stdout);}
146 for(int y=0; y<dimy; y++) for(int x=0; x<dimx; x++) {
147 double a[dimz];
148 for(int z=0; z<dimz; z++) a[z]=img->m[z][y][x][t];
149 for(int z=0; z<dimz; z++) {
150 double v=gtrunc[0]*a[z];
151 for(int m=1; m<=r; m++)
152 v+=gtrunc[m]*(a[filterHSSBE(dimz, z-m)] + a[filterHSSBE(dimz, z+m)]);
153 img->m[z][y][x][t]=v;
154 }
155 }
156 }
157 }
158 return(0);
159}
double inverfc(double x)
Definition doubleutil.c:205

Referenced by imgPVCRRL(), and imgPVCRVC().

◆ imgGetFrameDiff()

int imgGetFrameDiff ( IMG * img,
IMG * dimg,
IMG * mimg,
int verbose )
extern

Compute sum absolute difference and/or sum absolute average between consecutive frames.

See also
imgGetPeak, imgGetMaxFrame, imgSmoothOverFrames
Returns
Returns 0, if ok.
Parameters
imgDynamic image; not modified.
dimgPointer to an empty IMG struct in which the sum of absolute differences will be written; any old contents are deleted; NULL, if not needed.
mimgPointer to an empty IMG struct in which the sum of absolute means will be written; any old contents are deleted; NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 180 of file imgframe.c.

191 {
192 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
193
194 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) return(1);
195 if(img->dimt<2) {
196 if(verbose>0) {fprintf(stderr, "only dynamic image can be processed!\n"); fflush(stderr);}
197 return(1);
198 }
199 if(dimg==NULL && mimg==NULL) return(0);
200 if(dimg!=NULL && dimg->status==IMG_STATUS_OCCUPIED) imgEmpty(dimg);
201 if(mimg!=NULL && mimg->status==IMG_STATUS_OCCUPIED) imgEmpty(mimg);
202
203
204 /* Allocate memory for one frame */
205 int ret=0;
206 if(verbose>1) {
207 printf("allocating memory for %dx%dx%d pixels\n", img->dimz, img->dimy, img->dimx);
208 fflush(stdout);
209 }
210 if(dimg!=NULL) ret=imgAllocate(dimg, img->dimz, img->dimy, img->dimx, 1); else ret=0;
211 if(!ret && mimg!=NULL) ret=imgAllocate(mimg, img->dimz, img->dimy, img->dimx, 1);
212 if(ret) return(ret);
213 /* set image header information */
214 if(dimg!=NULL) {
215 imgCopyhdr(img, dimg);
216 dimg->start[0]=img->start[0]; dimg->end[0]=img->end[img->dimt-1];
217 dimg->mid[0]=(dimg->start[0]+dimg->end[0])/2.0;
218 }
219 if(mimg!=NULL) {
220 imgCopyhdr(img, mimg);
221 mimg->start[0]=img->start[0]; mimg->end[0]=img->end[img->dimt-1];
222 mimg->mid[0]=(mimg->start[0]+mimg->end[0])/2.0;
223 }
224
225 /* Go through every pixel */
226 int ti, zi, xi, yi;
227 for(zi=0; zi<img->dimz; zi++) {
228 for(yi=0; yi<img->dimy; yi++) for(xi=0; xi<img->dimx; xi++) {
229 for(ti=1; ti<img->dimt; ti++) {
230 if(dimg!=NULL) {
231 dimg->m[zi][yi][xi][0]+=fabs(img->m[zi][yi][xi][ti]-img->m[zi][yi][xi][ti-1]);
232 }
233 if(mimg!=NULL) {
234 mimg->m[zi][yi][xi][0]+=0.5*fabs(img->m[zi][yi][xi][ti]+img->m[zi][yi][xi][ti-1]);
235 }
236 }
237 }
238 }
239
240 return(0);
241}

◆ imgGetFrameDyn()

int imgGetFrameDyn ( IMG * img,
IMG * iimg,
IMG * dimg,
int verbose )
extern

Compute the number of increases and decreases between consecutive frames.

See also
imgGetPeak, imgGetMaxFrame
Returns
Returns 0, if ok.
Parameters
imgDynamic image; not modified.
iimgPointer to an empty IMG struct in which the nr of increases will be written; any old contents are deleted; NULL, if not needed.
dimgPointer to an empty IMG struct in which the nr of decreases will be written; any old contents are deleted; NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 249 of file imgframe.c.

260 {
261 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
262
263 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) return(1);
264 if(img->dimt<2) {
265 if(verbose>0) {fprintf(stderr, "only dynamic image can be processed!\n"); fflush(stderr);}
266 return(1);
267 }
268 if(iimg==NULL && dimg==NULL) return(0);
269 if(iimg!=NULL && iimg->status==IMG_STATUS_OCCUPIED) imgEmpty(iimg);
270 if(dimg!=NULL && dimg->status==IMG_STATUS_OCCUPIED) imgEmpty(dimg);
271
272
273 /* Allocate memory for one frame */
274 int ret=0;
275 if(verbose>1) {
276 printf("allocating memory for %dx%dx%d pixels\n", img->dimz, img->dimy, img->dimx);
277 fflush(stdout);
278 }
279 if(dimg!=NULL) ret=imgAllocate(dimg, img->dimz, img->dimy, img->dimx, 1); else ret=0;
280 if(!ret && iimg!=NULL) ret=imgAllocate(iimg, img->dimz, img->dimy, img->dimx, 1);
281 if(ret) return(ret);
282 /* set image header information */
283 if(dimg!=NULL) {
284 imgCopyhdr(img, dimg);
285 dimg->start[0]=img->start[0]; dimg->end[0]=img->end[img->dimt-1];
286 dimg->mid[0]=(dimg->start[0]+dimg->end[0])/2.0;
287 }
288 if(iimg!=NULL) {
289 imgCopyhdr(img, iimg);
290 iimg->start[0]=img->start[0]; iimg->end[0]=img->end[img->dimt-1];
291 iimg->mid[0]=(iimg->start[0]+iimg->end[0])/2.0;
292 }
293 iimg->unit=dimg->unit=CUNIT_UNITLESS;
294
295 /* Go through every pixel */
296 int ti, zi, xi, yi;
297 if(iimg!=NULL) {
298 for(zi=0; zi<img->dimz; zi++) {
299 for(yi=0; yi<img->dimy; yi++) for(xi=0; xi<img->dimx; xi++) {
300 for(ti=1; ti<img->dimt; ti++)
301 if(img->m[zi][yi][xi][ti]>img->m[zi][yi][xi][ti-1]) iimg->m[zi][yi][xi][0]+=1.0;
302 if(verbose>2) {printf("increases m[%d][%d][%d]=%g\n", zi, yi, xi, iimg->m[zi][yi][xi][0]);}
303 }
304 }
305 }
306 if(dimg!=NULL) {
307 for(zi=0; zi<img->dimz; zi++) {
308 for(yi=0; yi<img->dimy; yi++) for(xi=0; xi<img->dimx; xi++) {
309 for(ti=1; ti<img->dimt; ti++)
310 if(img->m[zi][yi][xi][ti]<img->m[zi][yi][xi][ti-1]) dimg->m[zi][yi][xi][0]+=1.0;
311 if(verbose>2) {printf("decreases m[%d][%d][%d]=%g\n", zi, yi, xi, dimg->m[zi][yi][xi][0]);}
312 }
313 }
314 }
315
316 return(0);
317}

◆ imgInv()

int imgInv ( IMG * img)
extern

Replace IMG data values by their inverse value (1/activity).

Pixels with <=0 are set to zero.

See also
imgLn, imgLog10, imgAbs, imgArithm
Returns
Returns 0, if ok.
Parameters
imgPointer to IMG data.

Definition at line 314 of file imgarithm.c.

317 {
318 if(img->status<IMG_STATUS_OCCUPIED) return(1);
319 if(img->dimt<1 || img->dimz<1 || img->dimy<1 || img->dimx<1) return(2);
320 for(int pi=0; pi<img->dimz; pi++)
321 for(int yi=0; yi<img->dimy; yi++)
322 for(int xi=0; xi<img->dimx; xi++)
323 for(int fi=0; fi<img->dimt; fi++) {
324 if(img->m[pi][yi][xi][fi]<=0.0) img->m[pi][yi][xi][fi]=0.0;
325 else {
326 img->m[pi][yi][xi][fi]=1.0/img->m[pi][yi][xi][fi];
327 if(!isfinite(img->m[pi][yi][xi][fi])) img->m[pi][yi][xi][fi]=0.0;
328 }
329 }
330 return(0);
331}

◆ imgLn()

int imgLn ( IMG * img)
extern

Replace IMG data values by their natural logarithms.

See also
imgLog10, imgAbs, imgArithm, imgInv, imgSS
Returns
Returns 0, if ok.
Parameters
imgPointer to IMG data.

Definition at line 248 of file imgarithm.c.

251 {
252 if(img->status<IMG_STATUS_OCCUPIED) return(1);
253 if(img->dimt<1 || img->dimz<1 || img->dimy<1 || img->dimx<1) return(2);
254 for(int pi=0; pi<img->dimz; pi++)
255 for(int yi=0; yi<img->dimy; yi++)
256 for(int xi=0; xi<img->dimx; xi++)
257 for(int fi=0; fi<img->dimt; fi++) {
258 if(img->m[pi][yi][xi][fi]<=0.0) img->m[pi][yi][xi][fi]=0.0;
259 else img->m[pi][yi][xi][fi]=log(img->m[pi][yi][xi][fi]);
260 }
261 return(0);
262}

◆ imgLog10()

int imgLog10 ( IMG * img)
extern

Replace IMG data values by their log10 values.

See also
imgLn, imgAbs, imgArithm
Returns
Returns 0, if ok.
Parameters
imgPointer to IMG data.

Definition at line 270 of file imgarithm.c.

273 {
274 if(img->status<IMG_STATUS_OCCUPIED) return(1);
275 if(img->dimt<1 || img->dimz<1 || img->dimy<1 || img->dimx<1) return(2);
276 for(int pi=0; pi<img->dimz; pi++)
277 for(int yi=0; yi<img->dimy; yi++)
278 for(int xi=0; xi<img->dimx; xi++)
279 for(int fi=0; fi<img->dimt; fi++) {
280 if(img->m[pi][yi][xi][fi]<=0.0) img->m[pi][yi][xi][fi]=0.0;
281 else img->m[pi][yi][xi][fi]=log10(img->m[pi][yi][xi][fi]);
282 }
283 return(0);
284}

◆ imgMaskCloak()

int imgMaskCloak ( IMG * img,
int dim,
float id )
extern

Cloak mask.

See also
imgMaskDilate, imgMaskErode
Returns
Returns 0 when successful.
Parameters
imgPointer to 2D/3D mask image.
dimCloak the existing mask in xy (2) or xyz (3) dimensions.
idId number for the cloak mask. Should be different from existing IDs.

Definition at line 429 of file mask.c.

436 {
437 if(img==NULL) return(1);
438 int dimx=img->dimx, dimy=img->dimy, dimz=img->dimz;
439 if(dimx<1 || dimy<1 || dimz<1) return(2);
440
441 for(int z=0; z<dimz; z++) {
442 for(int y=0; y<dimy; y++) {
443 for(int x=0; x<dimx; x++) if(!(img->m[z][y][x][0]<0.5) && img->m[z][y][x][0]!=id) {
444 int x1=x, x2=x, y1=y, y2=y, z1=z, z2=z;
445 if(x>0) x1=x-1;
446 if(x<dimx-1) x2=x+1;
447 if(y>0) y1=y-1;
448 if(y<dimy-1) y2=y+1;
449 if(dim==3) {
450 if(z>0) z1=z-1;
451 if(z<dimz-1) z2=z+1;
452 }
453 for(int nz=z1; nz<=z2; nz++)
454 for(int ny=y1; ny<=y2; ny++)
455 for(int nx=x1; nx<=x2; nx++)
456 if(z!=nz || y!=ny || x!=nx)
457 if(img->m[nz][ny][nx][0]<0.5)
458 img->m[nz][ny][nx][0]=id;
459 }
460 }
461 }
462
463 return(0);
464}

◆ imgMaskConjunction()

int imgMaskConjunction ( IMG * mask1,
IMG * mask2 )
extern

Conjunction (AND, wedge) for two 3D mask images.

See also
imgMaskInv, imgMaskDilate, imgMaskCount, imgMaskFloodFill
Returns
Returns 0 when successful.
Parameters
mask1Pointer to IMG structure containing the first mask image; will be overwritten by the conjunction mask.
mask2Pointer to IMG structure containing the second mask image; not modified.

Definition at line 238 of file mask.c.

244 {
245 if(mask1==NULL || mask2==NULL) return(1);
246 if(mask1->dimx<1 || mask1->dimy<1 || mask1->dimz<1) return(2);
247 if(mask1->dimx!=mask2->dimx) return(3);
248 if(mask1->dimy!=mask2->dimy) return(4);
249 if(mask1->dimz!=mask2->dimz) return(5);
250
251 int zi, yi, xi;
252 for(zi=0; zi<mask1->dimz; zi++)
253 for(yi=0; yi<mask1->dimy; yi++)
254 for(xi=0; xi<mask1->dimx; xi++) {
255 if(fabs(mask1->m[zi][yi][xi][0])<1.0E-12 ||
256 fabs(mask2->m[zi][yi][xi][0])<1.0E-12)
257 {
258 mask1->m[zi][yi][xi][0]=0.0;
259 } else {
260 mask1->m[zi][yi][xi][0]=1.0;
261 }
262 }
263
264 return(0);
265}

◆ imgMaskCount()

long long imgMaskCount ( IMG * img)
extern

Count the nr of positive values inside 3D mask image.

See also
imgMaskRoiNr, imgThresholdMask, imgMaskInvert, imgMaskFloodFill
Returns
Returns the number of positive voxels.
Parameters
imgPointer to mask IMG structure.

Definition at line 15 of file mask.c.

18 {
19 long long n=0;
20 int zi, yi, xi;
21 for(zi=0; zi<img->dimz; zi++)
22 for(yi=0; yi<img->dimy; yi++)
23 for(xi=0; xi<img->dimx; xi++)
24 if(img->m[zi][yi][xi][0]>0.0) n++;
25 return(n);
26}

◆ imgMaskDilate()

int imgMaskDilate ( IMG * img,
IMG * se )
extern

Dilate the 3D mask image.

See also
imgStructuringElement, imgMaskErode, imgMaskCloak, imgMaskCount, imgMaskFloodFill, imgSwell
Returns
Returns the number of dilated voxels, or <0 in case of an error.
Parameters
imgPointer to IMG structure containing the mask image.
sePointer to IMG structure containing the structuring element; all dimensions must be odd numbers.

Definition at line 80 of file mask.c.

86 {
87 if(img==NULL || se==NULL) return(-1);
88 if(img->dimx<1 || img->dimy<1 || img->dimz<1) return(-2);
89 if(se->dimx<1 || se->dimy<1 || se->dimz<1) return(-3);
90 if(se->dimx%2==0 || se->dimy%2==0 || se->dimz%2==0) return(-4);
91
92
93 /* make a copy of original data */
94 IMG orig; imgInit(&orig);
95 if(imgDup(img, &orig)!=0) return(-5);
96 long long n=0;
97 int zi, yi, xi, zj, yj, xj;
98 for(zi=0; zi<orig.dimz; zi++)
99 for(yi=0; yi<orig.dimy; yi++)
100 for(xi=0; xi<orig.dimx; xi++)
101 if(orig.m[zi][yi][xi][0]==0.0) {
102 int zs, ys, xs;
103 float mav=-1.0E+20;
104 for(zs=0; zs<se->dimz; zs++)
105 for(ys=0; ys<se->dimy; ys++)
106 for(xs=0; xs<se->dimx; xs++)
107 if(se->m[zs][ys][xs][0]>0.0) {
108 zj=zi+(zs-se->dimz/2); if(zj<0 || zj>=orig.dimz) continue;
109 yj=yi+(ys-se->dimy/2); if(yj<0 || yj>=orig.dimy) continue;
110 xj=xi+(xs-se->dimx/2); if(xj<0 || xj>=orig.dimx) continue;
111 if(orig.m[zj][yj][xj][0]>mav) mav=orig.m[zj][yj][xj][0];
112 }
113 if(mav>0.0) {img->m[zi][yi][xi][0]=mav; n++;}
114 }
115 imgEmpty(&orig);
116
117 return(n);
118}

◆ imgMaskErode()

int imgMaskErode ( IMG * img,
IMG * se )
extern

Erode the 3D mask image.

See also
imgStructuringElement, imgMaskDilate, imgMaskCount, imgShrink
Returns
Returns the number of eroded voxels, or <0 in case of an error.
Parameters
imgPointer to IMG structure containing the mask image.
sePointer to IMG structure containing the structuring element; all dimensions must be odd numbers.

Definition at line 34 of file mask.c.

40 {
41 if(img==NULL || se==NULL) return(-1);
42 if(img->dimx<1 || img->dimy<1 || img->dimz<1) return(-2);
43 if(se->dimx<1 || se->dimy<1 || se->dimz<1) return(-3);
44 if(se->dimx%2==0 || se->dimy%2==0 || se->dimz%2==0) return(-4);
45
46
47 /* make a copy of original data */
48 IMG orig; imgInit(&orig);
49 if(imgDup(img, &orig)!=0) return(-5);
50 long long n=0;
51 int zi, yi, xi, zj, yj, xj;
52 for(zi=0; zi<orig.dimz; zi++)
53 for(yi=0; yi<orig.dimy; yi++)
54 for(xi=0; xi<orig.dimx; xi++)
55 if(orig.m[zi][yi][xi][0]>0.0) {
56 int zs, ys, xs;
57 float miv=+1.0E+20;
58 for(zs=0; zs<se->dimz; zs++)
59 for(ys=0; ys<se->dimy; ys++)
60 for(xs=0; xs<se->dimx; xs++)
61 if(se->m[zs][ys][xs][0]>0.0) {
62 zj=zi+(zs-se->dimz/2); if(zj<0 || zj>=orig.dimz) continue;
63 yj=yi+(ys-se->dimy/2); if(yj<0 || yj>=orig.dimy) continue;
64 xj=xi+(xs-se->dimx/2); if(xj<0 || xj>=orig.dimx) continue;
65 if(orig.m[zj][yj][xj][0]<miv) miv=orig.m[zj][yj][xj][0];
66 }
67 if(!(miv>1.0E-20)) {img->m[zi][yi][xi][0]=0.0; n++;}
68 }
69 imgEmpty(&orig);
70
71 return(n);
72}

◆ imgMaskFloodFill()

int imgMaskFloodFill ( IMG * m,
int sz,
int sy,
int sx,
int label,
long long * n,
int verbose )
extern

Flood filling for the Region labelling.

Processes only the first frame, even if several do exist.

Based on Burger W and Burge MJ: Principles of Digital Image Processing - Core Algorithms, Springer, 2009, DOI 10.1007/978-1-84800-195-4.

See also
imgMaskRegionLabeling, imgMaskErode, imgMaskCount, imgMaskConjunction, imgMaskRoiNr
Returns
Returns 0 when successful.
Parameters
mPointer to IMG structure containing the mask image to be flood filled. Pixels with value 1 are flood filled with label, pixels with value <1 are considered as background, and pixels with values >1 are considered to belong to another already labelled region.
szZ coordinate of the starting point [0..dimz-1].
syY coordinate of the starting point [0..dimy-1].
sxX coordinate of the starting point [0..dimx-1].
labelThe label to be assigned to the region; at least 2.
nThe number of pixels that got labelled; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed into stdout or stderr.

Definition at line 352 of file mask.c.

370 {
371 if(verbose>0) {
372 printf("%s(mask, %d, %d, %d, %d)\n", __func__, sz, sy, sx, label);
373 fflush(stdout);
374 }
375 if(m==NULL || m->status!=IMG_STATUS_OCCUPIED) return(1);
376 if(m->dimx<1 || m->dimy<1 || m->dimz<1) return(2);
377 if(sx<0 || sy<0 || sz<0 || sx>=m->dimx || sy>=m->dimy || sz>=m->dimz) return(3);
378 if(label<2) return(4);
379 if(n!=NULL) *n=0;
380
381 /* Create empty stack of pixel coordinates */
382 IMG_PIXELS pxls; pxlInit(&pxls);
383
384 /* Put the start coordinate into the stack */
385 IMG_PIXEL pxl; pxl.x=sx; pxl.y=sy; pxl.z=sz;
386 if(pxlAdd(&pxls, &pxl)!=0) {
387 if(verbose>0) fprintf(stderr, "Error: cannot add seed pixel to stack.\n");
388 pxlFree(&pxls); return(11);
389 }
390
391 /* Process the stack until empty */
392 unsigned long long int pxlNr=0;
393 while(pxls.pxlNr>0) {
394 /* Take the last pixel from the list */
395 if(pxlGet(&pxls, pxls.pxlNr-1, &pxl)!=0) break;
396 pxls.pxlNr--;
397 /* Should this pixel be labelled? */
398 if(verbose>100) printf(" m[%d][%d][%d] := %g\n", pxl.z, pxl.y, pxl.x, m->m[pxl.z][pxl.y][pxl.x][0]);
399 if(pxl.z<0 || pxl.z>=m->dimz || pxl.y<0 || pxl.y>=m->dimy || pxl.x<0 || pxl.x>=m->dimx)
400 continue; // certainly not since outside of the image
401 if(m->m[pxl.z][pxl.y][pxl.x][0]!=1.0) continue; // no since labelled or part of background
402 m->m[pxl.z][pxl.y][pxl.x][0]=(float)label; // yes
403 if(verbose>100) printf(" -> m[%d][%d][%d] := %g\n", pxl.z, pxl.y, pxl.x, m->m[pxl.z][pxl.y][pxl.x][0]);
404 pxlNr++;
405 /* Add the 26 neighbours to the beginning of the stack */
406 if(pxlMakeRoom(&pxls, 0, 26)!=0) break;
407 if(pxls.pxlNr==0) pxls.pxlNr=26;
408 if(verbose>100) printf(" pxls.pxlNr := %lld\n", pxls.pxlNr);
409 unsigned long long int i=0;
410 for(int dz=-1; dz<2; dz++) for(int dy=-1; dy<2; dy++) for(int dx=-1; dx<2; dx++) {
411 if(dz==0 && dy==0 && dx==0) continue;
412 pxls.p[i].z=pxl.z+dz; pxls.p[i].y=pxl.y+dy; pxls.p[i].x=pxl.x+dx;
413 i++;
414 }
415 }
416 pxlFree(&pxls);
417 if(verbose>1) printf(" %lld pixels labelled.\n", pxlNr);
418 if(n!=NULL) *n=pxlNr;
419 if(pxlNr==0) return(21);
420 return(0);
421}
int pxlMakeRoom(IMG_PIXELS *list, long long int i, long long int n)
Definition pixel.c:110
void pxlFree(IMG_PIXELS *pxl)
Definition pixel.c:28
int pxlGet(IMG_PIXELS *list, long long int i, IMG_PIXEL *pxl)
Definition pixel.c:163
int pxlAdd(IMG_PIXELS *list, IMG_PIXEL *pxl)
Definition pixel.c:139
void pxlInit(IMG_PIXELS *pxl)
Definition pixel.c:14
IMG_PIXEL * p
long long int pxlNr

Referenced by imgMaskRegionLabeling().

◆ imgMaskInvert()

void imgMaskInvert ( IMG * img)
extern

Invert the 3D mask image, setting zeroes to ones, and non-zeroes to zeroes.

Processes only the first frame, even if several do exist.

See also
imgMaskCount, imgMaskRoiNr, imgThresholdMask, imgMaskFloodFill
Parameters
imgPointer to mask IMG structure.

Definition at line 216 of file mask.c.

219 {
220 if(img==NULL) return;
221 int zi, yi, xi;
222 for(zi=0; zi<img->dimz; zi++)
223 for(yi=0; yi<img->dimy; yi++)
224 for(xi=0; xi<img->dimx; xi++)
225 if(fabs(img->m[zi][yi][xi][0])>1.0E-12)
226 img->m[zi][yi][xi][0]=0.0;
227 else
228 img->m[zi][yi][xi][0]=1.0;
229 return;
230}

◆ imgMaskRegionLabeling()

int imgMaskRegionLabeling ( IMG * mask1,
IMG * mask2,
int * n,
int verbose )
extern

Region labelling with flood filling.

Processes only the first frame, even if several do exist.

Based on Burger W and Burge MJ: Principles of Digital Image Processing - Core Algorithms, Springer, 2009, DOI 10.1007/978-1-84800-195-4.

Returns
Returns 0 when successful.
See also
imgMaskFloodFill
Parameters
mask1Pointer to IMG structure containing the mask image to be region labelled; not modified. All pixels with value < 0.1 are considered to belong to background, others to foreground.
mask2Pointer to an empty but initiated IMG structure for the output, the region labelled mask image.
nThe number of regions that were found; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed into stdout or stderr

Definition at line 279 of file mask.c.

291 {
292 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
293 if(mask1==NULL || mask2==NULL || mask1==mask2) return(1);
294 if(mask1->status!=IMG_STATUS_OCCUPIED) return(2);
295 if(mask1->dimx<1 || mask1->dimy<1 || mask1->dimz<1) return(3);
296 if(verbose>1) printf("mask dimensions := %d x %d x %d\n", mask1->dimx, mask1->dimy, mask1->dimz);
297 if(n!=NULL) *n=0;
298
299 /* Make a copy of the mask */
300 imgEmpty(mask2);
301 long long nr;
302 if(imgThresholdMaskCount(mask1, 0.1, 1.0E+22, mask2, &nr)!=0) {
303 if(verbose>0) fprintf(stderr, "Error: cannot make initial copy of mask.\n");
304 return(11);
305 }
306 if(nr==0) {
307 if(verbose>0) fprintf(stderr, "Warning: empty mask.\n");
308 return(0);
309 }
310 if(verbose>1) printf("mask contains %lld foreground pixels.\n", nr);
311 if(verbose>80) {
312 for(int zi=0; zi<mask2->dimz; zi++)
313 for(int yi=0; yi<mask2->dimy; yi++)
314 for(int xi=0; xi<mask2->dimx; xi++)
315 if(mask2->m[zi][yi][xi][0]!=0.0)
316 printf(" %d,%d,%d\n", zi, yi, xi);
317 }
318
319 /* Label regions */
320 int ret=0, nextLabel=2;
321 for(int zi=0; zi<mask2->dimz; zi++)
322 for(int yi=0; yi<mask2->dimy; yi++)
323 for(int xi=0; xi<mask2->dimx; xi++)
324 if(mask2->m[zi][yi][xi][0]==1.0) {
325 ret=imgMaskFloodFill(mask2, zi, yi, xi, nextLabel, &nr, verbose);
326 if(ret!=0) break;
327 if(verbose>2) printf("%lld pixels labelled as %d\n", nr, nextLabel);
328 nextLabel++;
329 }
330 if(ret!=0) {
331 if(verbose>0) fprintf(stderr, "Error: Flood fill failed.\n");
332 imgEmpty(mask2); return(21);
333 }
334 if(verbose>0) printf("%d regions labelled.\n", nextLabel-2);
335 if(n!=NULL) *n=nextLabel-2;
336
337 return(0);
338}
int imgThresholdMaskCount(IMG *img, float minValue, float maxValue, IMG *timg, long long *count)
int imgMaskFloodFill(IMG *m, int sz, int sy, int sx, int label, long long *n, int verbose)
Definition mask.c:352

◆ imgMaskRoiNr()

int imgMaskRoiNr ( IMG * img,
INTEGER_LIST * list )
extern

Get the list of ROIs in the mask image.

See also
imgMaskCount, imgThresholdMaskCount, imgThresholdMask
Returns
Returns 0 if successful.
Parameters
imgPointer to mask image. Pixel values <=0 represent pixels outside any ROI, and each rounded positive integer value represents one ROI.
listInitiated list of integers.

Definition at line 176 of file imgeval.c.

182 {
183 /* Check the input */
184 if(img==NULL || list==NULL) return 1;
185
186 /* Clear any previous list contents */
187 if(list->nr>0) {integerListEmpty(list);}
188
189 /* Go through the mask image */
190 for(int zi=0; zi<img->dimz; zi++)
191 for(int yi=0; yi<img->dimy; yi++)
192 for(int xi=0; xi<img->dimx; xi++) {
193 int v=temp_roundf(img->m[zi][yi][xi][0]);
194 if(v>0) {
195 int ret=integerListAdd(list, v, 1);
196 if(ret<0) return(100+ret);
197 }
198 }
199 /* Sort the list */
200 integerListSort(list);
201
202 return 0;
203}
int integerListEmpty(INTEGER_LIST *l)
Definition intex.c:175
int integerListSort(INTEGER_LIST *l)
Definition intex.c:219
int integerListAdd(INTEGER_LIST *l, int v, int ifnew)
Definition intex.c:190
int temp_roundf(float e)
Definition petc99.c:20

◆ imgMaskTAC()

int imgMaskTAC ( IMG * img,
IMG * mask,
double * tac,
int verbose )
extern

Calculate TAC as weighted average of voxels in specified image data with relative weights given in a mask image.

See also
imgsegmThresholdMask, imgAverageMaskTAC, imgThresholdingLowHigh, imgThresholdMask
Returns
Returns 0 if successful.
Parameters
imgPointer to allocated image from which the weighted TAC is calculated.
maskPointer to mask image; x, y, and z dimensions must be the same as in the image to which the mask is applied.
tacPointer to an array where weighted pixel averages are written; it must be allocated for size >= dimt.
verboseVerbose level; set to <=0 to prevent all prints to stdout.

Definition at line 126 of file imgeval.c.

137 {
138 if(verbose>0) printf("imgMaskTAC()\n");
139
140 if(img->status<IMG_STATUS_OCCUPIED) return(1);
141 if(mask->status<IMG_STATUS_OCCUPIED) return(2);
142 if(mask->dimz!=img->dimz) return(3);
143 if(mask->dimy!=img->dimy) return(4);
144 if(mask->dimx!=img->dimx) return(5);
145 if(img->dimt<1 || mask->dimt<1) return(6);
146 if(tac==NULL) return(7);
147
148 /* Initiate TAC */
149 for(int fi=0; fi<img->dimt; fi++) tac[fi]=0.0;
150 /* Add weighted sum to TAC */
151 double w=0.0;
152 for(int zi=0; zi<mask->dimz; zi++)
153 for(int yi=0; yi<mask->dimy; yi++)
154 for(int xi=0; xi<mask->dimx; xi++) if(mask->m[zi][yi][xi][0]>0.0) {
155 for(int fi=0; fi<img->dimt; fi++)
156 tac[fi]+=mask->m[zi][yi][xi][0]*img->m[zi][yi][xi][fi];
157 w+=mask->m[zi][yi][xi][0];
158 }
159 /* Divide sum TAC by sum weights */
160 for(int fi=0; fi<img->dimt; fi++) tac[fi]/=w;
161 if(verbose>1) printf("mask_sum := %g\n", w);
162 if(w<=0.0 && verbose>0)
163 fprintf(stderr, "Warning: zero mask applied to image.\n");
164
165 return(0);
166}

◆ imgMeanFilter()

int imgMeanFilter ( IMG * img,
int xn,
int yn,
int zn,
int tn,
int verbose )
extern

Image mean filtering in 1-4 dimensions.

See also
imgSmoothOverFrames, imgGaussianAMFilter, imgSS, fMean1DFilter
Returns
If an error is encountered, function returns a non-zero value. Otherwise 0 is returned.
Parameters
imgImage data to be processed; data is overwritten with filtered image. All image frames are processed.
xnNumber of adjacent pixels in x dimension; Enter 0 to not filter in x dimension.
ynNumber of adjacent pixels in y dimension; Enter 0 to not filter in y dimension.
znNumber of adjacent pixels in z dimension; Enter 0 to not filter in z dimension.
tnNumber of adjacent pixels in t dimension; Enter 0 to not filter in t dimension.
verboseVerbose level; if zero, then only warnings are printed into stderr.

Definition at line 624 of file imgfilter.c.

638 {
639 if(verbose>0) printf("%s(*img, %d, %d, %d, %d)\n", __func__, xn, yn, zn, verbose);
640
641 if(img==NULL || img->dimz<1 || img->dimy<1 || img->dimx<1 || img->dimt<1) return(1);
642 int dimx=img->dimx, dimy=img->dimy, dimz=img->dimz, dimt=img->dimt;
643 if(dimx==1) xn=0;
644 if(dimy==1) yn=0;
645 if(dimz==1) zn=0;
646 if(dimt==1) tn=0;
647 if(!(xn>0) && !(yn>0) && !(zn>0) && !(tn>0)) {
648 if(verbose>1) printf(" no filtering done.\n");
649 return(0);
650 }
651 if((xn>0 && xn<3) || (yn>0 && yn<3) || (zn>0 && zn<3) || (tn>0 && tn<3)) {
652 if(verbose>1) printf(" invalid pixel number.\n");
653 return(1);
654 }
655 if((xn>0 && xn%2==0) || (yn>0 && yn%2==0) || (zn>0 && zn%2==0) || (tn>0 && tn%2==0)) {
656 if(verbose>1) printf(" invalid pixel number.\n");
657 return(1);
658 }
659 if((xn>0 && dimx<=xn) || (yn>0 && dimy<=yn) || (zn>0 && dimz<=zn) || (tn>0 && dimt<=tn)) {
660 if(verbose>1) printf(" invalid pixel number.\n");
661 return(1);
662 }
663
664
665 /*
666 * Filtering in x dimension
667 */
668 if(xn>=3) {
669 if(verbose>1) {printf(" filtering in x dimension\n"); fflush(stdout);}
670 float buf[dimx];
671 for(int z=0; z<dimz; z++)
672 for(int y=0; y<dimy; y++)
673 for(int t=0; t<dimt; t++) {
674 for(int x=0; x<dimx; x++) buf[x]=img->m[z][y][x][t];
675 if(!fMean1DFilter(buf, dimx, xn))
676 for(int x=0; x<dimx; x++) img->m[z][y][x][t]=buf[x];
677 }
678 }
679
680 /*
681 * Filtering in y dimension
682 */
683 if(yn>=3) {
684 if(verbose>1) {printf(" filtering in y dimension\n"); fflush(stdout);}
685 float buf[dimy];
686 for(int z=0; z<dimz; z++)
687 for(int x=0; x<dimx; x++)
688 for(int t=0; t<dimt; t++) {
689 for(int y=0; y<dimy; y++) buf[y]=img->m[z][y][x][t];
690 if(!fMean1DFilter(buf, dimy, yn))
691 for(int y=0; y<dimy; y++) img->m[z][y][x][t]=buf[y];
692 }
693 }
694
695 /*
696 * Filtering in z dimension
697 */
698 if(zn>=3) {
699 if(verbose>1) {printf(" filtering in z dimension\n"); fflush(stdout);}
700 float buf[dimz];
701 for(int y=0; y<dimy; y++)
702 for(int x=0; x<dimx; x++)
703 for(int t=0; t<dimt; t++) {
704 for(int z=0; z<dimz; z++) buf[z]=img->m[z][y][x][t];
705 if(!fMean1DFilter(buf, dimz, zn))
706 for(int z=0; z<dimz; z++) img->m[z][y][x][t]=buf[z];
707 }
708 }
709
710 /*
711 * Filtering in t dimension
712 */
713 if(tn>=3) {
714 if(verbose>1) {printf(" filtering in t dimension\n"); fflush(stdout);}
715 float buf[dimt];
716 for(int z=0; z<dimz; z++)
717 for(int y=0; y<dimy; y++)
718 for(int x=0; x<dimx; x++) {
719 for(int t=0; t<dimt; t++) buf[t]=img->m[z][y][x][t];
720 if(!fMean1DFilter(buf, dimt, tn))
721 for(int t=0; t<dimt; t++) img->m[z][y][x][t]=buf[t];
722 }
723 }
724
725
726 return(0);
727}
int fMean1DFilter(float *data, const int n, const int s)
Definition imgfilter.c:595

◆ imgMeanZ()

int imgMeanZ ( IMG * img1,
IMG * img2 )
extern

Calculate image average over z dimension (image planes).

See also
imgFlipAbove, img2cube
Returns
Returns 0 if successful.
Parameters
img1Pointer to input IMG data structure; not modified.
img2Pointer to output IMG data structure; allocated here.

Definition at line 157 of file imgflips.c.

162 {
163 if(img1==NULL || img2==NULL) return(1);
164 if(img1->dimz<1 || img1->dimy<1 || img1->dimx<1 || img1->dimt<1) return(1);
165
166 /* If z dim is already 1, then just duplicate the image */
167 if(img1->dimz==1) return(imgDup(img1, img2));
168
169 /* Allocate memory for the output image */
170 if(imgAllocateWithHeader(img2, 1, img1->dimy, img1->dimx, img1->dimt, img1)!=0)
171 return(3);
172
173 /* Sum over z dimension */
174 for(int zi=0; zi<img1->dimz; zi++)
175 for(int yi=0; yi<img1->dimy; yi++)
176 for(int xi=0; xi<img1->dimx; xi++)
177 for(int ti=0; ti<img1->dimt; ti++)
178 img2->m[0][yi][xi][ti]+=img1->m[zi][yi][xi][ti];
179
180 /* Divide by original z dimension */
181 for(int yi=0; yi<img2->dimy; yi++)
182 for(int xi=0; xi<img2->dimx; xi++)
183 for(int ti=0; ti<img2->dimt; ti++)
184 img2->m[0][yi][xi][ti]/=(float)img1->dimz;
185
186 return(0);
187}

◆ imgMRT()

int imgMRT ( IMG * img,
IMG * oimg,
int verbose )
extern

Calculate (incomplete) mean residence time (MRT) for every pixel in dynamic image.

MRT = area under moment curve (AUMC) / area under curve (AUC). Data is not extrapolated. Frame gaps or overlaps are not accepted.

See also
imgAUMC, imgGetMaxTime, imgGetPeak, imgGetMaxFrame, imgFramesCheck
Returns
Returns 0, if ok.
Parameters
imgPointer to dynamic image; not modified. Frame times are obligatory.
oimgPointer to empty IMG struct in which the AUMC will be written; any old contents are deleted.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 606 of file imgarithm.c.

614 {
615 if(verbose>0) printf("%s(*img, *oimg)\n", __func__);
616
617 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) return(1);
618 if(img->dimt<2) {
619 if(verbose>1) fprintf(stderr, "Error: dynamic image required.\n");
620 return(2);
621 }
622 if(!imgExistentTimes(img)) {
623 if(verbose>1) fprintf(stderr, "Error: unknown frame times.\n");
624 return(2);
625 }
626 if(oimg==NULL) return(3);
627 if(oimg->status==IMG_STATUS_OCCUPIED) imgEmpty(oimg);
628
629 if(imgFramesCheck(img, verbose-1)>0) {
630 if(verbose>1) fprintf(stderr, "Error: gaps or overlap between time frames.\n");
631 return(4);
632 }
633
634 /* Allocate memory for one frame */
635 int ret;
636 if(verbose>1) printf("allocating memory for %dx%dx%d pixels\n", img->dimz, img->dimy, img->dimx);
637 ret=imgAllocate(oimg, img->dimz, img->dimy, img->dimx, 1);
638 if(ret) return(ret);
639 /* set image header information */
640 imgCopyhdr(img, oimg);
641 oimg->start[0]=img->start[0]; oimg->end[0]=img->end[img->dimt-1];
642 oimg->mid[0]=(oimg->start[0]+oimg->end[0])/2.0;
643 oimg->unit=CUNIT_UNKNOWN;
644
645 /* Calculate AUMC, AUC, and MRT */
646 for(int zi=0; zi<img->dimz; zi++) {
647 for(int yi=0; yi<img->dimy; yi++) {
648 for(int xi=0; xi<img->dimx; xi++) {
649 float aumc=0.0, auc=0.0;
650 for(int ti=0; ti<img->dimt; ti++) {
651 if(isnan(img->m[zi][yi][xi][ti])) continue;
652 float fdur=img->end[ti]-img->start[ti]; if(!(fdur>0.0)) fdur=0.0;
653 aumc+=img->m[zi][yi][xi][ti]*img->mid[ti]*fdur;
654 auc+=img->m[zi][yi][xi][ti]*fdur;
655 }
656 float mrt=aumc/auc;
657 if(isfinite(mrt)) oimg->m[zi][yi][xi][0]=mrt; else oimg->m[zi][yi][xi][0]=0.0;
658 }
659 }
660 }
661
662 return(0);
663}

◆ imgOutlierFilter()

int imgOutlierFilter ( IMG * img,
float limit )
extern

Filter out pixels that are over limit x higher than their closest 8 neighbour pixels.

See also
imgFast2DGaussianFilter, imgFast3DGaussianFilter, imgThresholdingLowHigh
Returns
Returns the nr of filtered pixels, and negative value in case of an error.
Parameters
imgPointer to IMG struct which will be filtered here.
limitCut-off value.

Definition at line 339 of file imgthreshold.c.

344 {
345 int zi, yi, xi, fi;
346 long long nr=0;
347 float f;
348 IMG tmp;
349
350 if(img->status!=IMG_STATUS_OCCUPIED || img->dimt<1) return(-1);
351 imgInit(&tmp);
352 if(imgAllocate(&tmp, img->dimz, img->dimy, img->dimx, 1)!=0) return(-2);
353 /* Process one frame at a time */
354 for(fi=0; fi<img->dimt; fi++) {
355 /* Copy one frame to safety */
356 for(zi=0; zi<tmp.dimz; zi++)
357 for(yi=0; yi<tmp.dimy; yi++)
358 for(xi=0; xi<tmp.dimx; xi++)
359 tmp.m[zi][yi][xi][0]=img->m[zi][yi][xi][fi];
360 /* Go through it */
361 for(zi=0; zi<img->dimz; zi++) {
362 for(yi=1; yi<img->dimy-1; yi++) for(xi=1; xi<img->dimx-1; xi++) {
363 f=tmp.m[zi][yi][xi-1][0]+
364 tmp.m[zi][yi][xi+1][0]+
365 tmp.m[zi][yi-1][xi][0]+
366 tmp.m[zi][yi+1][xi][0]+
367 tmp.m[zi][yi+1][xi-1][0]+
368 tmp.m[zi][yi+1][xi+1][0]+
369 tmp.m[zi][yi-1][xi-1][0]+
370 tmp.m[zi][yi-1][xi+1][0];
371 f/=8.0;
372 if(img->m[zi][yi][xi][fi]>(limit*f)) {img->m[zi][yi][xi][fi]=f; nr++;}
373 }
374 } /* next plane */
375 } /* next frame */
376 imgEmpty(&tmp);
377
378 return(nr);
379}

◆ imgRawCountsPerTime()

int imgRawCountsPerTime ( IMG * img,
int operation )
extern

Divide or multiply raw data (sinogram) counts by frame duration.

If IMG is not raw data, division is quietly not done. Error is returned if sinogram does not contain frame times, except if sinogram contains only one time frame, also then division is not done.

See also
imgArithmConst, imgArithm, imgFrameIntegral
Returns
Returns 0 if ok.
Parameters
imgIMG containing raw data.
operation1=division, 0=multiply.

Definition at line 442 of file imgarithm.c.

447 {
448 int fi, zi, xi, yi, notime=0;
449 float f;
450
451 /* Check the input data */
452 if(operation!=0 && operation!=1) return(1);
453 if(img==NULL) return(2);
454 if(img->status!=IMG_STATUS_OCCUPIED) return(3);
455 if(img->type!=IMG_TYPE_RAW) return(0);
456 for(fi=0; fi<img->dimt; fi++) {
457 f=img->end[fi]-img->start[fi]; if(f<=1.0E-12) notime++;
458 }
459 if(notime>0) {
460 if(img->dimt>1) return(4);
461 else return(0); /* just one frame; might be parametric or transmission sinogram,
462 therefore no error. */
463 }
464 for(fi=0; fi<img->dimt; fi++) {
465 f=img->end[fi]-img->start[fi]; if(operation==1) f=1.0/f;
466 for(zi=0; zi<img->dimz; zi++)
467 for(yi=0; yi<img->dimy; yi++)
468 for(xi=0; xi<img->dimx; xi++)
469 img->m[zi][yi][xi][fi]*=f;
470 }
471 return(0);
472}

◆ imgRegionGrowingByThreshold()

int imgRegionGrowingByThreshold ( IMG * img,
const int sz,
const int sy,
const int sx,
float lthr,
float uthr,
IMG * mask,
int verbose )
extern

Seeded region growing based on thresholds.

Calls itself recursively until neighbouring pixels fall outside thresholds. Because of recursion, program which uses this function needs a large space for stack.

See also
imgMaskErode, imgMaskDilate, imgsegmClusterExpand
Returns
Returns 0, if seed pixel was added to mask, and 1 if not, and >1 in case of an error.
Parameters
imgPointer to static image data, to which the threshold is applied.
szSeed pixel position [z,y,x] as indices.
sySeed pixel position [z,y,x] as indices.
sxSeed pixel position [z,y,x] as indices.
lthrLower threshold as absolute value.
uthrUpper threshold as absolute value.
maskPointer to mask image; must have the same dimensions as the static image.
verboseVerbose level; if zero, then only warnings are printed into stderr.

Definition at line 394 of file imgthreshold.c.

411 {
412 if(verbose>0) {
413 printf("imgRegionGrowingByThreshold(img, %d, %d, %d, %g, %g, mask, %d)\n",
414 sz, sy, sx, lthr, uthr, verbose);
415 fflush(stdout);
416 }
417 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) return(2);
418 if(mask==NULL || mask->status!=IMG_STATUS_OCCUPIED) return(3);
419 if(img->dimz!=mask->dimz || img->dimy!=mask->dimy || img->dimx!=mask->dimx) return(4);
420 int dimz=img->dimz, dimy=img->dimy, dimx=img->dimx;
421
422 /* Check that seed pixel resides inside image volume */
423 if(sz<0 || sy<0 || sx<0 || sz>=dimz || sy>=dimy || sx>=dimx) {
424 if(verbose>1) printf("pixels does not reside inside image\n");
425 return(1);
426 }
427
428 /* Check that seed pixel is not already part of mask */
429 if(mask->m[sz][sy][sx][0]>0.5) {
430 if(verbose>1) printf("seed already belongs to mask\n");
431 return(1);
432 }
433
434 /* Threshold */
435 if(img->m[sz][sy][sx][0]<lthr || img->m[sz][sy][sx][0]>uthr) {
436 if(verbose>1) {
437 printf(" [%d][%d][%d] outside thresholds\n", sz, sy, sx);
438 fflush(stdout);
439 }
440 mask->m[sz][sy][sx][0]=0.0;
441 return(1);
442 }
443 if(verbose>1) {
444 printf(" [%d][%d][%d] added to mask\n", sz, sy, sx);
445 fflush(stdout);
446 }
447 mask->m[sz][sy][sx][0]=1.0;
448
449 /* Check the neighbouring pixels */
450 int nsz, nsy, nsx;
451 nsz=sz; nsy=sy; nsx=sx-1;
452 imgRegionGrowingByThreshold(img, nsz, nsy, nsx, lthr, uthr, mask, verbose);
453 nsz=sz; nsy=sy; nsx=sx+1;
454 imgRegionGrowingByThreshold(img, nsz, nsy, nsx, lthr, uthr, mask, verbose);
455 nsz=sz; nsy=sy-1; nsx=sx;
456 imgRegionGrowingByThreshold(img, nsz, nsy, nsx, lthr, uthr, mask, verbose);
457 nsz=sz; nsy=sy+1; nsx=sx;
458 imgRegionGrowingByThreshold(img, nsz, nsy, nsx, lthr, uthr, mask, verbose);
459 nsz=sz-1; nsy=sy; nsx=sx;
460 imgRegionGrowingByThreshold(img, nsz, nsy, nsx, lthr, uthr, mask, verbose);
461 nsz=sz+1; nsy=sy; nsx=sx;
462 imgRegionGrowingByThreshold(img, nsz, nsy, nsx, lthr, uthr, mask, verbose);
463
464 return(0);
465}
int imgRegionGrowingByThreshold(IMG *img, const int sz, const int sy, const int sx, float lthr, float uthr, IMG *mask, int verbose)

Referenced by imgRegionGrowingByThreshold().

◆ imgScale()

void imgScale ( IMG * src,
IMG * targ,
float zoom,
int method )
extern

Image size scaling using the defined method.

See also
integerScale, imgArithm, imgSwell, imgShrink
Parameters
srcSource image to be scaled.
targScaled image; must be allocated to the size of resulting image.
zoomScaling factor (integer); currently must be >=1.
methodMethod code number (not used yet).

Definition at line 123 of file imgtransform.c.

132 {
133 int frame, plane, x, y;
134 float **tmp_targ;
135
136 if(method==0) {} // prevent compiler warning
137
138 // Allocate memory for temporary target matrix:
139 tmp_targ = malloc(targ->dimy * sizeof(float*));
140 for(y=0; y<targ->dimy; y++)
141 tmp_targ[y] = malloc(targ->dimx * sizeof(float));
142
143 for(plane=0; plane<src->dimz; plane++)
144 for(frame=0; frame<src->dimt; frame++){
145 integerScale(frame, src->m[plane], tmp_targ, src->dimx, src->dimy, (int)roundf(zoom));
146 // Copy scaled image matrix to target image buffer:
147 for(y=0; y<targ->dimy; y++)
148 for(x=0; x<targ->dimx; x++)
149 targ->m[plane][y][x][frame] = tmp_targ[y][x];
150 }
151}
void integerScale(int frame, float ***src, float **targ, int width, int height, int zoom)

◆ imgsegmCalcMRL()

int imgsegmCalcMRL ( float y1[],
float y2[],
long long n )
extern

Calculates the maximum run length between given n length arrays of data.

See also
imgsegmPearson, imgsegmSimilar, imgsegmFindBestNeighbour, imgThresholdingLowHigh
Returns
Returns the maximum run length between given n length arrays of data.
Parameters
y1Array 1.
y2Array 2.
nLength of arrays.

Definition at line 567 of file imgsegm.c.

574 {
575 long long i, mrl=0, rl=0;
576 char last_sign=0, sign;
577
578 for(i=0; i<n; i++) {
579 if(y1[i]>y2[i]) sign=1; else if(y1[i]<y2[i]) sign=-1; else sign=0;
580 if(sign!=last_sign) {
581 rl=0; last_sign=sign;
582 } else {
583 if(sign!=0) {rl++; if(rl>mrl) mrl=rl;}
584 }
585 }
586 return(mrl);
587}

Referenced by imgsegmSimilar().

◆ imgsegmCheckNeighbours()

int imgsegmCheckNeighbours ( IMG * cimg,
int pi,
int ri,
int ci )
extern

Checks if neighbours of the specified pixel belong to any cluster.

See also
imgsegmFindBestNeighbour
Returns
Returns 1, if all are in clusters, and 0, if at least one is 'free'.
Parameters
cimgCluster image.
piPixel definition [z,y,x].
riPixel definition [z,y,x].
ciPixel definition [z,y,x].

Definition at line 398 of file imgsegm.c.

407 {
408 int pj, rj, cj;
409
410 for(pj=pi-1; pj<=pi+1; pj++) if(pj>=0 && pj<cimg->dimz)
411 for(rj=ri-1; rj<=ri+1; rj++) if(rj>=0 && rj<cimg->dimy)
412 for(cj=ci-1; cj<=ci+1; cj++) if(cj>=0 && cj<cimg->dimx)
413 if((pi!=pj || ri!=rj || ci!=cj) && cimg->m[pj][rj][cj][0]<-0.1) return(0);
414 return(1);
415}

◆ imgsegmClusterExpand()

int imgsegmClusterExpand ( IMG * cimg,
IMG * simg,
IMG * dimg,
int clusterID,
int pi,
int ri,
int ci,
int pj,
int rj,
int cj,
float CVlim,
float CClim,
int verbose )
extern

Expands the cluster locally to its neighbour pixels.

Calls itself recursively until neighbouring pixels do not belong to cluster. Because of recursion, program which uses this function needs a large space for stack: add the following line to your program: unsigned _stklen = 4194304;

See also
imgMaskErode, imgMaskDilate
Returns
Returns 0, if test pixel belongs to cluster, and 1 if not, and >1 in case of an error.
Parameters
cimgpointer to cluster image data.
simgpointer to sum image data.
dimgpointer to dynamic image data.
clusterIDnumber of cluster to be tested.
picoordinates of test pixel [z,y,x].
ricoordinates of test pixel [z,y,x].
cicoordinates of test pixel [z,y,x].
pjcoordinates of cluster start [z,y,x].
rjcoordinates of cluster start [z,y,x].
cjcoordinates of cluster start [z,y,x].
CVlimCV limit.
CClimCC limit.
verboseVerbose level; if zero, then only warnings are printed into stderr.

Definition at line 219 of file imgsegm.c.

246 {
247 if(verbose>0) {
248 printf("imgsegmClusterExpand(cimg, simg, dimg, %d, %d, %d, %d, %d, %d, %d, %f, %f, %d)\n",
249 clusterID, pi, ri, ci, pj, rj, cj, CVlim, CClim, verbose);
250 fflush(stdout);
251 }
252 if(cimg==NULL || cimg->status!=IMG_STATUS_OCCUPIED) return(2);
253 if(simg==NULL || simg->status!=IMG_STATUS_OCCUPIED) return(3);
254 if(dimg==NULL || dimg->status!=IMG_STATUS_OCCUPIED) return(4);
255
256 /* Check that test pixel resides inside image volume */
257 if(pi<0 || ri<0 || ci<0 || pi>=cimg->dimz || ri>=cimg->dimy || ci>=cimg->dimx) {
258 if(verbose>1) printf("pixels does not reside inside image\n");
259 return(1);
260 }
261
262 /* Check that test pixel is not already part of any cluster */
263 if(cimg->m[pi][ri][ci][0]>=-0.1) {
264 if(verbose>1)
265 printf("pixel already belongs to cluster %g\n", cimg->m[pi][ri][ci][0]);
266 return(1);
267 }
268
269 /* Check that AUCs are matching */
270 {
271 float mean=0.5*(simg->m[pi][ri][ci][0]+simg->m[pj][rj][cj][0]);
272 float a=simg->m[pi][ri][ci][0]-mean;
273 float b=simg->m[pj][rj][cj][0]-mean;
274 float cv;
275 if(fabs(mean)>1.0e-10) cv=(a*a + b*b) / mean; else cv=0.0;
276 if(verbose>2) printf("cv=%g CVlim=%g mean=%g\n", cv, CVlim, mean);
277 if(cv>CVlim) {
278 if(verbose>2) printf("AUCs are not matching, %g>%g\n", cv, CVlim);
279 return(1);
280 }
281 }
282
283 /* Check that TACs are correlating */
284 {
285 float r=imgsegmPearson(dimg->m[pj][rj][cj], dimg->m[pi][ri][ci], dimg->dimt);
286 if(verbose>3) printf(" r=%g CClim=%g\n", r, CClim);
287 if(r<CClim) {
288 if(verbose>2) printf("TACs are not correlating, %g<%g\n", r, CClim);
289 return(1);
290 }
291 }
292
293 /* If we got this far, the test pixel belongs to the cluster */
294 cimg->m[pi][ri][ci][0]=clusterID;
295 if(verbose>1) {
296 printf(" [%d][%d][%d] belongs to cluster %d\n", pi, ri, ci, clusterID);
297 fflush(stdout);
298 }
299
300 /* Check if the neighbouring pixels belong to this cluster */
301 for(int pk=pi-1; pk<=pi+1; pk++) if(pk>=0 && pk<cimg->dimz)
302 for(int rk=ri-1; rk<=ri+1; rk++) if(rk>=0 && rk<cimg->dimy)
303 for(int ck=ci-1; ck<=ci+1; ck++) if(ck>=0 && ck<cimg->dimx)
304 if((pk!=pi || rk!=ri || ck!=ci) && cimg->m[pk][rk][ck][0]<-0.1) {
305 int ret=imgsegmClusterExpand(cimg, simg, dimg, clusterID,
306 pk, rk, ck, pj, rj, cj, CVlim, CClim, verbose);
307 if(ret>1) return(ret);
308 }
309
310 return(0);
311}
float imgsegmPearson(float *x, float *y, long long nr)
Definition imgsegm.c:322
int imgsegmClusterExpand(IMG *cimg, IMG *simg, IMG *dimg, int clusterID, int pi, int ri, int ci, int pj, int rj, int cj, float CVlim, float CClim, int verbose)
Definition imgsegm.c:219
int mean(double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
Definition pearson.c:341

Referenced by imgsegmClusterExpand().

◆ imgsegmClusterMean()

int imgsegmClusterMean ( IMG * dimg,
IMG * cimg,
int clusterID,
float * avg,
int verbose )
extern

Calculates the average of pixels belonging to the specified cluster, and returns this average for each frame in the specified float array.

Cluster pixels do not have to be adjacent!

See also
imgsegmSimilar
Returns
Returns the nr of pixels that belong to this cluster, or <0 in case of an error.
Parameters
dimgDynamic image.
cimgCluster image.
clusterIDCluster number 0...
avgPointer to a float array where cluster average TAC is written.
verboseVerbose level; if zero, then only warnings are printed into stderr.

Definition at line 357 of file imgsegm.c.

368 {
369 int fi, pi, ri, ci;
370
371 /* Check the arguments */
372 if(dimg==NULL || cimg==NULL || avg==NULL) return(-1);
373 if(cimg->dimx!=dimg->dimx || cimg->dimy!=dimg->dimy || cimg->dimz!=dimg->dimz)
374 return(-2);
375
376 if(verbose>0) printf("calculating avg of cluster %d:", clusterID);
377 for(fi=0; fi<dimg->dimt; fi++) avg[fi]=0.0;
378 long long n=0;
379 for(pi=0; pi<cimg->dimz; pi++)
380 for(ri=0; ri<cimg->dimy; ri++)
381 for(ci=0; ci<cimg->dimx; ci++)
382 if(fabs(cimg->m[pi][ri][ci][0]-(float)clusterID)<0.1) {
383 for(fi=0; fi<dimg->dimt; fi++)
384 avg[fi]+=dimg->m[pi][ri][ci][fi];
385 n++;
386 }
387 if(n>0) for(fi=0; fi<dimg->dimt; fi++) avg[fi]/=(float)n;
388 if(verbose>0) printf(" %lld pixels\n", n);
389 return(n);
390}

Referenced by clusterTACs().

◆ imgsegmFindBestNeighbour()

int imgsegmFindBestNeighbour ( IMG * dimg,
IMG * cimg,
int pi,
int ri,
int ci )
extern

Combines this pixel to the cluster of the neighbour which has the best correlation.

All neighbours of the specified pixel must belong to some cluster (must be checked before calling this function).

See also
imgsegmCalcMRL, imgsegmCheckNeighbours
Returns
If ok, returns 0.
Parameters
dimgDynamic image.
cimgCluster image.
piPixel definition [z,y,x].
riPixel definition [z,y,x].
ciPixel definition [z,y,x].

Definition at line 427 of file imgsegm.c.

438 {
439 int pj, rj, cj;
440 float cc, best_cc, best_ID;
441
442 best_ID=-1.0; best_cc=-1.0e+20;
443 for(pj=pi-1; pj<=pi+1; pj++) if(pj>=0 && pj<cimg->dimz)
444 for(rj=ri-1; rj<=ri+1; rj++) if(rj>=0 && rj<cimg->dimy)
445 for(cj=ci-1; cj<=ci+1; cj++) if(cj>=0 && cj<cimg->dimx)
446 if((pi!=pj || ri!=rj || ci!=cj)) {
447 cc=imgsegmPearson(dimg->m[pj][rj][cj], dimg->m[pi][ri][ci], dimg->dimt);
448 if(cc>best_cc) {
449 best_cc=cc;
450 best_ID=cimg->m[pj][rj][cj][0];
451 }
452 }
453 if(best_ID<0.0) return(1);
454 cimg->m[pi][ri][ci][0]=best_ID;
455 return(0);
456}

◆ imgsegmFindMaxOutsideClusters()

int imgsegmFindMaxOutsideClusters ( IMG * sumimg,
IMG * cluster,
float * max,
int * plane,
int * row,
int * col )
extern

Finds the maximum sumimg pixel value, excluding all pixels which already belong to clusters (cluster>=0).

Returns
Returns 0, if max was found, >1 in case of an error, and -1, if all pixels already belong to clusters.
Parameters
sumimgIntegral image.
clusterCluster image.
maxFound max value.
planeFound max pixel [Z,y,x].
rowFound max pixel [z,Y,x].
colFound max pixel [z,y,X].

Definition at line 166 of file imgsegm.c.

179 {
180 int p, i, j, maxp=0, maxi=0, maxj=0;
181
182 if(sumimg->status!=IMG_STATUS_OCCUPIED) return(1);
183 if(cluster->status!=IMG_STATUS_OCCUPIED) return(2);
184 if(sumimg->dimt>1) return(3);
185 if(cluster->dimt>1) return(4);
186 if(sumimg->dimx!=cluster->dimx || sumimg->dimy!=cluster->dimy) return(5);
187 if(sumimg->dimz!=cluster->dimz) return(6);
188
189 *max=-1.0e8;
190 long long n=0;
191 for(p=0; p<sumimg->dimz; p++) {
192 for(j=0; j<sumimg->dimy; j++) for(i=0; i<sumimg->dimx; i++)
193 if(cluster->m[p][j][i][0]<-0.1) {
194 if(sumimg->m[p][j][i][0]>*max) {
195 *max=sumimg->m[p][j][i][0]; maxp=p; maxj=j; maxi=i;
196 }
197 n++;
198 }
199 }
200 if(n==0) return(-1);
201 *plane=maxp; *row=maxj; *col=maxi;
202 return(0);
203}

◆ imgsegmMaskToCluster()

int imgsegmMaskToCluster ( IMG * img)
extern

Sets 0 values in mask image to -1, and others to value 0.

Returns
Returns 0 if ok.
Parameters
imgPointer to the mask image.

Definition at line 142 of file imgsegm.c.

145 {
146 int plane, i, j;
147
148 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
149 if(img->dimt>1) return(2);
150 for(plane=0; plane<img->dimz; plane++)
151 for(j=0; j<img->dimy; j++) for(i=0; i<img->dimx; i++) {
152 if(img->m[plane][j][i][0]>0.0) img->m[plane][j][i][0]=0.0;
153 else img->m[plane][j][i][0]=-1.0;
154 }
155 return(0);
156}

◆ imgsegmPearson()

float imgsegmPearson ( float * x,
float * y,
long long nr )
extern

Calculates Pearson's correlation coefficient between x[] and y[] values.

Not corrected for sample size.

See also
regr_line, best_pearson, highest_slope, pearson, mean, imgsegmCalcMRL
Returns
Returns Pearson's correlation coefficient; in case of an error returns 0.
Parameters
xx axis values.
yy axis values.
nrnr of samples.

Definition at line 322 of file imgsegm.c.

329 {
330 int i;
331 float sumx=0.0, sumy=0.0, sumsx=0.0, sumsy=0.0, sumxy=0.0, r, q;
332
333 if(nr<1 || x==NULL || y==NULL) return(0.0);
334 if(nr<3) return(1.0);
335 for(i=0; i<nr; i++) {
336 sumx+=x[i]; sumy+=y[i];
337 sumsx+=x[i]*x[i]; sumsy+=y[i]*y[i];
338 sumxy+=x[i]*y[i];
339 }
340 q=(sumsx - sumx*sumx/(float)nr) * (sumsy - sumy*sumy/(float)nr);
341 if(q<=0.0) return(1.0);
342 r=(sumxy-((sumx*sumy)/(float)nr)) / sqrt(q);
343 return(r);
344}

Referenced by imgsegmClusterExpand(), and imgsegmFindBestNeighbour().

◆ imgsegmSimilar()

int imgsegmSimilar ( IMG * input,
int smoothDim,
int smoothNr,
IMG * output,
int verbose )
extern

Computes a smoothed image from the specified dynamic image with noise.

The TACs inside a matrix smoothDim*smoothDim*smoothDim are sorted by the MRL and AUC, and each TAC is replaced by the mean of the best smoothNr TACs. This function allocates memory for output and copies the header info.

See also
imgsegmCalcMRL, imgsegmFindBestNeighbour, imgFast3DGaussianFilter, imgAverageTAC
Returns
Returns 0 if ok.
Parameters
inputDynamic input image.
smoothDimSmoothing mask dimensions; either 3 or 5 (default).
smoothNrNr of TACs to average; default is 9.
outputSmoothed image.
verboseVerbose level; if zero, then only warnings are printed into stderr.

Definition at line 478 of file imgsegm.c.

489 {
490 int ret, pi, ri, ci, pj, rj, cj, mi, mj, fi, maskNr, smod;
491 IMG sum;
492 IMGSEGMMASK mask[125];
493
494
495 if(verbose>0) printf("in filterSimilar(input, %d, %d, output)\n", smoothDim, smoothNr);
496 /* Check the parameters */
497 if(input->status!=IMG_STATUS_OCCUPIED) return(1);
498 if(input->dimt<2) return(2);
499 if(smoothDim==3) smod=1; else smod=2;
500 if(smoothNr<2) smoothNr=9;
501
502 /* Compute AUC image */
503 imgInit(&sum);
504 ret=imgFrameIntegral(input, 0, input->dimt-1, &sum, verbose);
505 if(ret) return(10+ret);
506
507 /* Allocate space for smoothed image */
509 output, input->dimz, input->dimy, input->dimx, input->dimt, input);
510 if(ret) {imgEmpty(&sum); return(20+ret);}
511
512 /* One pixel at a time */
513 for(pi=0; pi<input->dimz; pi++) {
514 if(input->dimz>1) {fprintf(stdout, "."); fflush(stdout);}
515 for(ri=0; ri<input->dimy; ri++) {
516 for(ci=0; ci<input->dimx; ci++) {
517 /* Fill the smoothing mask values */
518 for(mi=0; mi<125; mi++) mask[mi].order=0;
519 mi=0;
520 for(pj=pi-smod; pj<=pi+smod; pj++) if(pj>=0 && pj<input->dimz) {
521 for(rj=ri-smod; rj<=ri+smod; rj++) if(rj>=0 && rj<input->dimy) {
522 for(cj=ci-smod; cj<=ci+smod; cj++) if(cj>=0 && cj<input->dimx) {
523 mask[mi].p=pj; mask[mi].r=rj; mask[mi].c=cj;
524 /* Calculate the AUC difference */
525 mask[mi].dauc=fabs(sum.m[pi][ri][ci][0]-sum.m[pj][rj][cj][0]);
526 /* Calculate the MRL */
527 mask[mi].mrl=imgsegmCalcMRL(input->m[pi][ri][ci], input->m[pj][rj][cj], input->dimt);
528 mi++;
529 }
530 }
531 }
532 maskNr=mi;
533 /* Put mask values in similarity order */
534 for(mi=0; mi<maskNr; mi++) {
535 mask[mi].order=0;
536 for(mj=0; mj<maskNr; mj++) {
537 if(mask[mj].dauc>mask[mi].dauc) mask[mi].order++;
538 if(mask[mj].mrl>mask[mi].mrl) mask[mi].order++;
539 }
540 }
541 qsort(mask, maskNr, sizeof(IMGSEGMMASK), imgsegmSimilarSort);
542 /* Calculate average */
543 mj=smoothNr; if(mj>maskNr/2) mj=maskNr/2;
544 for(fi=0; fi<input->dimt; fi++) {
545 output->m[pi][ri][ci][fi]=0.0;
546 for(mi=0; mi<mj; mi++) {
547 /*printf("order=%d pj=%d rj=%d cj=%d\n", mask[mi].order, mask[mi].p, mask[mi].r, mask[mi].c);*/
548 output->m[pi][ri][ci][fi]+=
549 input->m[mask[mi].p][mask[mi].r][mask[mi].c][fi];
550 }
551 output->m[pi][ri][ci][fi]/=(double)mj;
552 }
553 }
554 }
555 }
556 if(input->dimz>1) {fprintf(stdout, "\n"); fflush(stdout);}
557 imgEmpty(&sum);
558 return(0);
559}
int imgFrameIntegral(IMG *img, int first, int last, IMG *iimg, int verbose)
Definition imgarithm.c:346
int imgsegmCalcMRL(float y1[], float y2[], long long n)
Definition imgsegm.c:567

◆ imgsegmThreshold()

int imgsegmThreshold ( IMG * img,
float minValue,
float maxValue )
extern

Sets values <minValue to zero, and values >maxValue to maxValue.

See also
imgThresholdingLowHigh, imgsegmThresholdByMask
Returns
Returns 0 if ok.
Parameters
imgDynamic or static image.
minValueMin pixel value.
maxValueMax pixel value.

Definition at line 116 of file imgsegm.c.

123 {
124 int frame, plane, i, j;
125
126 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
127 for(plane=0; plane<img->dimz; plane++)
128 for(j=0; j<img->dimy; j++) for(i=0; i<img->dimx; i++)
129 for(frame=0; frame<img->dimt; frame++)
130 if(img->m[plane][j][i][frame]<minValue)
131 img->m[plane][j][i][frame]=0.0;
132 else if(img->m[plane][j][i][frame]>maxValue)
133 img->m[plane][j][i][frame]=maxValue;
134 return(0);
135}

◆ imgsegmThresholdByMask()

int imgsegmThresholdByMask ( IMG * img,
IMG * template,
float minValue,
float maxValue )
extern

Sets pixel values in img to minValue, if corresponding pixel value in the mask is == 2, and to maxValue, if mask value is == 1.

Only first plane of the mask is used.

See also
imgThresholdingLowHigh, imgsegmThreshold, imgThresholdMaskCount
Returns
Returns 0 if ok.
Parameters
imgDynamic image which is modified based on the mask.
templateMask image.
minValueThis value is put into img if template value is =2.
maxValueThis value is put into img if template value is =1.

Definition at line 83 of file imgsegm.c.

92 {
93 int frame, plane, i, j;
94
95 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
96 if(template->status!=IMG_STATUS_OCCUPIED) return(2);
97 for(plane=0; plane<img->dimz; plane++)
98 for(j=0; j<img->dimy; j++) for(i=0; i<img->dimx; i++)
99 if(template->m[plane][j][i][0]==1.0) {
100 for(frame=0; frame<img->dimt; frame++)
101 img->m[plane][j][i][frame]=minValue;
102 } else if(template->m[plane][j][i][0]==2.0) {
103 for(frame=0; frame<img->dimt; frame++)
104 img->m[plane][j][i][frame]=maxValue;
105 }
106 return(0);
107}

◆ imgsegmThresholdMask()

int imgsegmThresholdMask ( IMG * img,
float minValue,
float maxValue,
IMG * timg )
extern

Allocate and fill a mask image based on the specified image and threshold values.

If pixel value in original image is <minValue, sets the mask pixel to 1, if >maxValue, sets mask pixel to 2, and to 0, if value is between minValue and maxValue. Only first frame is used, allocated and filled.

See also
imgVoiMaskTAC, imgMaskTAC, imgThresholdMaskCount, imgMaskDilate, imgMaskErode
Returns
Returns 0 if ok.
Parameters
imgPointer to original (static) image.
minValueLower threshold limit.
maxValueUpper threshold limit.
timgPointer to initiated and empty mask image.

Definition at line 39 of file imgsegm.c.

48 {
49 int frame, plane, i, j, ret;
50
51 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
52 /* Allocate memory for the mask data */
53 ret=imgAllocateWithHeader(timg, img->dimz, img->dimy, img->dimx, 1, img);
54 if(ret) return(ret);
55 timg->start[0]=img->start[0]; timg->end[0]=img->end[img->dimt-1];
56 timg->mid[0]=(timg->start[0]+timg->end[0])/2.0;
57 timg->isWeight=0;
58
59 /* Make the mask data */
60 for(plane=0; plane<img->dimz; plane++)
61 for(j=0; j<img->dimy; j++) for(i=0; i<img->dimx; i++) {
62 frame=0;
63 if(img->m[plane][j][i][frame]<minValue)
64 timg->m[plane][j][i][frame]=1.0;
65 else if(img->m[plane][j][i][frame]>maxValue)
66 timg->m[plane][j][i][frame]=2.0;
67 else
68 timg->m[plane][j][i][frame]=0.0;
69 }
70 return(0);
71}
char isWeight

◆ imgSetScanner()

int imgSetScanner ( IMG * img,
int scanner_type )
extern

Sets scanner specific parameters in IMG data. If possible, set image zoom before calling this.

Returns
Returns 0, if ok.
Parameters
imgIMG data which is filled with scanner specific information
scanner_typeSCANNER_ECAT931, SCANNER_ADVANCE, SCANNER_HRPLUS, SCANNER_HRRT, SCANNER_STEVCT_PET, as defined in libtpcimgio.h

Definition at line 14 of file imgscanner.c.

20 {
21 int rayNr;
22
23 if(img->status<IMG_STATUS_OCCUPIED) return(1);
24 img->scanner=scanner_type;
25 /* Set zoom to 1.0, if it is not set */
26 if(img->zoom<=0.0) img->zoom=1.0;
27 /* Then the others */
28 if(scanner_type==SCANNER_ECAT931) {
29 // dimz 15
30 rayNr=192;
31 img->axialFOV=108.;
32 img->transaxialFOV=600.826;
33 img->sampleDistance=3.12932;
34 img->sizez=6.75;
35 } else if(scanner_type==SCANNER_ADVANCE) {
36 // dimz 35
37 rayNr=281;
38 img->axialFOV=153.;
39 img->transaxialFOV=550.;
40 img->sampleDistance=1.970177;
41 img->sizez=4.25;
42 } else if(scanner_type==SCANNER_HRPLUS) {
43 rayNr=288;
44 img->axialFOV=155.2;
45 img->transaxialFOV=583.;
46 img->sampleDistance=2.25; /* bin size */
47 img->sizez=2.425;
48 } else if(scanner_type==SCANNER_HRRT) {
49 rayNr=256;
50 img->axialFOV=252.28;
51 img->transaxialFOV=312.;
52 img->sampleDistance=1.08; /* bin size */
53 img->sizez=img->sizex=img->sizey=1.218750;
54 } else if(scanner_type==SCANNER_STEVCT_PET) {
55 // dimz 47
56 rayNr=0;
57 img->sizez=3.27;
58 img->sizex=img->sizey=5.46875;
59/*} else if(scanner_type==SCANNER_DMI_PET) { // Aino
60 rayNr=544;
61 img->axialFOV=200.;
62 img->transaxialFOV=700.;
63 img->sizez=nan("");
64 img->sizex=img->sizey=nan("");
65*/
66 } else
67 return(2);
68 /* If this is image, then set also pixel sizes */
69 if(img->type==IMG_TYPE_IMAGE) {
70 if(scanner_type!=SCANNER_HRRT && scanner_type!=SCANNER_STEVCT_PET) {
71 img->sizex=img->sizey=
72 img->sampleDistance*(float)rayNr / ( (float)img->dimx*img->zoom );
73 } else {
74 img->sizex=img->sizey=
75 img->transaxialFOV / ( (float)img->dimx*img->zoom );
76 }
77 }
78
79 return(0);
80}
#define SCANNER_ADVANCE
#define SCANNER_HRRT
#define SCANNER_HRPLUS
#define SCANNER_STEVCT_PET
#define SCANNER_ECAT931
float sampleDistance
float transaxialFOV
int scanner
float zoom
float axialFOV

Referenced by imgAnalyzeToEcat(), and imgNiftiToEcat().

◆ imgShrink()

int imgShrink ( IMG * img1,
IMG * img2,
int doz )
extern

Shrink the image data matrix into half of the original size in each dimension.

Eight neighbouring pixels are averaged into one pixel, without any interpolation etc.

See also
img2cube, imgScale, imgSwell, imgMaskErode
Returns
Returns 0 if ok.
Parameters
img1Pointer to the original image; not changed.
img2Pointer to the shrunken image; must be initiated. If allocated for correct size, then only pixel values are set; if not, then any previous contents are deleted, memory is allocated, header information is set, and of course the pixel values are set.
dozShrink (1) the image in z dimension (over image planes), or shrink only in x and y dimensions (0).

Definition at line 263 of file imgtransform.c.

274 {
275 if(img1==NULL || img2==NULL) return(1);
276 if(img1->dimz<1 || img1->dimy<2 || img1->dimx<2 || img1->dimt<1) return(2);
277
278 /* Set correct dimensions for the shrunken image */
279 int dimz, dimy, dimx;
280 if(doz!=0) dimz=0.5*img1->dimz; else dimz=img1->dimz;
281 dimy=0.5*img1->dimy;
282 dimx=0.5*img1->dimx;
283 /* Correct dimensions (add 1) if the original ones were odd */
284 if((img1->dimz % 2!=0.0) && doz!=0) dimz+=1;
285 if(img1->dimy % 2!=0.0) dimy+=1;
286 if(img1->dimx % 2!=0.0) dimx+=1;
287
288 /* If output image does not yet have these dimensions, then re-allocate it and set headers */
289 if(img2->dimz!=dimz || img2->dimy!=dimy || img2->dimx!=dimx || img2->dimt!=img1->dimt) {
290 /* Allocate memory for the image */
291 int ret=imgAllocateWithHeader(img2, dimz, dimy, dimx, img1->dimt, img1);
292 if(ret) return(10+ret);
293 /* Correct the pixel sizes so that the actual size (cm x cm) of the image won't change */
294 if(doz!=0) {img2->sizez=2.0*img1->sizez; img2->gapz=2.0*img1->gapz;}
295 img2->sizey=2.0*img1->sizey; img2->gapy=2.0*img1->gapy;
296 img2->sizex=2.0*img1->sizex; img2->gapx=2.0*img1->gapx;
297 }
298
299 /* Calculate the averages of 2x2x2 or 2x2 pixel areas */
300 if(doz!=0) {
301 int fi, pi, yi, xi, pc, yc, xc;
302 for(fi=0; fi<img2->dimt; fi++){
303 for(pi=0, pc=1; pi<img2->dimz; pi++) {
304 for(yi=0, yc=1; yi<img2->dimy; yi++) for(xi=0, xc=1; xi<img2->dimx; xi++) {
305 img2->m[pi][yi][xi][fi]=0.0;
306 if(2*pi+1==img1->dimz) pc=0;
307 if(2*yi+1==img1->dimy) yc=0;
308 if(2*xi+1==img1->dimx) xc=0;
309 img2->m[pi][yi][xi][fi]+=img1->m[2*pi][2*yi][2*xi][fi];
310 img2->m[pi][yi][xi][fi]+=img1->m[2*pi][2*yi][2*xi+xc][fi];
311 img2->m[pi][yi][xi][fi]+=img1->m[2*pi][2*yi+yc][2*xi][fi];
312 img2->m[pi][yi][xi][fi]+=img1->m[2*pi][2*yi+yc][2*xi+xc][fi];
313 img2->m[pi][yi][xi][fi]+=img1->m[2*pi+pc][2*yi][2*xi][fi];
314 img2->m[pi][yi][xi][fi]+=img1->m[2*pi+pc][2*yi][2*xi+xc][fi];
315 img2->m[pi][yi][xi][fi]+=img1->m[2*pi+pc][2*yi+yc][2*xi][fi];
316 img2->m[pi][yi][xi][fi]+=img1->m[2*pi+pc][2*yi+yc][2*xi+xc][fi];
317 img2->m[pi][yi][xi][fi]/=8.0;
318 } /* next row and column */
319 } /* next plane */
320 } /*next frame */
321 } else {
322 int fi, pi, yi, xi, yc, xc;
323 for(fi=0; fi<img2->dimt; fi++){
324 for(pi=0; pi<img2->dimz; pi++) {
325 for(yi=0, yc=1; yi<img2->dimy; yi++) for(xi=0, xc=1; xi<img2->dimx; xi++) {
326 img2->m[pi][yi][xi][fi]=0.0;
327 if(2*yi+1==img1->dimy) yc=0;
328 if(2*xi+1==img1->dimx) xc=0;
329 img2->m[pi][yi][xi][fi]+=img1->m[pi][2*yi][2*xi][fi];
330 img2->m[pi][yi][xi][fi]+=img1->m[pi][2*yi][2*xi+xc][fi];
331 img2->m[pi][yi][xi][fi]+=img1->m[pi][2*yi+yc][2*xi][fi];
332 img2->m[pi][yi][xi][fi]+=img1->m[pi][2*yi+yc][2*xi+xc][fi];
333 img2->m[pi][yi][xi][fi]/=4.0;
334 } /* next row and column */
335 } /* next plane */
336 } /*next frame */
337 }
338
339 return(0);
340}

◆ imgSmoothOverFrames()

int imgSmoothOverFrames ( IMG * img,
int n )
extern

Smooth dynamic image data over specified number of time frames.

Average is weighted by frame durations. Gaps or overlaps in frame times are not taken into account. Do not use this for quantitative analysis, but only for robust peak search etc.

See also
imgGetFrameDiff, imgGaussianFilter, imgMeanFilter, imgMeanZ
Returns
Non-zero value, if error is encountered, otherwise 0 is returned.
Parameters
imgPointer to IMG structure containing the 4D image data.
nNr of frames to average; n must be an odd number and at least 3.

Definition at line 136 of file imgframe.c.

141 {
142 int zi, yi, xi, fi, fj, m, f1, f2;
143
144 if(IMG_TEST) {fprintf(stdout, "%s(img, %d)\n", __func__, n); fflush(stdout);}
145 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
146 if(n<3) n=3; else if((n%2)==0) return(1);
147 if(img->dimt<n) return(0); // too few frames for smoothing
148 m=n/2;
149 double orig[img->dimt], vsum, fsum, fdur;
150 for(zi=0; zi<img->dimz; zi++) {
151 for(yi=0; yi<img->dimy; yi++) for(xi=0; xi<img->dimx; xi++) {
152 /* preserve original data for now */
153 for(fi=0; fi<img->dimt; fi++) orig[fi]=img->m[zi][yi][xi][fi];
154 /* frame-by-frame */
155 for(fi=0; fi<img->dimt; fi++) {
156 /* set frame range */
157 f1=fi-m; if(f1<0) f1=0;
158 f2=fi+m; if(f2>img->dimt-1) f2=img->dimt-1;
159 /* mean */
160 fsum=vsum=0.0;
161 for(fj=f1; fj<=f2; fj++) {
162 fdur=img->end[fj]-img->start[fj];
163 vsum+=fdur*orig[fj];
164 fsum+=fdur;
165 }
166 if(fsum<1.0E-010) return(2);
167 img->m[zi][yi][xi][fi]=vsum/fsum;
168 }
169 }
170 }
171 return(0);
172}

◆ imgStructuringElement()

int imgStructuringElement ( IMG * img,
const int structuring_element,
int verbose )
extern

Make 3D structuring element for eroding and dilation.

See also
imgMaskDilate, imgMaskErode
Returns
Returns 0 when successful.
Parameters
imgPointer to empty IMG struct for the element.
structuring_elementStructuring element:
  1. 3x3x3 cube
  2. rounded 3x3x3 cube (23 voxels)
  3. cube on its corner (star, consisting of 7 voxels).
verboseVerbose level; if zero, then only warnings are printed into stderr

Definition at line 126 of file mask.c.

137 {
138 if(img==NULL) return(1);
139 imgEmpty(img);
140
141 int ret=0;
142 if(structuring_element==1) {
143 if(verbose>0) printf("making cube as the structuring element\n");
144 ret=imgAllocate(img, 3, 3, 3, 1);
145 } else if(structuring_element==2) {
146 if(verbose>0) printf("making rounded cube as the structuring element\n");
147 ret=imgAllocate(img, 3, 3, 3, 1);
148 } else if(structuring_element==3) {
149 if(verbose>0) printf("making star as the structuring element\n");
150 ret=imgAllocate(img, 3, 3, 3, 1);
151 } else {
152 fprintf(stderr, "Error: unsupported structuring element.\n");
153 return(2);
154 }
155 if(verbose>0) {fflush(stdout);}
156 if(ret) {
157 fprintf(stderr, "Error: cannot allocate memory.\n");
158 imgEmpty(img);
159 return(3);
160 }
161
162 int z, y, x, n;
163
164 if(structuring_element==1) { // 3x3x3 cube
165 for(z=0; z<3; z++)
166 for(y=0; y<3; y++)
167 for(x=0; x<3; x++)
168 img->m[z][y][x][0]=1.0;
169 } else if(structuring_element==2) { // rounded 3x3x3 cube
170 for(z=0; z<3; z++)
171 for(y=0; y<3; y++)
172 for(x=0; x<3; x++)
173 if(z==1 || y==1 || x==1)
174 img->m[z][y][x][0]=1.0;
175 else
176 img->m[z][y][x][0]=0.0;
177 } else if(structuring_element==3) { // 7-voxel star
178 for(z=0; z<3; z++)
179 for(y=0; y<3; y++)
180 for(x=0; x<3; x++) {
181 n=0;
182 if(z==1) n++;
183 if(y==1) n++;
184 if(x==1) n++;
185 if(n>1)
186 img->m[z][y][x][0]=1.0;
187 else
188 img->m[z][y][x][0]=0.0;
189 }
190 }
191
192 if(verbose>3) {
193 int z, y, x;
194 printf("\nplanes 1-3\n");
195 for(x=0; x<3; x++) {
196 for(z=0; z<3; z++) {
197 for(y=0; y<3; y++)
198 printf(" %g", img->m[z][y][x][0]);
199 printf(" ");
200 }
201 printf("\n");
202 }
203 printf("\n");
204 }
205 return(0);
206}

◆ imgSwell()

int imgSwell ( IMG * img1,
IMG * img2,
int doz )
extern

Inflate the image data matrix into twice the original size in each dimension.

Each pixel is inflated into eight pixels, without any interpolation etc.

See also
imgShrink, img2cube, imgScale
Returns
Returns 0 if ok.
Parameters
img1Pointer to the original image; not changed.
img2Pointer to the swollen image; must be initiated. If allocated for correct size, then only pixel values are set; if not, then any previous contents are deleted, memory is allocated, header information is set, and of course the pixel values are set.
dozInflate (1) the image in z dimension (over image planes), or only in x,y dimensions (0).

Definition at line 202 of file imgtransform.c.

212 {
213 if(img1==NULL || img2==NULL) return(1);
214 if(img1->dimz<1 || img1->dimy<1 || img1->dimx<1 || img1->dimt<1) return(2);
215
216 /* Set correct dimensions for the swollen image */
217 int dimz, dimy, dimx;
218 if(doz!=0) dimz=2*img1->dimz; else dimz=img1->dimz;
219 dimy=2*img1->dimy;
220 dimx=2*img1->dimx;
221
222 /* If output image does not yet have these dimensions, then re-allocate it and set headers */
223 if(img2->dimz!=dimz || img2->dimy!=dimy || img2->dimx!=dimx || img2->dimt!=img1->dimt) {
224 /* Allocate memory for the image */
225 int ret=imgAllocateWithHeader(img2, dimz, dimy, dimx, img1->dimt, img1);
226 if(ret) return(10+ret);
227 /* Correct the pixel sizes so that the actual size (cm x cm) of the image won't change */
228 if(doz!=0) {img2->sizez=0.5*img1->sizez; img2->gapz=0.5*img1->gapz;}
229 img2->sizey=0.5*img1->sizey; img2->gapy=0.5*img1->gapy;
230 img2->sizex=0.5*img1->sizex; img2->gapx=0.5*img1->gapx;
231 }
232
233 /* Fill the output image matrix */
234 if(doz!=0) {
235 int x, y, z;
236 for(z=0; z<img1->dimz; z++) for(y=0; y<img1->dimy; y++) for(x=0; x<img1->dimx; x++) {
237 int nz, ny, nx;
238 for(nz=2*z; nz<2+2*z; nz++) for(ny=2*y; ny<2+2*y; ny++) for(nx=2*x; nx<2+2*x; nx++) {
239 for(int t=0; t<img1->dimt; t++) img2->m[nz][ny][nx][t]=img1->m[z][y][x][t];
240 }
241 }
242 } else {
243 int x, y, z;
244 for(z=0; z<img1->dimz; z++) for(y=0; y<img1->dimy; y++) for(x=0; x<img1->dimx; x++) {
245 int ny, nx;
246 for(ny=2*y; ny<2+2*y; ny++) for(nx=2*x; nx<2+2*x; nx++) {
247 for(int t=0; t<img1->dimt; t++) img2->m[z][ny][nx][t]=img1->m[z][y][x][t];
248 }
249 }
250 }
251
252 return(0);
253}

◆ imgThresholdByMask()

int imgThresholdByMask ( IMG * img,
IMG * templt,
float thrValue )
extern

Threshold IMG by a mask image (template).

Sets pixel values in img to thrValue, if corresponding pixel value in template is == 0. Only first frame of template is used.

See also
imgThresholdMask, imgThresholdMaskCount, imgMaskTAC
Returns
Returns 0, if ok.
Parameters
imgImage to threshold.
templtThreshold template (mask image with 1 frame) where 0=cut off.
thrValueValue which is written in cut off pixels.

Definition at line 282 of file imgthreshold.c.

289 {
290 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
291 if(templt->status!=IMG_STATUS_OCCUPIED) return(2);
292 for(int zi=0; zi<img->dimz; zi++)
293 for(int yi=0; yi<img->dimy; yi++) for(int xi=0; xi<img->dimx; xi++)
294 if(templt->m[zi][yi][xi][0]==0.0) {
295 for(int fi=0; fi<img->dimt; fi++) img->m[zi][yi][xi][fi]=thrValue;
296 }
297 return(0);
298}

◆ imgThresholding()

int imgThresholding ( IMG * img,
float threshold_level,
long long * thr_nr )
extern

Threshold dynamic or static IMG data.

Pixel time-activity curves (TACs) which have AUC less than Threshold*Max_AUC will be set to zero.

See also
imgsegmThresholdByMask, imgThresholdingLowHigh, imgFast3DGaussianFilter, imgsegmThreshold, imgMax, imgMinMax, imgFrameIntegral
Returns
Returns 0, if ok.
Parameters
imgIMG data.
threshold_levelThreshold level, e.g. 0.50 will set to zero all pixels that are less than 50% of maximum pixel.
thr_nrNumber of pixels that will fall below the threshold level; give NULL pointer, if not needed.

Definition at line 19 of file imgthreshold.c.

26 {
27 int zi, yi, xi, fi, ret;
28 long long nr=0;
29 IMG aucimg;
30 float maxauc, thr_limit;
31
32 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
33 if(img->dimt>1) { // dynamic image
34 /* Calculate AUC image */
35 imgInit(&aucimg);
36 ret=imgFrameIntegral(img, 0, img->dimt-1, &aucimg, 0);
37 if(ret) return(ret);
38 /* Search the max AUC */
39 ret=imgMax(&aucimg, &maxauc); if(ret) {imgEmpty(&aucimg); return(ret);}
40 /* Calculate the limit value */
41 thr_limit=threshold_level*maxauc;
42 /* Set to zero the pixels with AUC less than this limit */
43 for(zi=0; zi<img->dimz; zi++)
44 for(yi=0; yi<img->dimy; yi++)
45 for(xi=0; xi<img->dimx; xi++)
46 if(aucimg.m[zi][yi][xi][0]<thr_limit) {
47 for(fi=0; fi<img->dimt; fi++) img->m[zi][yi][xi][fi]=0.0;
48 nr++;
49 }
50 imgEmpty(&aucimg);
51 } else { // static image
52 /* Search the max value */
53 ret=imgMax(img, &maxauc); if(ret) return(ret);
54 /* Calculate the limit value */
55 thr_limit=threshold_level*maxauc;
56 /* Set to zero the pixels with AUC less than this limit */
57 for(zi=0; zi<img->dimz; zi++)
58 for(yi=0; yi<img->dimy; yi++)
59 for(xi=0; xi<img->dimx; xi++)
60 if(img->m[zi][yi][xi][0]<thr_limit) {
61 for(fi=0; fi<img->dimt; fi++) img->m[zi][yi][xi][fi]=0.0;
62 nr++;
63 }
64 }
65 if(thr_nr!=NULL) *thr_nr=nr;
66 return(0);
67}
int imgMax(IMG *img, float *maxvalue)
Definition imgminmax.c:15

◆ imgThresholdingLowHigh()

int imgThresholdingLowHigh ( IMG * img,
float lower_threshold_level,
float upper_threshold_level,
IMG * timg,
long long * lower_thr_nr,
long long * upper_thr_nr )
extern

Threshold dynamic or static IMG data.

Checks whether pixel AUCs are lower or higher than the specified threshold levels * Max_AUC. Those pixel TACs are set to zero, or alternatively, if mask IMG is given, corresponding mask image pixel is set to 0.

See also
imgsegmThresholdByMask, imgVoiMaskTAC, imgMaskTAC, imgsegmThreshold, imgFrameIntegral
Returns
Returns 0, if ok.
Parameters
img(Dynamic) IMG data.
lower_threshold_levelLower threshold level, e.g. 0.10 will set to zero all pixels that are less than 10% of maximum pixel
upper_threshold_levelUpper threshold level, e.g. 0.90 will set to zero all pixels that are over 90% of maximum pixel
timgMask image; if empty, then it will be allocated here; if pre-allocated, then mask image value changed to 0 when necessary, but 0 is never changed to 1; enter NULL, if original TACs are to be thresholded to zeroes
lower_thr_nrNumber of pixels that will fall below the lower threshold level; give NULL pointer, if not needed.
upper_thr_nrNumber of pixels rejected because above the upper threshold level; give NULL pointer, if not needed.

Definition at line 79 of file imgthreshold.c.

99 {
100 int zi, yi, xi, fi, ret;
101 long long lnr=0, unr=0;
102 IMG aucimg;
103 float maxauc, lower_thr_limit, upper_thr_limit;
104
105 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
106
107 /* Check if mask image is given and if it exists */
108 if(timg!=NULL && timg->status!=IMG_STATUS_OCCUPIED) {
109 /* Allocate memory for the mask data */
110 ret=imgAllocate(timg, img->dimz, img->dimy, img->dimx, 1);
111 if(ret) return(ret);
112 /* set mask image header information */
113 imgCopyhdr(img, timg);
114 timg->start[0]=img->start[0]; timg->end[0]=img->end[img->dimt-1];
115 timg->mid[0]=(timg->start[0]+timg->end[0])/2.0;
116 /* Initiate mask to 1 */
117 for(zi=0; zi<img->dimz; zi++)
118 for(yi=0; yi<img->dimy; yi++)
119 for(xi=0; xi<img->dimx; xi++)
120 timg->m[zi][yi][xi][0]=1.0;
121 } else if(timg!=NULL) {
122 /* Check that mask dimensions are ok */
123 if(timg->dimz!=img->dimz || timg->dimy!=img->dimy || timg->dimx!=img->dimx) return 2;
124 if(timg->dimt<1) return 3;
125 }
126
127 /* Threshold */
128 if(img->dimt>1) { // dynamic image
129 /* Calculate AUC image */
130 imgInit(&aucimg);
131 ret=imgFrameIntegral(img, 0, img->dimt-1, &aucimg, 0);
132 if(ret) return(ret);
133 /* Search the max AUC */
134 ret=imgMax(&aucimg, &maxauc); if(ret) {imgEmpty(&aucimg); return(ret);}
135 /* Calculate the limit values */
136 lower_thr_limit=lower_threshold_level*maxauc;
137 upper_thr_limit=upper_threshold_level*maxauc;
138 /* Set to zero the pixels with AUC less/more than these limits */
139 for(zi=0; zi<img->dimz; zi++)
140 for(yi=0; yi<img->dimy; yi++)
141 for(xi=0; xi<img->dimx; xi++)
142 if(aucimg.m[zi][yi][xi][0]<lower_thr_limit) {
143 if(timg==NULL) for(fi=0; fi<img->dimt; fi++) img->m[zi][yi][xi][fi]=0.0;
144 else timg->m[zi][yi][xi][0]=0.0;
145 lnr++;
146 } else if(aucimg.m[zi][yi][xi][0]>upper_thr_limit) {
147 if(timg==NULL) for(fi=0; fi<img->dimt; fi++) img->m[zi][yi][xi][fi]=0.0;
148 else timg->m[zi][yi][xi][0]=0.0;
149 unr++;
150 }
151 imgEmpty(&aucimg);
152 } else { // static image
153 /* Search the max value */
154 ret=imgMax(img, &maxauc); if(ret) return(ret);
155 /* Calculate the limit values */
156 lower_thr_limit=lower_threshold_level*maxauc;
157 upper_thr_limit=upper_threshold_level*maxauc;
158 /* Set to zero the pixels with AUC less/more than these limits */
159 for(zi=0; zi<img->dimz; zi++)
160 for(yi=0; yi<img->dimy; yi++)
161 for(xi=0; xi<img->dimx; xi++)
162 if(img->m[zi][yi][xi][0]<lower_thr_limit) {
163 if(timg==NULL) for(fi=0; fi<img->dimt; fi++) img->m[zi][yi][xi][fi]=0.0;
164 else timg->m[zi][yi][xi][0]=0.0;
165 lnr++;
166 } else if(img->m[zi][yi][xi][0]>upper_thr_limit) {
167 if(timg==NULL) for(fi=0; fi<img->dimt; fi++) img->m[zi][yi][xi][fi]=0.0;
168 else timg->m[zi][yi][xi][0]=0.0;
169 unr++;
170 }
171 }
172
173 if(lower_thr_nr!=NULL) *lower_thr_nr=lnr;
174 if(upper_thr_nr!=NULL) *upper_thr_nr=unr;
175 return(0);
176}

◆ imgThresholdMask()

int imgThresholdMask ( IMG * img,
float minValue,
float maxValue,
IMG * timg )
extern

Creates a mask (template) image based on lower and upper threshold values.

This function allocates memory for the mask image. If pixel value in original image is >=minValue and <=maxValue, the corresponding mask pixel is set to 1, otherwise to 0. Only the first frame of images are used.

See also
imgThresholdMaskCount, imgsegmThresholdByMask, imgAverageMaskTAC, imgMinMax, imgMaskDilate, imgMaskErode, imgThresholdingLowHigh, imgsegmThreshold
Returns
Returns 0 if ok.
Parameters
imgOriginal image; only first frame is used here.
minValueLower threshold.
maxValueUpper threshold.
timgMask image; if empty, then it will be allocated here; if pre-allocated, then mask pixel value changed to 0 when necessary, but 0 is never changed to 1.

Definition at line 257 of file imgthreshold.c.

268 {
269 return(imgThresholdMaskCount(img, minValue, maxValue, timg, NULL));
270}

◆ imgThresholdMaskCount()

int imgThresholdMaskCount ( IMG * img,
float minValue,
float maxValue,
IMG * timg,
long long * count )
extern

Creates a mask (template) image based on lower and upper threshold values.

This function allocates memory for the mask image. If pixel value in original image is >=minValue and <=maxValue, the corresponding mask pixel is set to 1, otherwise to 0. Only the first frame of images are used.

See also
imgThresholdMask, imgThresholdByMask, imgsegmThresholdByMask, imgMaskRoiNr, imgMaskDilate, imgMaskErode, imgMinMax
Returns
Returns 0 if ok.
Parameters
imgOriginal image; only first frame is used here.
minValueLower threshold.
maxValueUpper threshold.
timgMask image; if empty, then it will be allocated here; if pre-allocated, then template value changed to 0 when necessary, but 0 is never changed to 1.
countThe number of pixels that pass the threshold limits is written here; set to NULL if not needed.

Definition at line 191 of file imgthreshold.c.

205 {
206 int fi=0, zi, xi, yi, ret;
207
208 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
209 if(count!=NULL) *count=0;
210 /* Check if mask image exists */
211 if(timg->status!=IMG_STATUS_OCCUPIED) {
212 /* Allocate memory for the template data */
213 ret=imgAllocate(timg, img->dimz, img->dimy, img->dimx, 1);
214 if(ret) return(ret);
215 /* set mask image header information */
216 imgCopyhdr(img, timg);
217 timg->start[0]=img->start[0]; timg->end[0]=img->end[img->dimt-1];
218 timg->mid[0]=(timg->start[0]+timg->end[0])/2.0;
219 /* Initiate template to 1 */
220 for(zi=0; zi<img->dimz; zi++)
221 for(yi=0; yi<img->dimy; yi++)
222 for(xi=0; xi<img->dimx; xi++)
223 timg->m[zi][yi][xi][0]=1.0;
224 } else {
225 /* Check that mask image dimensions are ok */
226 if(timg->dimz!=img->dimz || timg->dimy!=img->dimy || timg->dimx!=img->dimx)
227 return 2;
228 if(timg->dimt<1) return(3);
229 }
230 /* Set mask contents */
231 fi=0;
232 long long n=0;
233 for(zi=0; zi<img->dimz; zi++)
234 for(yi=0; yi<img->dimy; yi++)
235 for(xi=0; xi<img->dimx; xi++) {
236 /*printf("pxl=%g (%g - %g)\n", img->m[zi][yi][xi][fi], minValue, maxValue);*/
237 if(img->m[zi][yi][xi][fi]<minValue || img->m[zi][yi][xi][fi]>maxValue)
238 timg->m[zi][yi][xi][0]=0.0;
239 else n++;
240 }
241 if(count!=NULL) *count=n;
242 return(0);
243}

Referenced by imgMaskRegionLabeling(), and imgThresholdMask().

◆ imgVoiMaskTAC()

int imgVoiMaskTAC ( IMG * img,
IMG * mask,
int mv,
double * tac,
int verbose )
extern

Calculate TAC as average of voxels in image data, including only voxels which have specified value in the mask image.

See also
imgsegmThresholdMask, imgMaskTAC, imgMaskDilate, imgMaskErode
Returns
Returns the nr of voxels included, or <0 in case of an error.
Parameters
imgPointer to allocated image from which the mean TAC is calculated.
maskPointer to mask image; x, y, and z dimensions must be the same as in the image to which the mask is applied.
mvVoxels with this value in mask image are included in the average.
tacPointer to an array where weighted pixel averages are written; it must be allocated for size >= dimt.
verboseVerbose level; set to <=0 to prevent all prints to stdout.

Definition at line 214 of file imgeval.c.

227 {
228 if(verbose>0) printf("imgVoiMaskTAC(img, mask, %d, tac, %d)\n", mv, verbose);
229
230 if(img->status<IMG_STATUS_OCCUPIED) return(-1);
231 if(mask->status<IMG_STATUS_OCCUPIED) return(-2);
232 if(mask->dimz!=img->dimz) return(-3);
233 if(mask->dimy!=img->dimy) return(-4);
234 if(mask->dimx!=img->dimx) return(-5);
235 if(img->dimt<1 || mask->dimt<1) return(-6);
236 if(tac==NULL) return(-7);
237
238 /* Initiate TAC */
239 for(int fi=0; fi<img->dimt; fi++) tac[fi]=0.0;
240
241 /* Add the sum to TAC */
242 int pxlNr[img->dimt], badNr[img->dimt];
243 for(int fi=0; fi<img->dimt; fi++) pxlNr[fi]=badNr[fi]=0;
244 for(int zi=0; zi<mask->dimz; zi++) {
245 for(int yi=0; yi<mask->dimy; yi++) {
246 for(int xi=0; xi<mask->dimx; xi++) {
247 double mf=(int)temp_roundf(mask->m[zi][yi][xi][0]);
248 if(mf!=mv) continue;
249 for(int fi=0; fi<img->dimt; fi++) {
250 if(!isfinite(img->m[zi][yi][xi][fi])) {badNr[fi]++; continue;}
251 tac[fi]+=img->m[zi][yi][xi][fi]; pxlNr[fi]++;
252 }
253 }
254 }
255 }
256
257 /* Divide sum TAC by sum weights */
258 int minNr=pxlNr[0];
259 for(int fi=0; fi<img->dimt; fi++) {
260 if(badNr[fi]>0 && verbose>1) {
261 fprintf(stderr, "Warning: %d missing pixel values in frame %d.\n", badNr[fi], 1+fi);
262 fflush(stderr);
263 }
264 if(pxlNr[fi]==0) {
265 if(verbose>0) {
266 fprintf(stderr, "Warning: zero valid pixels in frame %d.\n", 1+fi); fflush(stderr);
267 }
268 tac[fi]=nan("");
269 }
270 if(verbose>1) {
271 printf("%d valid pixels inside mask in frame %d\n", pxlNr[fi], 1+fi); fflush(stdout);
272 }
273 tac[fi]/=(double)pxlNr[fi];
274 if(pxlNr[fi]<minNr) minNr=pxlNr[fi];
275 }
276
277 return(minNr);
278}

◆ integerScale()

void integerScale ( int frame,
float *** src,
float ** targ,
int width,
int height,
int zoom )
extern

Magnify one frame of dynamic 2D image by integer zoom factor. Pixel values are simply duplicated.

See also
imgScale
Parameters
frameIndex of the frame to be scaled.
srcSource data in dynamic 2D array: srcp[y][x][frame].
targPre-allocated target static 2D data matrix: targ[y][x]; actual matrix size is allowed to be larger than what is used here.
widthWidth (x dim) of the source data matrix.
heightHeight (y dim) of the source data matrix.
zoomZoom factor. If less than 2, then matrix is just copied.

Definition at line 159 of file imgtransform.c.

173 {
174 if(frame<0) frame=0;
175 if(zoom<1) zoom=1;
176
177 int w, h, z;
178
179 for(h=0; h<height; h++){
180 for(w=0; w<width; w++){
181 float val=src[h][w][frame];
182 for(z=0; z<zoom; z++) {
183 targ[h*zoom][w*zoom + z]=val;
184 }
185 }
186 /* Copy to next rows */
187 for(z=1; z<zoom; z++) {
188 for(int i=0; i<zoom*width; i++) targ[h*zoom+z][i]=targ[h*zoom+z-1][i];
189 //memcpy(targ[h*zoom+z], targ[h*zoom], width*zoom*sizeof(float));
190 }
191 }
192}

Referenced by imgScale().

◆ pRound()

int pRound ( float number)
extern

Round float to int.

Returns
Rounded value.
Parameters
numberAny number

Definition at line 15 of file point.c.

18 {
19 if(number - floor(number) < 0.5){
20 return floor(number);
21 }
22 return ceil(number);
23}

◆ tiffWriteImg()

int tiffWriteImg ( IMG * img,
int plane,
int frame,
float * maxvalue,
int colorscale,
char * fname,
int matXdim,
int matYdim,
int verbose,
char * status )
extern

Write one frame or plane in IMG data as a TIFF 6.0 format image. Overwrites existing TIFF file.

Returns
Returns 0, if ok.
See also
img2cube, imgFlipHorizontal, imgShrink, imgSwell, imgScale
Parameters
imgIMG containing PET image/sinogram data.
planematrix index of plane (0..dimz-1); all if <0.
framematrix index of frame (0..dimt-1); all if <0.
maxvaluecolours are scaled between 0 and maxvalue; if <=0, then searches max and sets maxvalue.
colorscalePET_GRAYSCALE, PET_GRAYSCALE_INV or PET_RAINBOW.
fnamename of output TIFF file.
matXdimNr of matrices tiled horizontally; enter 0 for automatic calculation.
matYdimNr of matrices tiled vertically; enter 0 for automatic calculation.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 15 of file imgtiff.c.

38 {
39 FILE *fp;
40 short int svar, svars[2048];
41 char buf[4096], *cdata, *cptr;
42 int ivar, ivars[1024];
43 /* Rainbow color scale */
44 struct { int n, r, g, b, dr, dg, db; }
45 bitty[] = { {32, 0, 0, 0, 2, 0, 4}, /* violet to indigo */
46 {32, 64, 0,128, -2, 0, 4}, /* indigo to blue */
47 {32, 0, 0,255, 0, 8, -8}, /* blue to green */
48 {64, 0,255, 0, 4, 0, 0}, /* green to yellow */
49 {32, 255,255, 0, 0, -2, 0}, /* yellow to orange */
50 {64, 255,192, 0, 0, -3, 0} }; /* orange to red */
51
52 if(verbose>0) printf("tiffWriteImg(*img, %d, %d, %g, %d, %s, status, %d)\n",
53 plane, frame, *maxvalue, colorscale, fname, verbose);
54
55 /* Check input data */
56 if(status!=NULL) strcpy(status, "fault in calling routine");
57 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
58 if(img->dimt<(frame+1) || img->dimz<(plane+1)) return(2);
59 int pxlNr=img->dimx*img->dimy; if(pxlNr<1) return(3);
60 if(status!=NULL) strcpy(status, "ok");
61
62 /* If color scale maximum was not specified, then determine it here */
63 if(*maxvalue<=0.0) {
64 *maxvalue=-1.0e-12;
65 for(int pi=0; pi<img->dimz; pi++) if(plane<0 || plane==pi)
66 for(int ri=0; ri<img->dimy; ri++) for(int ci=0; ci<img->dimx; ci++)
67 for(int fi=0; fi<img->dimt; fi++) if(frame<0 || frame==fi)
68 if(img->m[pi][ri][ci][fi]>*maxvalue)
69 *maxvalue=img->m[pi][ri][ci][fi];
70 if(*maxvalue<=0.0) {
71 if(status!=NULL) strcpy(status, "no positive pixel values");
72 return(6);
73 }
74 }
75
76 /* Calculate image dimensions */
77 /* image matrix number */
78 int matNr=0;
79 if(plane<0) matNr=img->dimz; else matNr=1;
80 if(frame<0) matNr*=img->dimt; else matNr*=1;
81 if(verbose>1) printf("matNr=%d\n", matNr);
82 /* image matrix x*y number */
83 if(matXdim<=0 && matYdim<=0) {
84 matXdim=(int)ceil(sqrt((double)matNr));
85 matYdim=matNr/matXdim; if(matNr%matXdim) matYdim++;
86 } else {
87 if(matXdim>matNr) {
88 matXdim=matNr; matYdim=1;
89 } else if(matYdim>matNr) {
90 matYdim=matNr; matXdim=1;
91 } else if(matXdim>0) {
92 matYdim=matNr/matXdim; if(matNr%matXdim) matYdim++;
93 } else {
94 matXdim=matNr/matYdim; if(matNr%matYdim) matXdim++;
95 }
96 }
97 if(verbose>1) printf("matXdim:=%d\nmatYdim:=%d\n", matXdim, matYdim);
98
99
100 /* Open TIFF file */
101 if((fp=fopen(fname, "wb")) == NULL) {
102 if(status!=NULL) strcpy(status, "cannot open file for write");
103 return(11);
104 }
105
106 /* Construct TIFF header */
107 memset(buf, 0, 4096);
108 /* set the byte format */
109 if(little_endian()) memcpy(buf, "II", 2); else memcpy(buf, "MM", 2);
110 /* set file identifier */
111 svar=42; memcpy(buf+2, &svar, 2);
112 /* set byte offset of first IFD */
113 ivar=8; memcpy(buf+4, &ivar, 4);
114 /* Construct the (first) Image File Directory (IFD) */
115 /* set nr of directory entries */
116 if(colorscale==PET_RAINBOW || colorscale==PET_RAINBOW_WB)
117 svar=12; else svar=11;
118 memcpy(buf+8, &svar, 2);
119 /* move into start of first entry */
120 cptr=buf+10;
121 /* tag: ImageWidth */
122 svars[0]=256; svars[1]=4; memcpy(cptr, svars, 4); cptr+=4;
123 ivars[0]=1; ivars[1]=matXdim*img->dimx; memcpy(cptr, ivars, 8); cptr+=8;
124 /* tag: ImageLength */
125 svars[0]=257; svars[1]=4; memcpy(cptr, svars, 4); cptr+=4;
126 ivars[0]=1; ivars[1]=matYdim*img->dimy; memcpy(cptr, ivars, 8); cptr+=8;
127 /* tag: BitsPerSample (xv3 on Sun/Solaris gives warning but works) */
128 svars[0]=258; svars[1]=3; memcpy(cptr, svars, 4); cptr+=4;
129 ivars[0]=1; memcpy(cptr, ivars, 4); cptr+=4;
130 svars[0]=(unsigned short int)8; memcpy(cptr, svars, 2); cptr+=4; /* 256 shades */
131 /* tag: Compression */
132 svars[0]=259; svars[1]=3; memcpy(cptr, svars, 4); cptr+=4;
133 ivars[0]=1; memcpy(cptr, ivars, 4); cptr+=4;
134 svars[0]=1; memcpy(cptr, svars, 2); cptr+=4; /* no compression */
135 /* tag: Photometric Interpretation */
136 svars[0]=262; svars[1]=3; memcpy(cptr, svars, 4); cptr+=4;
137 ivars[0]=1; memcpy(cptr, ivars, 4); cptr+=4;
138 if(colorscale==PET_RAINBOW || colorscale==PET_RAINBOW_WB)
139 svars[0]=3; /* palette */
140 else if(colorscale==PET_GRAYSCALE)
141 svars[0]=1; /* black is zero */
142 else
143 svars[0]=0; /* white is zero */
144 memcpy(cptr, svars, 2); cptr+=4;
145 /* tag: StripOffsets */
146 svars[0]=273; svars[1]=4; memcpy(cptr, svars, 4); cptr+=4;
147 /* byte offset of strip(s) of data */
148 ivars[0]=1; ivars[1]=4096; memcpy(cptr, ivars, 8); cptr+=8;
149 /* tag: RowsPerStrip */
150 svars[0]=278; svars[1]=4; memcpy(cptr, svars, 4); cptr+=4;
151 ivars[0]=1; ivars[1]=matYdim*img->dimy; memcpy(cptr, ivars, 8); cptr+=8;
152 /* tag: StripByteCounts */
153 svars[0]=279; svars[1]=4; memcpy(cptr, svars, 4); cptr+=4;
154 ivars[0]=1; ivars[1]=matXdim*matYdim*pxlNr; memcpy(cptr, ivars, 8); cptr+=8;
155 /* tag: XResolution */
156 ivars[0]=33; ivars[1]=1; ivars[2]=33; ivars[3]=1; memcpy(buf+1024, ivars, 16);
157 svars[0]=282; svars[1]=5; memcpy(cptr, svars, 4); cptr+=4;
158 ivars[0]=1; ivars[1]=1024; memcpy(cptr, ivars, 8); cptr+=8;
159 /* tag: YResolution */
160 svars[0]=283; svars[1]=5; memcpy(cptr, svars, 4); cptr+=4;
161 ivars[0]=1; ivars[1]=1032; memcpy(cptr, ivars, 8); cptr+=8;
162 /* tag: ResolutionUnit */
163 svars[0]=296; svars[1]=3; memcpy(cptr, svars, 4); cptr+=4;
164 ivars[0]=1; memcpy(cptr, ivars, 4); cptr+=4;
165 svars[0]=3; memcpy(cptr, svars, 2); cptr+=4; /* cm */
166 if(colorscale!=PET_RAINBOW && colorscale!=PET_RAINBOW_WB) {
167 /* offset of the next IFD, or 0000 */
168 for(int i=0; i<4; i++) *cptr++=(char)0;
169 } else {
170 int i, j;
171 /* tag: ColorMap */
172 svars[0]=320; svars[1]=3; memcpy(cptr, svars, 4); cptr+=4;
173 ivars[0]=3*256; memcpy(cptr, ivars, 4); cptr+=4;
174 //svars[0]=2048; memcpy(cptr, svars, 2); cptr+=4;
175 ivars[0]=2048; memcpy(cptr, ivars, 4); cptr+=4;
176 /* offset of the next IFD, or 0000 */
177 for(i=0; i<4; i++) *cptr++=(char)0;
178 /* Color table */
179 cptr=buf+2048;
180 /* red */
181 for(i=0, j=0; j<6; j++) {
182 svars[i++]=bitty[j].r;
183 for(int k=1; k<bitty[j].n; k++, i++) svars[i]=svars[i-1]+bitty[j].dr;
184 }
185 if(colorscale==PET_RAINBOW_WB) svars[0]=255;
186 memcpy(cptr, svars, 512); cptr+=512;
187 /* green */
188 for(i=0, j=0; j<6; j++) {
189 svars[i++]=bitty[j].g;
190 for(int k=1; k<bitty[j].n; k++, i++) svars[i]=svars[i-1]+bitty[j].dg;
191 }
192 if(colorscale==PET_RAINBOW_WB) svars[0]=255;
193 memcpy(cptr, svars, 512); cptr+=512;
194 /* blue */
195 for(i=0, j=0; j<6; j++) {
196 svars[i++]=bitty[j].b;
197 for(int k=1; k<bitty[j].n; k++, i++) svars[i]=svars[i-1]+bitty[j].db;
198 }
199 if(colorscale==PET_RAINBOW_WB) svars[0]=255;
200 memcpy(cptr, svars, 512); cptr+=512;
201 }
202
203 /* write the IFD */
204 if(fwrite(buf, 1, 4096, fp) != 4096) {
205 fclose(fp); remove(fname);
206 if(status!=NULL) strcpy(status, "cannot write file");
207 return(13);
208 }
209
210 /* Write pixel data */
211 cdata=(char*)calloc(matXdim*matYdim*pxlNr, sizeof(char));
212 if(cdata==NULL) {
213 fclose(fp); remove(fname);
214 if(status!=NULL) strcpy(status, "out of memory");
215 return(14);
216 }
217 cptr=cdata;
218 int mi=0; int mc=0; int mr=1;
219 for(int fi=0; fi<img->dimt; fi++) if(frame<0 || frame==fi) {
220 for(int pi=0; pi<img->dimz; pi++) if(plane<0 || plane==pi) {
221 mi++; mc++;
222 for(int ri=0; ri<img->dimy; ri++)
223 for(int ci=0; ci<img->dimx; ci++) {
224 cptr=cdata + (mr-1)*matXdim*pxlNr + ri*matXdim*img->dimx + (mc-1)*img->dimx + ci;
225 if(img->m[pi][ri][ci][fi]>0.0) {
226 if((img->m[pi][ri][ci][fi])<(*maxvalue))
227 *cptr=(unsigned char)(255.*(img->m[pi][ri][ci][fi])/(*maxvalue));
228 else *cptr=(unsigned char)255;
229 } else
230 *cptr=(unsigned char)0;
231 }
232 if(mc==matXdim) {mc=0; mr++;}
233 }
234 }
235 cptr=cdata;
236 if(fwrite(cptr, 1, matXdim*matYdim*pxlNr, fp) != (unsigned int)matXdim*matYdim*pxlNr) {
237 fclose(fp); remove(fname); free(cdata);
238 if(status!=NULL) strcpy(status, "cannot write file");
239 return(15);
240 }
241 free(cdata);
242
243 fclose(fp);
244 if(status!=NULL) strcpy(status, "ok");
245 return(0);
246}
#define PET_RAINBOW_WB
Definition libtpcimgp.h:38
#define PET_RAINBOW
Definition libtpcimgp.h:36
#define PET_GRAYSCALE
Definition libtpcimgp.h:32
int little_endian()
Definition swap.c:14