38 if(sinogram==NULL || rays<2 || views<2 || dim<2 || image==NULL)
return(1);
40 if(cutoff<0.05 || cutoff>0.99)
return(2);
45 int lenFFT=(2*rays)-1;
46 if(lenFFT<256) lenFFT=256;
else if(lenFFT<512) lenFFT=512;
47 else if(lenFFT<1024) lenFFT=1024;
else if(lenFFT<2048) lenFFT=2048;
48 else if(lenFFT<4096) lenFFT=4096;
else if(lenFFT<8192) lenFFT=8192;
49 else if(lenFFT<16384) lenFFT=16384;
else return(3);
52 for(i=0; i<dim*dim; i++) image[i]=0.0;
56 calloc((2*lenFFT + (lenFFT+1) + 5*lenFFT/4 + 3*views/2),
sizeof(
float));
57 if(locData==NULL)
return(4);
59 float *sinFFT, *cosFFT, *fbpFilter, *sinBP;
60 real=locData; imag=real+lenFFT;
61 fbpFilter=imag+lenFFT;
62 sinFFT=fbpFilter+(lenFFT+1);
63 cosFFT=sinFFT+lenFFT/4;
64 sinBP=sinFFT+5*lenFFT/4;
69 dg=(double)M_PI*2.0/(
double)lenFFT;
70 for(i=0, df=0.0; i<5*lenFFT/4; i++, df+=dg) sinFFT[i]=(
float)sin(df);
73 n=
fbpMakeFilter(sinFFT, cosFFT, cutoff, filter, lenFFT, views, fbpFilter, 0);
74 if(n) {free(locData);
return(100+n);}
79 for(
int pi=0; pi<views; pi+=2) {
81 for(i=0; i<rays; i++) real[i]=sinogram[pi*rays+i];
82 for(i=0; i<rays; i++) imag[i]=sinogram[pi*rays+rays+i];
83 for(i=rays; i<lenFFT; i++) real[i]=imag[i]=0.0;
87 for(i=0; i<lenFFT; i++) real[i]*=fbpFilter[i];
88 for(i=0; i<lenFFT; i++) imag[i]*=fbpFilter[i];
93 0.0, 0.0, 1.0, sinBP, sinBP);
95 0.0, 0.0, 1.0, sinBP, sinBP);
132 printf(
"imgFBP(scn, img, %d, %g, %d, %g, %g, %g, %g)\n",
133 imgDim, zoom, filter, cutoff, shiftX, shiftY, rotation);
135 int i, j, ret, plane, frame, fullBP;
137 float *sinB, *sinBrot, *sinFFT, *cosFFT;
138 float *oReal, *oImag, *real, *imag, *scnData, *imgData, *imgOrigin;
139 float *fbpFilter, bpZoom, bpZoomInv, *fptr, *gptr, *row1, *row2, f;
140 float offsX, offsY, pixSize;
145 if(imgDim<2 || imgDim>4096 || imgDim%2)
return(1);
146 if(zoom<0.01 || zoom>1000.)
return(1);
147 if(filter<0 || filter>6)
return(1);
148 if(cutoff<=0.0 || cutoff>=1.0)
return(1);
149 if(scn->
dimx<=1 || scn->
dimx>16384)
return(1);
154 if(verbose>1) {printf(
"allocating memory for the image\n"); fflush(stdout);}
160 if(verbose>1) {printf(
"setting image header\n"); fflush(stdout);}
162 img->
unit=CUNIT_COUNTS;
182 for(plane=0; plane<scn->
dimz; plane++)
187 for(frame=0; frame<scn->
dimt; frame++) {
189 img->
mid[frame]=0.5*(img->
start[frame]+img->
end[frame]);
197 if(verbose>1) {printf(
"allocating memory for matrices\n"); fflush(stdout);}
199 float *matData=calloc(i,
sizeof(
float));
204 scnData=matData; imgData=matData+(scn->
dimx*scn->
dimy);
207 lenFFT=(2*scn->
dimx)-1;
208 if(lenFFT<256) lenFFT=256;
else if(lenFFT<512) lenFFT=512;
209 else if(lenFFT<1024) lenFFT=1024;
else if(lenFFT<2048) lenFFT=2048;
210 else if(lenFFT<4096) lenFFT=4096;
else if(lenFFT<8192) lenFFT=8192;
211 else if(lenFFT<16384) lenFFT=16384;
else return(1);
213 printf(
"rays=%d views=%d lenFFT=%d\n", scn->
dimx, scn->
dimy, lenFFT);
216 i=3*scn->
dimy/2 + 3*scn->
dimy/2 + 5*lenFFT/4;
217 if(verbose>1) printf(
"allocating memory for pre-computed tables\n");
218 float *tabData=calloc(i,
sizeof(
float));
223 sinB=tabData; sinBrot=tabData+3*scn->
dimy/2;
224 sinFFT=sinBrot+3*scn->
dimy/2;
227 if(verbose>1) printf(
"computing sine tables for back-projection\n");
231 if(verbose>1) printf(
"computing sine and cosine tables for FFT\n");
234 dg=(double)M_PI*2.0/(
double)lenFFT;
235 for(i=0; i<5*lenFFT/4; i++, df+=dg) sinFFT[i]=(
float)sin(df);
236 cosFFT=sinFFT+lenFFT/4;
240 if(verbose>1) printf(
"allocating memory for reconstruction filters\n");
241 float *filData=calloc((5*lenFFT),
sizeof(
float));
243 imgEmpty(img); free(matData); free(tabData);
246 fbpFilter=filData; oReal=filData+lenFFT; oImag=oReal+2*lenFFT;
247 real=oReal+lenFFT/2; imag=oImag+lenFFT/2;
251 fbpFilter, verbose-1);
253 imgEmpty(img); free(matData); free(tabData); free(filData);
257 printf(
"\nfbpFilter:\n");
258 for(i=0; i<lenFFT; i++) {
259 printf(
"%g ", fbpFilter[i]);
260 if((i+1)%7==0 || i==lenFFT-1) printf(
"\n");}
265 bpZoom=zoom*(float)imgDim/(
float)scn->
dimx;
266 bpZoomInv=1.0/bpZoom;
267 if(verbose>2) printf(
"bpZoom=%g bpZoomInv=%g\n", bpZoom, bpZoomInv);
270 if(zoom>M_SQRT2) fullBP=1;
272 if(verbose>1) printf(
"fullBP := %d\n", fullBP);
275 if(verbose>1) printf(
"initialize variables for back-projection\n");
277 offsX=shiftX/pixSize; offsY=shiftY/pixSize;
278 for(i=0; i<3*(scn->
dimy)/2; i++) {
280 sinBrot[i]*=bpZoomInv;
282 imgOrigin=imgData+imgDim*(halfDim-1)+halfDim;
284 printf(
"halfDim=%d offsX=%g offsY=%g\n", halfDim, offsX, offsY);
290 if(verbose>1) printf(
"reconstruct one matrix at a time...\n");
291 for(plane=0; plane<scn->
dimz; plane++)
292 for(frame=0; frame<scn->
dimt; frame++) {
295 printf(
"reconstructing plane %d frame %d\n",
301 for(i=0, fptr=scnData; i<scn->
dimy; i++)
302 for(j=0; j<scn->
dimx; j++)
303 *fptr++=scn->
m[plane][i][j][frame];
305 printf(
"scn->m[%d][158][116][%d]=%e\n",
306 plane, frame, scn->
m[plane][64][56][frame]);
309 for(i=0, fptr=imgData; i<imgDim*imgDim; i++) *fptr++=0.0;
312 for(
int view=0; view<scn->
dimy; view+=2) {
315 for(j=0; j<2*lenFFT; j++) oReal[j]=0.0;
316 for(j=0; j<2*lenFFT; j++) oImag[j]=0.0;
317 row1=scnData+view*scn->
dimx;
319 fptr=real; gptr=imag;
320 for(j=0; j<scn->
dimx; j++) {
326 fptr=real; gptr=imag;
330 for(j=0, fptr=fbpFilter; j<lenFFT; j++) {
336 fptr=real; gptr=imag;
338 fptr=real; gptr=imag;
341 offsX, offsY, sinB, sinBrot);
343 offsX, offsY, sinB, sinBrot);
346 scn->
dimy, scn->
dimx, offsX, offsY, bpZoom, sinB, sinBrot);
348 scn->
dimy, scn->
dimx, offsX, offsY, bpZoom, sinB, sinBrot);
355 f=img->
end[frame]-img->
start[frame];
358 for(i=0, fptr=imgData; i<img->
dimy; i++)
359 for(j=0; j<img->
dimx; j++)
360 img->
m[plane][i][j][frame] = (*fptr++)*f;
362 printf(
"img->m[%d][64][56][%d]=%e\n",
363 plane, frame, img->
m[plane][64][56][frame]);
368 free(matData); free(tabData); free(filData);
370 if(verbose>1) printf(
"imgFBP() done.\n");
401 printf(
"fbpMakeFilter(..., %g, %d, %d, %d, ...)\n",
402 cutoff, filter, lenFFT, views);
403 if(sinFFT==NULL || cosFFT==NULL || fbpFilter==NULL)
return(1);
407 float invNr, bp_ifft_scale, rampDC, rampSlope;
410 if(lenFFT<2 || views<2)
return(1);
419 float *locData=calloc(lenFFT,
sizeof(
float));
420 if(locData==NULL)
return(2);
423 invNr=1.0/(float)lenFFT;
424 bp_ifft_scale=M_PI/(float)(views*lenFFT);
425 if(verbose>1) printf(
"invNr=%g bp_ifft_scale=%g\n", invNr, bp_ifft_scale);
428 for(i=1; i<=lenFFT/2; i++)
429 ramp[i]=ramp[lenFFT-i]=(
float)i*invNr;
431 rampSlope=ramp[lenFFT/2]-rampDC;
432 if(verbose>1) printf(
"rampDC=%g rampSlope=%g\n", rampDC, rampSlope);
435 istop=(int)(cutoff*(
float)lenFFT+0.5);
436 if(istop>lenFFT/2) istop=lenFFT/2;
439 case FBP_FILTER_RAMP:
440 fbpFilter[0]=ramp[0]*bp_ifft_scale;
441 for(i=1; i<=istop; i++)
442 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*bp_ifft_scale;
443 for(; i<=lenFFT/2; i++)
444 fbpFilter[i]=fbpFilter[lenFFT-i]=0.0;
446 case FBP_FILTER_HANN:
447 fbpFilter[0]=ramp[0]*bp_ifft_scale;
448 for(i=1; i<=istop; i++) {
449 f=0.5+0.5*cosf(M_PI*invNr*(
float)i/cutoff);
450 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*f*bp_ifft_scale;
452 for(; i<=lenFFT/2; i++) fbpFilter[i]=fbpFilter[lenFFT-i]=0.0;
454 case FBP_FILTER_HAMM:
455 fbpFilter[0]=ramp[0];
456 for(i=1; i<=istop; i++) {
457 f=0.54+0.46*cosf(M_PI*invNr*(
float)i/cutoff);
458 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*f*bp_ifft_scale;
460 for(; i<=lenFFT/2; i++) fbpFilter[i]=fbpFilter[lenFFT-i]=0.0;
462 case FBP_FILTER_PARZEN:
463 fbpFilter[0]=ramp[0];
464 for(i=1; i<=istop/2; i++) {
465 f=(float)i/(
float)istop; f=1.0-6.0*f*f*(1.0-f);
466 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*f*bp_ifft_scale;
468 for(; i<=istop; i++) {
469 f=1.0-(float)i/(
float)istop; f=2.0*f*f*f;
470 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*f*bp_ifft_scale;
472 for(; i<=lenFFT/2; i++) fbpFilter[i]=fbpFilter[lenFFT-i]=0.0;
474 case FBP_FILTER_SHEPP:
475 fbpFilter[0]=ramp[0];
476 for(i=1; i<=istop; i++) {
477 f=0.5*(float)i/(
float)istop; f=sinf(f*M_PI)/(f*M_PI);
478 fbpFilter[i]=fbpFilter[lenFFT-i]=ramp[i]*f*bp_ifft_scale;
480 for(; i<=lenFFT/2; i++) fbpFilter[i]=fbpFilter[lenFFT-i]=0.0;
482 case FBP_FILTER_BUTTER:
483 fprintf(stderr,
"Warning: Butter filter not implemented, using None.\n");
486 case FBP_FILTER_NONE:
487 for(i=0; i<lenFFT; i++) fbpFilter[i]=bp_ifft_scale;
491 fprintf(stderr,
"Error: invalid filter requested.\n");
526 int i, j, m, halfn, mmax, istep, ind;
527 float c, s, treal, timag;
533 for(i=j=1; i<=n; i++) {
535 treal=real[j-1]; timag=imag[j-1];
536 real[j-1]=real[i-1]; imag[j-1]=imag[i-1];
537 real[i-1]=treal; imag[i-1]=timag;
540 while(j>m) {j-=m; m++; m/=2;}
547 for(m=1; m<=mmax; m++) {
548 ind=(int)((
float)(halfn*(m-1))/(
float)mmax);
549 c=cosine[ind]; s=(direct>=0)?sine[ind]:-sine[ind];
550 for(i=m; i<=n; i+=istep) {
552 treal=real[j-1]*c - imag[j-1]*s;
553 timag=imag[j-1]*c + real[j-1]*s;
554 real[j-1]=real[i-1]-treal;
555 imag[j-1]=imag[i-1]-timag;
564 for(i=j=0; i<n; i++) {
566 treal=real[j]; timag=imag[j];
567 real[j]=real[i]; imag[j]=imag[i];
568 real[i]=treal; imag[i]=timag;
571 while(j>=m) {j-=m; m++; m/=2;}
578 for(m=0; m<mmax; m++) {
579 ind=(int)((
float)(halfn*m)/(
float)mmax);
580 c=cosine[ind]; s=(direct>=0)?sine[ind]:-sine[ind];
581 for(i=m; i<n; i+=istep) {
583 treal=real[j]*c - imag[j]*s;
584 timag=imag[j]*c + real[j]*s;
585 real[j]=real[i]-treal;
586 imag[j]=imag[i]-timag;
621 float si, co, tleft, sir, cor, rayCenter, dif;
623 int x, y, halfDim, leftX, rightTopLimit, yBottom, ti;
625 float *imgp=imgCorner;
629 rightTopLimit=halfDim-1;
631 rayCenter=0.5*(float)rays;
633 co=sinB[view+views/2];
635 cor=sinBrot[view+views/2];
636 x=leftX; y=rightTopLimit;
637 tleft= rayCenter - (float)y*sir - offsY*si + ((
float)(x+1))*cor + offsX*co;
638 for(; y>=yBottom; y--) {
640 for(x=leftX; x<=rightTopLimit; x++, t+=cor) {
641 ti=(int)t; dif=t-(float)ti;
643 *imgp++ += prj[ti] + (prj[ti+1]-prj[ti])*dif;
679 if(0) printf(
"fbp_back_proj_round(..., %d, %d, %d, %d, %g, %g, %g, ...)\n",
680 imgDim, view, views, rays, offsX, offsY, bpZoom);
682 float *imgp, si, co, sir, cor, toffs, rayCenter, tPow2, yph, dif;
684 int x, y, halfDim, right_top_limit, xrightround, ybottomround, ti;
688 co=sinB[views/2+view]*offsX;
691 cor=sinBrot[views/2+view];
694 rayCenter=0.5*(float)rays;
695 if((
float)y>(rayCenter*bpZoom)) {
696 y=(int)(rayCenter*bpZoom);
699 ybottomround=-halfDim+1;
701 toffs=rayCenter-si+co;
702 tPow2=rayCenter*rayCenter*bpZoom*bpZoom;
703 right_top_limit=halfDim-1;
704 for(; y>=ybottomround; y--) {
706 xrightround=(int)sqrt(tPow2 - yph*yph) + 1;
707 if(xrightround>=halfDim) {
708 xrightround=right_top_limit;
713 t=toffs-(float)y*sir+((
float)(x+1))*cor;
714 imgp=imgOrigin-y*imgDim+x;
715 for(; x<=xrightround; x++, t+=cor) {
716 ti=(int)t; dif=t-(float)ti;
717 *imgp++ += prj[ti] + (prj[ti+1] - prj[ti])*dif;