kopia lustrzana https://github.com/fellesverkstedet/fabmodules
347 wiersze
12 KiB
C
347 wiersze
12 KiB
C
//
|
|
// gif_png.c
|
|
// .gif to .png
|
|
//
|
|
// Neil Gershenfeld 9/20/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.
|
|
//
|
|
|
|
#define MAX_LINE 10000
|
|
#define BIG 1e10
|
|
|
|
#include "fab.h"
|
|
|
|
int main(int argc, char **argv) {
|
|
//
|
|
// local vars
|
|
//
|
|
GifFileType *GIFfile;
|
|
GifRecordType GIFtype;
|
|
GifByteType *GIFextension;
|
|
GifPixelType *GIFline;
|
|
uint32_t **lower_array,**upper_array;
|
|
double **image_array;
|
|
double f,fmin,fmax;
|
|
int x,y,z,h,i,j,k,n,p;
|
|
int imin,imax,image_width,image_height,image_count,color_resolution,GIFcode,ret;
|
|
float pixel_size,arg,threshold,rx,ry,rz;
|
|
char type,comment[256];
|
|
struct fab_vars v;
|
|
init_vars(&v);
|
|
//
|
|
// command line args
|
|
//
|
|
if (!((argc == 3) || (argc == 4) || (argc == 5) || (argc == 6) || (argc == 7) || (argc == 10))) {
|
|
printf("command line: gif_png in.gif out.png [type [arg [points [size [rx ry rz]]]]]\n");
|
|
printf(" in.gif = input gif file\n");
|
|
printf(" out.png = output PNG file\n");
|
|
printf(" type = 'z' of density, 'h' for height (default z)\n");
|
|
printf(" arg = type argument\n");
|
|
printf(" 'z': gamma (default 1)\n");
|
|
printf(" 'h': threshold (0 = min, 1 = max, default 0.5)\n");
|
|
printf(" points = points to interpolate per point (linear, default 0)\n");
|
|
printf(" size = voxel size (mm, default from file))\n");
|
|
printf(" to be implemented: rx,ry,rz = x,y,z rotation angles (degrees; default 0)\n");
|
|
exit(-1);
|
|
}
|
|
type = 'z';
|
|
p = 0;
|
|
rx = ry = rz = 0;
|
|
pixel_size = -1;
|
|
image_width = -1;
|
|
image_height = -1;
|
|
if (argc >= 4) {
|
|
sscanf(argv[3],"%c",&type);
|
|
if (!((type == 'z') || (type == 'h'))) {
|
|
printf("gif_png: oops -- type must be 'z' or 'h'\n");
|
|
exit(-1);
|
|
}
|
|
}
|
|
if (type == 'z') arg = 1.0;
|
|
else if (type == 'h') arg = 0.5;
|
|
if (argc >= 5)
|
|
sscanf(argv[4],"%f",&arg);
|
|
if (argc >= 6)
|
|
sscanf(argv[5],"%d",&p);
|
|
if (argc >= 7)
|
|
sscanf(argv[6],"%f",&pixel_size);
|
|
if (argc >= 10) {
|
|
sscanf(argv[7],"%f",&rx);
|
|
sscanf(argv[8],"%f",&ry);
|
|
sscanf(argv[9],"%f",&rz);
|
|
}
|
|
//
|
|
// scan the file
|
|
//
|
|
printf("read %s\n",argv[1]);
|
|
imin = 256;
|
|
imax = 0;
|
|
color_resolution = -1;
|
|
GIFfile = DGifOpenFileName(argv[1]);
|
|
if (GIFfile == NULL) {
|
|
printf("gif_png: oops -- can not open %s\n",argv[1]);
|
|
exit(-1);
|
|
}
|
|
GIFline = malloc(MAX_LINE*sizeof(GifPixelType));
|
|
do {
|
|
DGifGetRecordType(GIFfile,&GIFtype);
|
|
switch (GIFtype) {
|
|
case IMAGE_DESC_RECORD_TYPE:
|
|
DGifGetImageDesc(GIFfile);
|
|
image_width = GIFfile->SWidth;
|
|
image_height = GIFfile->SHeight;
|
|
image_count = GIFfile->ImageCount;
|
|
color_resolution = GIFfile->SColorResolution;
|
|
for (y = 0; y < GIFfile->SHeight; ++y) {
|
|
ret = DGifGetLine(GIFfile,GIFline,GIFfile->SWidth);
|
|
if (ret != GIF_OK) {
|
|
printf("gif_png: oops -- error reading line\n");
|
|
exit(-1);
|
|
}
|
|
for (x = 0; x < GIFfile->SWidth; ++x) {
|
|
if (GIFline[x] < imin) imin = GIFline[x];
|
|
if (GIFline[x] > imax) imax = GIFline[x];
|
|
}
|
|
}
|
|
break;
|
|
case EXTENSION_RECORD_TYPE:
|
|
DGifGetExtension(GIFfile,&GIFcode,&GIFextension);
|
|
if (GIFcode == COMMENT_EXT_FUNC_CODE) {
|
|
n = GIFextension[0];
|
|
for (i = 1; i <= n; ++i)
|
|
comment[i-1] = GIFextension[i];
|
|
comment[n] = 0;
|
|
if (pixel_size == -1)
|
|
sscanf(comment,"mm per pixel: %f;",&pixel_size);
|
|
}
|
|
while (GIFextension != NULL)
|
|
DGifGetExtensionNext(GIFfile,&GIFextension);
|
|
break;
|
|
case SCREEN_DESC_RECORD_TYPE:
|
|
DGifGetScreenDesc(GIFfile);
|
|
break;
|
|
case TERMINATE_RECORD_TYPE:
|
|
break;
|
|
case UNDEFINED_RECORD_TYPE:
|
|
printf("gif_png: oops -- undefined GIF record type\n");
|
|
exit(-1);
|
|
break;
|
|
}
|
|
} while (GIFtype != TERMINATE_RECORD_TYPE);
|
|
if (GIFfile == NULL) {
|
|
printf("gif_png: oops -- can not open %s\n",argv[1]);
|
|
exit(-1);
|
|
}
|
|
if (pixel_size == -1) {
|
|
pixel_size = 1.0;
|
|
printf(" no pixel size found, assuming 1 mm\n");
|
|
}
|
|
printf(" pixel size (mm): %f, color resolution (bits): %d\n",pixel_size,color_resolution);
|
|
printf(" intensity min: %d max: %d\n",imin,imax);
|
|
printf(" number of images: %d, image width %d, image height %d\n",image_count,image_width,image_height);
|
|
//
|
|
// set threshold
|
|
//
|
|
if (type == 'h')
|
|
threshold = imin + arg*(imax-imin);
|
|
//
|
|
// check and set limits
|
|
//
|
|
v.nx = image_width + (image_width-1)*p;
|
|
v.ny = image_height + (image_height-1)*p;
|
|
v.nz = image_count + (image_count-1)*p;
|
|
v.dx = v.nx*pixel_size;
|
|
v.dy = v.ny*pixel_size;
|
|
v.dz = v.nz*pixel_size;
|
|
v.xmin = 0;
|
|
v.ymin = 0;
|
|
v.zmin = 0;
|
|
//
|
|
// allocate arrays
|
|
//
|
|
lower_array = malloc(image_height*sizeof(uint32_t *));
|
|
for (y = 0; y < image_height; ++y) {
|
|
lower_array[y] = malloc(image_width*sizeof(uint32_t));
|
|
for (x = 0; x < image_width; ++x)
|
|
lower_array[y][x] = 0;
|
|
}
|
|
upper_array = malloc(image_height*sizeof(uint32_t *));
|
|
for (y = 0; y < image_height; ++y) {
|
|
upper_array[y] = malloc(image_width*sizeof(uint32_t));
|
|
for (x = 0; x < image_width; ++x)
|
|
upper_array[y][x] = 0;
|
|
}
|
|
image_array = malloc(v.ny*sizeof(double *));
|
|
for (y = 0; y < v.ny; ++y) {
|
|
image_array[y] = malloc(v.nx*sizeof(double));
|
|
for (x = 0; x < v.nx; ++x)
|
|
image_array[y][x] = 0;
|
|
}
|
|
v.array = malloc(v.ny*sizeof(uint32_t *));
|
|
for (y = 0; y < v.ny; ++y) {
|
|
v.array[y] = malloc(v.nx*sizeof(uint32_t));
|
|
for (x = 0; x < v.nx; ++x)
|
|
v.array[y][x] = 0;
|
|
}
|
|
//
|
|
// read the file
|
|
//
|
|
DGifCloseFile(GIFfile);
|
|
GIFfile = DGifOpenFileName(argv[1]);
|
|
if (GIFfile == NULL) {
|
|
printf("gif_png: oops -- can not open %s\n",argv[1]);
|
|
exit(-1);
|
|
}
|
|
z = 0;
|
|
do {
|
|
DGifGetRecordType(GIFfile,&GIFtype);
|
|
switch (GIFtype) {
|
|
case IMAGE_DESC_RECORD_TYPE:
|
|
//
|
|
// read image
|
|
//
|
|
DGifGetImageDesc(GIFfile);
|
|
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b layer = %d",z);
|
|
if (z == 0) {
|
|
//
|
|
// read first layer
|
|
//
|
|
for (y = 0; y < image_height; ++y) {
|
|
ret = DGifGetLine(GIFfile,GIFline,GIFfile->SWidth);
|
|
if (ret != GIF_OK) {
|
|
printf("gif_png: oops -- error reading first line\n");
|
|
exit(-1);
|
|
}
|
|
for (x = 0; x < image_width; ++x)
|
|
upper_array[y][x] = GIFline[x];
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// read next layer
|
|
//
|
|
for (y = 0; y < image_height; ++y) {
|
|
ret = DGifGetLine(GIFfile,GIFline,GIFfile->SWidth);
|
|
if (ret != GIF_OK) {
|
|
printf("gif_png: oops -- error reading line\n");
|
|
exit(-1);
|
|
}
|
|
for (x = 0; x < image_width; ++x) {
|
|
lower_array[y][x] = upper_array[y][x];
|
|
upper_array[y][x] = GIFline[x];
|
|
}
|
|
}
|
|
if (p == 0) {
|
|
//
|
|
// no interpolation, loop over layer voxels
|
|
//
|
|
for (x = 0; x < (image_width-1); ++x) {
|
|
for (y = 0; y < (image_height-1); ++y) {
|
|
if (type == 'z') {
|
|
image_array[y][x] += lower_array[y][x];
|
|
}
|
|
else if (type == 'h') {
|
|
if ((lower_array[y][x] >= threshold) && (upper_array[y][x] < threshold))
|
|
image_array[y][x] = z + (lower_array[y][x]-threshold)/(lower_array[y][x]-upper_array[y][x]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// yes interpolation, loop over layer sub-voxels
|
|
//
|
|
for (x = 0; x < (image_width-1); ++x) {
|
|
for (y = 0; y < (image_height-1); ++y) {
|
|
for (i = 0; i <= p; ++i) {
|
|
for (j = 0; j <= p; ++j) {
|
|
for (k = 0; k <= p; ++k) {
|
|
f = lower_array[y][x]*((p+1.0-i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((p+1.0-k)/(p+1.0))
|
|
+ lower_array[y][x+1]*((i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((p+1.0-k)/(p+1.0))
|
|
+ lower_array[y+1][x]*((p+1.0-i)/(p+1.0))*((j)/(p+1.0))*((p+1.0-k)/(p+1.0))
|
|
+ lower_array[y+1][x+1]*((i)/(p+1.0))*((j)/(p+1.0))*((p+1.0-k)/(p+1.0))
|
|
+ upper_array[y][x]*((p+1.0-i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((k)/(p+1.0))
|
|
+ upper_array[y][x+1]*((i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((k)/(p+1.0))
|
|
+ upper_array[y+1][x]*((p+1.0-i)/(p+1.0))*((j)/(p+1.0))*((k)/(p+1.0))
|
|
+ upper_array[y+1][x+1]*((i)/(p+1.0))*((j)/(p+1.0))*((k)/(p+1.0));
|
|
if (type == 'z') {
|
|
image_array[(1+p)*y+j][(1+p)*x+i] += f;
|
|
}
|
|
else if (type == 'h') {
|
|
h = (1+p)*z+k;
|
|
if ((f > threshold) && (h > image_array[(1+p)*y+j][(1+p)*x+i]))
|
|
image_array[(1+p)*y+j][(1+p)*x+i] = h;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
z += 1;
|
|
break;
|
|
case EXTENSION_RECORD_TYPE:
|
|
DGifGetExtension(GIFfile,&GIFcode,&GIFextension);
|
|
while (GIFextension != NULL)
|
|
DGifGetExtensionNext(GIFfile,&GIFextension);
|
|
break;
|
|
case SCREEN_DESC_RECORD_TYPE:
|
|
DGifGetScreenDesc(GIFfile);
|
|
break;
|
|
case TERMINATE_RECORD_TYPE:
|
|
break;
|
|
case UNDEFINED_RECORD_TYPE:
|
|
printf("gif_png: oops -- undefined GIF record type\n");
|
|
exit(-1);
|
|
break;
|
|
}
|
|
} while (GIFtype != TERMINATE_RECORD_TYPE);
|
|
printf("\n");
|
|
//
|
|
// scale image and copy to PNG array
|
|
//
|
|
if (type == 'z') {
|
|
fmin = BIG;
|
|
fmax = 0;
|
|
for (x = 0; x < v.nx; ++x) {
|
|
for (y = 0; y < v.ny; ++y) {
|
|
if (image_array[y][x] > fmax) fmax = image_array[y][x];
|
|
if (image_array[y][x] < fmin) fmin = image_array[y][x];
|
|
}
|
|
}
|
|
if (arg == 1) {
|
|
for (x = 0; x < v.nx; ++x)
|
|
for (y = 0; y < v.ny; ++y)
|
|
v.array[y][x] = 65536*(image_array[y][x]-fmin)/(fmax-fmin);
|
|
}
|
|
else {
|
|
for (x = 0; x < v.nx; ++x)
|
|
for (y = 0; y < v.ny; ++y)
|
|
v.array[y][x] = 65536*pow((image_array[y][x]-fmin)/(fmax-fmin),arg);
|
|
}
|
|
}
|
|
else if (type == 'h') {
|
|
for (x = 0; x < v.nx; ++x)
|
|
for (y = 0; y < v.ny; ++y)
|
|
v.array[y][x] = 65536*image_array[y][x]/(v.nz-1.0);
|
|
}
|
|
//
|
|
// write PNG
|
|
//
|
|
v.bit_depth = 16;
|
|
fab_write_png_K(&v,argv[2]);
|
|
//
|
|
// exit
|
|
//
|
|
DGifCloseFile(GIFfile);
|
|
exit(0);
|
|
}
|