/*------------------------------------------------------------------- * CTSliceSetVal - set a value in a CT image *------------------------------------------------------------------- */ void CTSliceSetVal(CTSlice slice, int x, int y, float val) { if (CTSliceShorts(slice)) CTSliceShortData(slice, x, y) = (unsigned short) val; else if (CTSliceChars(slice)) CTSliceCharData(slice, x, y) = (unsigned char) val; else if (CTSliceFloats(slice)) CTSliceFloatData(slice, x, y) = val; }
/*------------------------------------------------------------------- * CTWritePGM - write a slice in portable greymap format *------------------------------------------------------------------- */ static int CTWritePGM(char *path, CTSlice slice) { FILE *fp; int i, j; // int c, width, height, max; // unsigned char *line; if ((fp=fopen(path, "w")) == NULL) return(0); if (CTSliceMaxD(slice) <= 255) { fprintf(fp, "P5\n%d %d\n%d\n", CTSliceXSize(slice), CTSliceYSize(slice), CTSliceMaxD(slice)); if (CTSliceChars(slice)) { for (i=CTSliceYSize(slice)-1; i>=0; i--) { for (j=0; j<CTSliceXSize(slice); j++) fputc(CTSliceCharData(slice, j, i), fp); } } else if (CTSliceShorts(slice)) { for (i=CTSliceYSize(slice)-1; i>=0; i--) { for (j=0; j<CTSliceXSize(slice); j++) fputc(CTSliceShortData(slice, j, i), fp); } } } else { fprintf(fp, "P2\n%d %d\n%d\n", CTSliceXSize(slice), CTSliceYSize(slice), CTSliceMaxD(slice)); for (i=CTSliceYSize(slice)-1; i>=0; i--) { for (j=0; j<CTSliceXSize(slice); j++) fputc(CTSliceShortData(slice, j, i), fp); } } fclose(fp); return(1); }
CTVolume CTVolumeHartley3D(CTVolume vol) { CTVolume vol2; CTSlice slice; int l,m,n,L,M,N,i,j,k; #ifdef USE_PTIME int t1,t2; #endif float *d1,*d2,*X,*D,Z,*w,*w1,*w2; float *Mcas, *Lcos, *Lsin, *Ncos, *Nsin, max, min; double dL, dM, dN, s, c; /* Get source volume info. */ L = CTVolXSize(vol); M = CTVolYSize(vol); N = CTVolNumSlices(vol); dL = (double)L; dM = (double)M; dN = (double)N; /* Initialize the new volume. */ vol2 = CTVolumeCreate(CTH3D,CTVolPrefix(vol),".h3d",CTVolXSize(vol), CTVolYSize(vol),CTVolZSize(vol),CTVolXSep(vol), CTVolYSep(vol),CTVolZSep(vol),CTVolFirstSlice(vol), CTVolLastSlice(vol),1.0e10,CT_MSBF,CT_FLOAT); /* Open the new volume for writing. */ CTVolumeOpen(vol2,CTH3D,CTVolPrefix(vol2),".h3d"); /* Read in the volume data. */ D = (float *)malloc(L*M*N*sizeof(float)); switch (CTVolVoxelBits(vol)) { /* Read in and convert CT_8BIT values to CT_FLOAT. */ case CT_8BIT: for (n=0;n<N;n++) { slice = CTSliceRead(vol,n+CTVolFirstSlice(vol),-1,-1,-1,-1); for (l=0;l<L;l++) { for (m=0;m<M;m++) { D[n+N*(l+L*m)] = (float)CTSliceCharData(slice,l,m); } } CTSliceFree(slice); } break; /* Read in and convert CT_16BIT values to CT_FLOAT. */ case CT_16BIT: for (n=0;n<N;n++) { slice = CTSliceRead(vol,n+CTVolFirstSlice(vol),-1,-1,-1,-1); for (l=0;l<L;l++) { for (m=0;m<M;m++) { D[n+N*(l+L*m)] = (float)CTSliceShortData(slice,l,m); } } CTSliceFree(slice); } break; /* Read in CT_FLOAT values. */ case CT_FLOAT: for (n=0;n<N;n++) { slice = CTSliceRead(vol,n+CTVolFirstSlice(vol),-1,-1,-1,-1); for (l=0;l<L;l++) { for (m=0;m<M;m++) { D[n+N*(l+L*m)] = CTSliceFloatData(slice,l,m); } } CTSliceFree(slice); } break; } /* Precompute necessary sin, cos, and cas function values. */ Lcos = (float *)malloc(sizeof(float)*L*L); Lsin = (float *)malloc(sizeof(float)*L*L); Ncos = (float *)malloc(sizeof(float)*N*N); Nsin = (float *)malloc(sizeof(float)*N*N); Mcas = (float *)malloc(sizeof(float)*M*M); for (i=0;i<L*L;i++) { s = sin(2.0*M_PI*(double)i/dL); c = cos(2.0*M_PI*(double)i/dL); Lcos[i] = (float)c; Lsin[i] = (float)s; } for (i=0;i<N*N;i++) { s = sin(2.0*M_PI*(double)i/dN); c = cos(2.0*M_PI*(double)i/dN); Ncos[i] = (float)c; Nsin[i] = (float)s; } for (i=0;i<M*M;i++) { s = sin(2.0*M_PI*(double)i/dM); c = cos(2.0*M_PI*(double)i/dM); Mcas[i] = (float)(s+c); } /* Algorithm is O(LLMN+LMMN+LMNN). */ X = (float *)malloc(L*M*sizeof(float)); w1 = (float *)malloc(L*M*sizeof(float)); w2 = (float *)malloc(M*sizeof(float)); #ifdef USE_PTIME t1 = t2 = time(NULL); #endif /* Transfrom the original volume and write the new volume one slice at a time, in order. */ for (k=0;k<N;k++) { /* Initialize max and min values for each slice. */ min = 1.0e10; max = -1.0e10; /* Compute w1(i,m,n) */ d1 = D; w = w1; for (m=0;m<M;m++) { for (l=0;l<L;l++) { d2 = &D[N*((L-l)%L+L*((M-m)%M))]; *w = 0.0; for (n=0;n<N;n++) { *w += (*d1++)*Ncos[k*n]+(*d2++)*Nsin[k*n]; } w++; } } /* Compute w2(i,j,n) */ for (i=0;i<L;i++) { w = w2; d1 = w1; for (m=0;m<M;m++) { *w = 0.0; d2 = &w1[L*((M-m)%M)]; for (l=0;l<L;l++) { *w += (*d1++)*Lcos[i*l]+(*d2++)*Lsin[i*l]; } w++; } /* Compute X(i,j,k) */ for (j=0;j<M;j++) { Z = 0.0; w = w2; for (m=0;m<M;m++) { Z += (*w++)*Mcas[j*m]; } if (Z>max) max = Z; if (Z<min) min = Z; X[i+L*j] = Z; } } /* Write the transformed slice. */ slice = CTSliceCreate(L,M,min,max,vol2,k); for (i=0;i<L;i++) { for (j=0;j<M;j++) { CTSliceSetVal(slice,i,j,X[i+L*j]); } } CTSliceWrite(NULL,slice); CTSliceFree(slice); #ifdef USE_PTIME printf("Slice %d/%d, ",k+1,N); ptime((int)((float)(time(NULL)-t1)/(float)(k+1)*(float)(N-k-1))); printf("\n"); #endif } /* Done writing to the new volume. */ CTVolumeClose(vol2); #ifdef USE_PTIME t2 = time(NULL); printf("(3D)Total time: "); ptime(t2-t1); printf("\n"); #endif /* Return the transformed volume. */ return(vol2); }
/*------------------------------------------------------------------------ * CTSliceCompMinMaxD - compute min and max densities for a slice *------------------------------------------------------------------------ */ void CTSliceCompMinMaxD(CTSlice slice) { double val; int i, j; unsigned long nnonzero; CTSliceMaxD(slice) = -1e100; CTSliceMinD(slice) = 1e100; nnonzero=0; if (CTSliceShorts(slice)) { for (i=CTSliceMinX(slice); i<=CTSliceMaxX(slice); i++) { for (j=CTSliceMinY(slice); j<=CTSliceMaxY(slice); j++) { if ((val=CTSliceShortData(slice, i, j)) > CTVolNoise(slice->vol)) continue; if (val > CTSliceMaxD(slice)) CTSliceMaxD(slice) = val; if (val < CTSliceMinD(slice)) CTSliceMinD(slice) = val; if (val != 0) nnonzero++; } } } else if (CTSliceChars(slice)) { for (i=CTSliceMinX(slice); i<=CTSliceMaxX(slice); i++) { for (j=CTSliceMinY(slice); j<=CTSliceMaxY(slice); j++) { if ((val=CTSliceCharData(slice, i, j)) > CTVolNoise(slice->vol)) continue; if (val > CTSliceMaxD(slice)) CTSliceMaxD(slice) = val; if (val < CTSliceMinD(slice)) CTSliceMinD(slice) = val; if (val != 0) nnonzero++; } } } else if (CTSliceFloats(slice)) { for (i=CTSliceMinX(slice); i<=CTSliceMaxX(slice); i++) { for (j=CTSliceMinY(slice); j<=CTSliceMaxY(slice); j++) { if ((val=CTSliceFloatData(slice, i, j)) > CTVolNoise(slice->vol)) continue; if (val > CTSliceMaxD(slice)) CTSliceMaxD(slice) = val; if (val < CTSliceMinD(slice)) CTSliceMinD(slice) = val; if (val != 0) nnonzero++; } } } CTSliceRatio(slice) = nnonzero/ (double)(CTSliceWidth(slice)*CTSliceHeight(slice)); }
/*------------------------------------------------------------------- * CTReadPGM - read a slice from a portable greymap file *------------------------------------------------------------------- */ static int CTReadPGM(FILE *fp, CTSlice slice, int x1, int y1, int x2, int y2) { int c, i, j, width, height, max; unsigned char *line; char buf[1024]; /* read for the magic number, skipping comments */ while ((c=fgetc(fp)) == '#') fgets(buf, 1024, fp); ungetc(c, fp); if (fscanf(fp, "P%d\n", &c) != 1) return(-1); if (c != 2 && c != 5) { /* file is not PGM, fail */ return(-1); } if (c==2) { while ((c=fgetc(fp)) == '#') fgets(buf, 1024, fp); ungetc(c, fp); if (fscanf(fp, "%d%d%d", &width, &height, &max) != 3) return(-1); if (x1==-1) { slice->x1=slice->y1=x1=y1=0; slice->x2=x2=width-1; slice->y2=y2=height-1; slice->data = (unsigned short *)malloc(sizeof(unsigned short)* (x2-x1+1)*(y2-y1+1)); memset(slice->data, 0, sizeof(short)*(x2-x1+1)*(y2-y1+1)); CTSliceWidth(slice) = width; CTSliceHeight(slice) = height; } /* eat extra character */ getc(fp); for (i=height-1; i>=0; i--) { for (j=0; j<width; j++) { int val; fscanf(fp, "%d", &val); CTSliceShortData(slice, j, i) = val; } } CTSliceCompMinMaxD(slice); return(0); } else if (c==5) { while ((c=fgetc(fp)) == '#') fgets(buf, 1024, fp); ungetc(c, fp); if (fscanf(fp, "%d%d%d", &width, &height, &max) != 3) { printf("failed to read width/height/max\n"); return(-1); } if (x1==-1) { slice->x1=slice->y1=x1=y1=0; slice->x2=x2=width-1; slice->y2=y2=height-1; slice->cdata = (unsigned char *)malloc(sizeof(unsigned char)* (x2-x1+1)*(y2-y1+1)); memset(slice->cdata, '\0', sizeof(char)*(x2-x1+1)*(y2-y1+1)); CTSliceWidth(slice) = width; CTSliceHeight(slice) = height; } /* eat extra character */ getc(fp); line = (unsigned char *)malloc(sizeof(char)*width); for (i=height-1; i>=0; i--) { fread(line, 1, width, fp); if (y1 <= i && i <= y2) { for (j=0; j<width; j++) { if (x1 <= j && j <= x2) CTSliceCharData(slice, j, i) = line[j]; } } } free(line); CTSliceCompMinMaxD(slice); return(0); } return(1); }
/*------------------------------------------------------------------- * CTReadRAS - read a slice from a sun raster file *------------------------------------------------------------------- */ static int CTReadRAS(FILE *fp, CTSlice slice, int x1, int y1, int x2, int y2) { int linesize,lsize,csize,isize,flipit,i,j,w,h,d,rv; unsigned char *line, r[256], g[256], b[256]; struct rasterfile sunheader; rv = 0; /* read in the Sun Rasterfile picture */ flipit = 0; fread(&sunheader, sizeof(struct rasterfile), 1, fp); if (sunheader.ras_magic != RAS_MAGIC) { flipl( (unsigned char *) &sunheader.ras_magic); if (sunheader.ras_magic == RAS_MAGIC) flipit = 1; else flipl( (unsigned char *) &sunheader.ras_magic); } if (sunheader.ras_magic != RAS_MAGIC) return( SunRasError("not a Sun rasterfile") ); if (flipit) { flipl((unsigned char *) &sunheader.ras_width); flipl((unsigned char *) &sunheader.ras_height); flipl((unsigned char *) &sunheader.ras_depth); flipl((unsigned char *) &sunheader.ras_length); flipl((unsigned char *) &sunheader.ras_type); flipl((unsigned char *) &sunheader.ras_maptype); flipl((unsigned char *) &sunheader.ras_maplength); } /* make sure that the input picture can be dealt with */ if (sunheader.ras_depth != 8) { fprintf (stderr, "Sun rasterfile image has depth %d\n", sunheader.ras_depth); fprintf (stderr, "Depths supported are 8\n"); return 1; } if (sunheader.ras_type != RT_OLD && sunheader.ras_type != RT_STANDARD && sunheader.ras_type != RT_BYTE_ENCODED && sunheader.ras_type != RT_FORMAT_RGB) { fprintf (stderr, "Sun rasterfile of unsupported type %d\n", sunheader.ras_type); return 1; } if (sunheader.ras_maptype != RMT_RAW && sunheader.ras_maptype != RMT_NONE && sunheader.ras_maptype != RMT_EQUAL_RGB) { fprintf (stderr, "Sun rasterfile colormap of unsupported type %d\n", sunheader.ras_maptype); return 1; } w = sunheader.ras_width; h = sunheader.ras_height; d = sunheader.ras_depth; isize = sunheader.ras_length ? sunheader.ras_length : (w * h * d) / 8; csize = (sunheader.ras_maptype == RMT_NONE) ? 0 : sunheader.ras_maplength; lsize = w * h * ( d == 1 ? d : d/8); linesize = w * d; /* if ((linesize % 48) && d == 24) linesize += (48 - (linesize % 48)); */ if (linesize % 16) linesize += (16 - (linesize % 16)); linesize /= 8; #ifdef DEBUG fprintf(stderr,"%s: LoadSunRas() - loading a %dx%d pic, %d planes\n", cmd, w, h, d); fprintf(stderr, "type %d, maptype %d, isize %d, csize %d, lsize %d, linesize %d\n", sunheader.ras_type, sunheader.ras_maptype, isize, csize, lsize, linesize); #endif /* read in the colormap, if any */ if (sunheader.ras_maptype == RMT_EQUAL_RGB && csize) { fread (r, sizeof(unsigned char), sunheader.ras_maplength/3, fp); fread (g, sizeof(unsigned char), sunheader.ras_maplength/3, fp); fread (b, sizeof(unsigned char), sunheader.ras_maplength/3, fp); } else if (sunheader.ras_maptype == RMT_RAW && csize) { /* we don't know how to handle raw colormap, ignore */ fskip(fp, csize); } else { /* no colormap, make one up */ if (sunheader.ras_depth == 1) { r[0] = g[0] = b[0] = 0; r[1] = g[1] = b[1] = 255; } else if (sunheader.ras_depth == 8) { for (i = 0; i < 256; i++) r[i] = g[i] = b[i] = i; } } /* CTSliceXSize(slice) = w; CTSliceYSize(slice) = h; */ if (x1==-1) { slice->x1=slice->y1=x1=y1=0; slice->x2=x2=w-1; slice->y2=y2=h-1; slice->cdata = (unsigned char *)malloc(sizeof(unsigned char)*(x2-x1+1)* (y2-y1+1)); memset(slice->cdata, '\0', sizeof(char)*(x2-x1+1)*(y2-y1+1)); CTSliceWidth(slice) = w; CTSliceHeight(slice) = h; } /* allocate memory for picture and read it in */ /* note we may slightly overallocate here (if image is padded) */ line = (unsigned char *) malloc (linesize); if (line == NULL) { fprintf(stderr, "Can't allocate memory for image\n"); exit(1); } for (i = 0; i < h; i++) { if (sunheader.ras_type == RT_BYTE_ENCODED) { if (rle_read (line, 1, linesize, fp, (i==0)) != linesize) break; } else { if (fread (line, 1, linesize, fp) != (unsigned int)linesize) return (SunRasError ("file read error")); } if (slice->y1 <= i && i <= slice->y2) { for (j=slice->x1; j<=slice->x2; j++) CTSliceCharData(slice, i, j) = line[j]; } /* switch (d) { case 1: SunRas1to8 (image + w * i, line, w); break; case 8: memcpy (image + w * i, line, w); break; case 24: memcpy (image + w * i * 3, line, w * 3); break; } */ } #ifdef DEBUG fprintf(stderr,"Sun ras: image loaded!\n"); #endif /* if (d == 24) { if (sunheader.ras_type != RT_FORMAT_RGB) fixBGR(image,w,h); rv = Conv24to8 (image, w, h, nc); free (image); return (rv); } else { pic = image; pWIDE = w; pHIGH = h; return (0); } */ CTSliceCompMinMaxD(slice); return(0); }
/*------------------------------------------------------------------- * CTSliceSetVals - set a block of values in a CT image *------------------------------------------------------------------- */ void CTSliceSetVals(CTSlice slice, int x1, int y1, int x2, int y2, int val, int z) { int x, y; if (x1 > x2) { x = x1; x1 = x2; x2 = x; } if (y1 > y2) { y = y1; y1 = y2; y2 = y; } x1 = MAX(x1, slice->x1); y1 = MAX(y1, slice->y1); x2 = MIN(x2, slice->x2); y2 = MIN(y2, slice->y2); if (z) { if (x1 <= x2) { /* set the first line */ if (CTSliceShorts(slice)) { for (y=y1; y<=y2; y++) CTSliceShortData(slice, x1, y) = val; for (x1++; x1<=x2; x1++) memcpy(&CTSliceShortData(slice, x1, y1),&CTSliceShortData(slice, x1-1, y1), sizeof(short)*(y2-y1+1)); } else { for (y=y1; y<=y2; y++) CTSliceCharData(slice, x1, y) = val; for (x1++; x1<=x2; x1++) memcpy(&CTSliceCharData(slice, x1, y1),&CTSliceCharData(slice, x1-1, y1), sizeof(char)*(y2-y1+1)); } } } else { if (CTSliceShorts(slice)) { for (x=x1; x<=x2; x++) { for (y=y1; y<=y2; y++) if (CTSliceShortData(slice, x, y) > 1000) CTSliceShortData(slice, x, y) = val; else CTSliceShortData(slice, x, y) = 0; } } else { for (x=x1; x<=x2; x++) { for (y=y1; y<=y2; y++) if (CTSliceCharData(slice, x, y) > 1000) CTSliceCharData(slice, x, y) = val; else CTSliceCharData(slice, x, y) = 0; } } } }