kopia lustrzana https://github.com/fellesverkstedet/fabmodules
266 wiersze
7.6 KiB
C
266 wiersze
7.6 KiB
C
//
|
|
// vol_gif.c
|
|
// .vol to .gif
|
|
//
|
|
// Neil Gershenfeld 11/29/13
|
|
// (c) Massachusetts Institute of Technology 2013
|
|
//
|
|
// This work may be reproduced, modified, distributed,
|
|
// performed, and displayed for any purpose, but must
|
|
// acknowledge the fab modules project. Copyright is
|
|
// retained and must be preserved. The work is provided
|
|
// as is; no warranty is provided, and users accept all
|
|
// liability.
|
|
//
|
|
|
|
/*
|
|
gcc -O3 vol_gif.c -o vol_gif -D_FILE_OFFSET_BITS=64 -Wall -lm -lgif
|
|
*/
|
|
|
|
#include "fab.h"
|
|
|
|
void read_voxel_f(FILE *input_file,float *f,int x,int y,int z,int *xi,int *yi,int *zi,int ix,int iy,int iz) {
|
|
int r,match=0;
|
|
while (1) {
|
|
if ((x == *xi) && (y == *yi) && (z == *zi)) {
|
|
match = 1;
|
|
}
|
|
r = fread(f,sizeof(*f),1,input_file);
|
|
if (r == 0) {
|
|
printf("vol_gif: oops -- not enough points in file\n");
|
|
exit(-1);
|
|
}
|
|
*xi += 1;
|
|
if (*xi == ix) {
|
|
*xi = 0;
|
|
*yi += 1;
|
|
if (*yi == iy) {
|
|
*yi = 0;
|
|
*zi += 1;
|
|
}
|
|
}
|
|
if (match == 1)
|
|
return;
|
|
}
|
|
}
|
|
|
|
void read_voxel_i(FILE *input_file,uint16_t *i,int x,int y,int z,int *xi,int *yi,int *zi,int ix,int iy,int iz) {
|
|
int r,match=0;
|
|
while (1) {
|
|
if ((x == *xi) && (y == *yi) && (z == *zi)) {
|
|
match = 1;
|
|
}
|
|
r = fread(i,sizeof(*i),1,input_file);
|
|
if (r == 0) {
|
|
printf("vol_gif: oops -- not enough points in file\n");
|
|
exit(-1);
|
|
}
|
|
*xi += 1;
|
|
if (*xi == ix) {
|
|
*xi = 0;
|
|
*yi += 1;
|
|
if (*yi == iy) {
|
|
*yi = 0;
|
|
*zi += 1;
|
|
}
|
|
}
|
|
if (match == 1)
|
|
return;
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
FILE *input_file;
|
|
float arg,size,rx,ry,rz;
|
|
float f,fmin=1e10,fmax=-1e10;
|
|
uint16_t i;
|
|
uint64_t count;
|
|
int xi,yi,zi,xo,yo,zo,nx,ny,nz,dx,dy,dz,x0,y0,z0,h;
|
|
int **image;
|
|
char format,type,comment[256];
|
|
GifFileType *GIFfile;
|
|
ColorMapObject *GIFcmap;
|
|
GifPixelType *GIFline;
|
|
//
|
|
// command line args
|
|
//
|
|
if (!((argc == 6) || (argc == 7) || (argc == 8) || (argc == 9) || (argc == 10) || (argc == 13) || (argc == 16) || (argc == 19))) {
|
|
printf("command line: vol_gif in.vol out.gif nx ny nz [format [type [arg [size [dx dy dz [x0 y0 z0 [rx ry rz]]]]]]]\n");
|
|
printf(" in.vol = input volume file\n");
|
|
printf(" out.gif = output GIF file\n");
|
|
printf(" nx,ny,nz = x,y,z input voxel number\n");
|
|
printf(" format = 'f' for float 32, 'i' for uint16_t (default 'f')\n");
|
|
printf(" type = 's' for section, 'h' for height (default 's')\n");
|
|
printf(" arg = gamma for 's', threshold for 'h' (default 1)\n");
|
|
printf(" size = mm per voxel (default 1)\n");
|
|
printf(" dx,dy,dz = x,y,z output voxel number (default all)\n");
|
|
printf(" x0,y0,z0 = x,y,z output voxel origin (default 0)\n");
|
|
printf(" to be implemented: rx,ry,rz = view rotation angles (degrees; default 0)\n");
|
|
exit(-1);
|
|
}
|
|
format = 'f';
|
|
type = 's';
|
|
arg = 1;
|
|
size = 1.0;
|
|
rx = ry = rz = 0;
|
|
sscanf(argv[3],"%d",&nx);
|
|
sscanf(argv[4],"%d",&ny);
|
|
sscanf(argv[5],"%d",&nz);
|
|
dx = nx; dy = ny; dz = nz;
|
|
x0 = y0 = z0 = 0;
|
|
if (argc >= 7) {
|
|
sscanf(argv[6],"%c",&format);
|
|
if (!((format == 'f') || (format == 'i'))) {
|
|
printf("vol_gif: oops -- format must be 'f' or 'i'\n");
|
|
exit(-1);
|
|
}
|
|
}
|
|
if (argc >= 8) {
|
|
sscanf(argv[7],"%c",&type);
|
|
if (!((type == 's') || (type == 'h'))) {
|
|
printf("vol_gif: oops -- type must be 's' or 'h'\n");
|
|
exit(-1);
|
|
}
|
|
}
|
|
if (argc >= 9) {
|
|
sscanf(argv[8],"%f",&arg);
|
|
}
|
|
if (argc >= 10) {
|
|
sscanf(argv[9],"%f",&size);
|
|
}
|
|
if (argc >= 13) {
|
|
sscanf(argv[10],"%d",&x0);
|
|
sscanf(argv[11],"%d",&y0);
|
|
sscanf(argv[12],"%d",&z0);
|
|
}
|
|
if (argc >= 16) {
|
|
sscanf(argv[13],"%d",&dx);
|
|
sscanf(argv[14],"%d",&dy);
|
|
sscanf(argv[15],"%d",&dz);
|
|
}
|
|
if (argc >= 19) {
|
|
sscanf(argv[16],"%f",&rx);
|
|
sscanf(argv[17],"%f",&ry);
|
|
sscanf(argv[18],"%f",&rz);
|
|
}
|
|
//
|
|
// check and find limits
|
|
//
|
|
input_file = fopen(argv[1],"rb");
|
|
if (input_file == NULL) {
|
|
printf("vol_gif: oops -- can not open %s\n",argv[1]);
|
|
exit(-1);
|
|
}
|
|
if (((x0 + dx) > nx) || ((y0 + dy) > ny) || ((z0 + dz) > nz)) {
|
|
printf("vol_gif: oops -- region too large\n");
|
|
exit(-1);
|
|
}
|
|
printf("read %s\n",argv[1]);
|
|
if (format == 'f') {
|
|
count = 0;
|
|
while (fread(&f,sizeof(f),1,input_file) != 0) {
|
|
if (f > fmax) fmax = f;
|
|
if (f < fmin) fmin = f;
|
|
count += 1;
|
|
}
|
|
}
|
|
else if (format == 'i') {
|
|
count = 0;
|
|
while (fread(&i,sizeof(i),1,input_file) != 0) {
|
|
if (i > fmax) fmax = i;
|
|
if (i < fmin) fmin = i;
|
|
count += 1;
|
|
}
|
|
}
|
|
printf(" %" PRIu64 " points, min %f, max %f\n",count,fmin,fmax);
|
|
printf(" nx ny nz: %d %d %d\n",nx,ny,nz);
|
|
rewind(input_file);
|
|
//
|
|
// set up color map
|
|
//
|
|
GIFcmap = MakeMapObject(256, NULL);
|
|
for (i = 0; i < 256; i++) {
|
|
GIFcmap->Colors[i].Red = i;
|
|
GIFcmap->Colors[i].Green = i;
|
|
GIFcmap->Colors[i].Blue = i;
|
|
}
|
|
//
|
|
// open GIF file
|
|
//
|
|
printf("write %s\n",argv[2]);
|
|
GIFfile = EGifOpenFileName(argv[2], 0);
|
|
EGifPutScreenDesc(GIFfile,dx,dy,8,0,GIFcmap);
|
|
unsigned char loop_count[] = {1,0,0};
|
|
EGifPutExtensionFirst(GIFfile, APPLICATION_EXT_FUNC_CODE, 11, "NETSCAPE2.0");
|
|
EGifPutExtensionLast(GIFfile, APPLICATION_EXT_FUNC_CODE, 3, loop_count);
|
|
unsigned char delay_count[5] = {
|
|
0, // no transparency
|
|
0, // delay time
|
|
0, // delay time
|
|
0 // transparent index not used
|
|
};
|
|
//
|
|
// allocate image
|
|
//
|
|
image = malloc(dy*sizeof(int *));
|
|
for (yo = 0; yo < dy; ++yo) {
|
|
image[yo] = malloc(dx*sizeof(int));
|
|
for (xo = 0; xo < dx; ++xo)
|
|
image[yo][xo] = 0;
|
|
}
|
|
GIFline = malloc(dx*sizeof(GifPixelType));
|
|
//
|
|
// scan file
|
|
//
|
|
xi = yi = zi = 0;
|
|
for (zo = 0; zo < dz; ++zo) {
|
|
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b layer = %d",zo);
|
|
EGifPutExtension(GIFfile,GRAPHICS_EXT_FUNC_CODE,4,delay_count);
|
|
EGifPutImageDesc(GIFfile,0,0,dx,dy,0,NULL);
|
|
//
|
|
// read layer
|
|
//
|
|
for (yo = 0; yo < dy; ++yo) {
|
|
for (xo = 0; xo < dx; ++xo) {
|
|
if (format == 'f') {
|
|
read_voxel_f(input_file,&f,xo+x0,yo+y0,zo+z0,&xi,&yi,&zi,nx,ny,nz);
|
|
if (type == 'h') {
|
|
h = 255*zo/(nz-1.0);
|
|
if ((h > image[yo][xo]) && (f > arg))
|
|
image[yo][xo] = h;
|
|
GIFline[xo] = image[yo][xo]*(nz-1.0)/zo;
|
|
}
|
|
else if (type == 's') {
|
|
GIFline[xo] = 255*pow((f-fmin)/(fmax-fmin),arg);
|
|
}
|
|
}
|
|
else if (format == 'i') {
|
|
read_voxel_i(input_file,&i,xo+x0,yo+y0,zo+z0,&xi,&yi,&zi,nx,ny,nz);
|
|
if (type == 'h') {
|
|
h = 255*zo/(nz-1.0);
|
|
if ((h > image[yo][xo]) && (i > arg))
|
|
image[yo][xo] = h;
|
|
GIFline[xo] = image[yo][xo]*(nz-1.0)/zo;
|
|
}
|
|
else if (type == 's') {
|
|
GIFline[xo] = 255*pow((i-fmin)/(fmax-fmin),arg);
|
|
}
|
|
}
|
|
}
|
|
EGifPutLine(GIFfile,GIFline,dx);
|
|
}
|
|
}
|
|
printf("\n");
|
|
//
|
|
// put mm per pixel in comment
|
|
//
|
|
sprintf(comment,"mm per pixel: %f;",size);
|
|
EGifPutComment(GIFfile,comment);
|
|
//
|
|
// exit
|
|
//
|
|
fclose(input_file);
|
|
EGifCloseFile(GIFfile);
|
|
exit(0);
|
|
}
|