int main(int argc, char *argv[]) { static VFloat reso = -1.0; static VLong itype = 0; static VBoolean flip = TRUE; static VBoolean reorder = TRUE; static VOptionDescRec options[] = { { "reso", VFloatRepn, 1, (VPointer) &reso, VOptionalOpt, NULL, "New voxel resolution in mm, def: -1 means min(1.0,\"best source resolution\")" }, { "flip", VBooleanRepn, 1, (VPointer) &flip, VOptionalOpt, NULL, "Whether to flip to natural convention" }, { "reorder", VBooleanRepn, 1, (VPointer) &reorder, VOptionalOpt, NULL, "Whether to reorder axial slices from axial source image" }, { "interpolation", VLongRepn, 1, & itype, VOptionalOpt, ITYPDict, "Type of interpolation (0: linear, 1: nearest neighbour, 2: cubic spline)" } }; FILE *in_file, *out_file; VAttrList list; VAttrListPosn posn; int nobjects = 0; VImage src = NULL, dest = NULL, result = NULL; int i, b, r, c, nbands, nrows, ncols; VString str, newstr, fixpointString, caString, cpString; float fix_c, fix_r, fix_b; float ca_c, ca_r, ca_b; float cp_c, cp_r, cp_b; float x, y, z, min; VDouble v, scale_band, scale_row, scale_col; float scale[3], shift[3]; /* print information */ char prg_name[100]; char ver[100]; getLipsiaVersion(ver, sizeof(ver)); sprintf(prg_name, "visotrop V%s", ver); fprintf(stderr, "%s\n", prg_name); fflush(stderr); /* Parse command line arguments: */ VParseFilterCmd(VNumber(options), options, argc, argv, & in_file, & out_file); /* Read source image(s): */ if(!(list = VReadFile(in_file, NULL))) exit(EXIT_FAILURE); /* Scale each object: */ for(VFirstAttr(list, & posn); VAttrExists(& posn); VNextAttr(& posn)) { switch(VGetAttrRepn(& posn)) { case VImageRepn: VGetAttrValue(& posn, NULL, VImageRepn, & src); if(VGetAttr(VImageAttrList(src), "voxel", NULL, VStringRepn, (VPointer) & str) == VAttrFound) { sscanf(str, "%f %f %f", &x, &y, &z); fprintf(stderr, " voxel: %f %f %f\n", x, y, z); min = x < y ? x : y; min = z < min ? z : min; /* if resolution is not set, use default value 1 or smaler value if the image resolution is better */ if(reso < 0.0) reso = min < 1.0 ? min : 1.0; if(reso <= 0.0) exit(EXIT_FAILURE); fprintf(stderr, " new resolution: %f \n", reso); scale_col = x / reso; scale_row = y / reso; scale_band = z / reso; nbands = VImageNBands(src) * scale_band; nrows = VImageNRows(src) * scale_row; ncols = VImageNColumns(src) * scale_col; if(VImageNBands(src) == nbands && VImageNRows(src) == nrows && VImageNColumns(src) == ncols) { itype = 0; } fprintf(stderr, " interpolation type: %s\n", ITYPDict[itype].keyword); fprintf(stderr, " old dim: %3d %3d %3d\n", VImageNBands(src), VImageNRows(src), VImageNColumns(src)); for(i = 0; i < 3; i++) shift[i] = scale[i] = 0; scale[0] = scale_band; scale[1] = scale_row; scale[2] = scale_col; switch(itype) { /* trilinear interpolation resampling */ case 0: dest = VTriLinearScale3d(src, NULL, (int)nbands, (int)nrows, (int)ncols, shift, scale); break; /* nearest neightbour resampling */ case 1: dest = VNNScale3d(src, NULL, (int)nbands, (int)nrows, (int)ncols, shift, scale); break; /* cubic spline */ case 2: dest = VCubicSplineScale3d(src, NULL, (int)nbands, (int)nrows, (int)ncols, shift, scale); break; case 3: /* no interpolation, just reshuffle */ dest = VCopyImage(src, NULL, VAllBands); break; default: VError(" unknown resampling type %d", itype); } if(! dest) exit(EXIT_FAILURE); /*aa 2003/09/11 added function not to rotate siemens data*/ if(! VGetAttr(VImageAttrList(src), "orientation", NULL, VStringRepn, (VPointer) & str) == VAttrFound) VError(" attribute 'orientation' missing"); if(strcmp(str, "axial") == 0) { fprintf(stderr, " new dim: %3d %3d %3d\n", nbands, nrows, ncols); result = VCreateImage(nbands, nrows, ncols, VPixelRepn(src)); VFillImage(result, VAllBands, 0); for(b = 0; b < nbands; b++) for(r = 0; r < nrows; r++) for(c = 0; c < ncols; c++) { v = VGetPixel(dest, b, r, c); if((flip == FALSE) && (reorder == FALSE)) VSetPixel(result, b, r, ncols - c - 1, v); else if((flip == TRUE) && (reorder == FALSE)) VSetPixel(result, b, r, c, v); else if((flip == FALSE) && (reorder == TRUE)) VSetPixel(result, nbands - b - 1, r, ncols - c - 1, v); else if((flip == TRUE) && (reorder == TRUE)) VSetPixel(result, nbands - b - 1, r, c, v); } } else if(strcmp(str, "sagittal") == 0) { /* re-arrange from sagittal to axial orientation */ fprintf(stderr, " new dim: %3d %3d %3d\n", nrows, ncols, nbands); result = VCreateImage(nrows, ncols, nbands, VPixelRepn(src)); VFillImage(result, VAllBands, 0); for(b = 0; b < nbands; b++) for(r = 0; r < nrows; r++) for(c = 0; c < ncols; c++) { v = VGetPixel(dest, b, r, c); if(flip == FALSE) VSetPixel(result, r, c, nbands - b - 1, v); else VSetPixel(result, r, c, b, v); } } else if(strcmp(str, "coronal") == 0) { /* re-arrange from coronal to axial orientation */ fprintf(stderr, " new dim: %3d %3d %3d\n", nrows, nbands, ncols); result = VCreateImage(nrows, nbands, ncols, VPixelRepn(src)); VFillImage(result, VAllBands, 0); for(b = 0; b < nbands; b++) for(r = 0; r < nrows; r++) for(c = 0; c < ncols; c++) { v = VGetPixel(dest, b, r, c); if(flip == FALSE) VSetPixel(result, r, b, ncols - c - 1, v); else VSetPixel(result, r, b, c, v); } } else { VError(" unknown resampling type %d", itype); exit(EXIT_FAILURE); } /* copy attributes from source image */ VCopyImageAttrs(src, result); // [TS] 08/03/27 // correct 'fixpoint', 'ca' and 'cp' if they exist in the source image // // NOTE: // this is only done when no flipping or reordering is requested :-( // (WARNING!!!!) '-flip true' actually means that no flipping is done (WHAAAAT ????) // and therefore we test for reorder = false and flip = true fixpointString = VMalloc(80); caString = VMalloc(80); cpString = VMalloc(80); VBoolean _issueWarning = FALSE; if(VGetAttr(VImageAttrList(src), "fixpoint", NULL, VStringRepn, (VPointer)&fixpointString) == VAttrFound) { if(reorder == FALSE && flip == TRUE) { sscanf(fixpointString, "%f %f %f", &fix_c, &fix_r, &fix_b); fix_c *= scale_col; fix_r *= scale_row; fix_b *= scale_band; sprintf((char *)fixpointString, "%f %f %f", fix_c, fix_r, fix_b); VSetAttr(VImageAttrList(result), "fixpoint", NULL, VStringRepn, fixpointString); } else { _issueWarning = TRUE; } } if(VGetAttr(VImageAttrList(src), "ca", NULL, VStringRepn, (VPointer)&caString) == VAttrFound) { if(reorder == FALSE && flip == TRUE) { sscanf(caString, "%f %f %f", &ca_c, &ca_r, &ca_b); ca_c *= scale_col; ca_r *= scale_row; ca_b *= scale_band; sprintf((char *)caString, "%f %f %f", ca_c, ca_r, ca_b); VSetAttr(VImageAttrList(result), "ca", NULL, VStringRepn, caString); } else { _issueWarning = TRUE; } } if(VGetAttr(VImageAttrList(src), "cp", NULL, VStringRepn, (VPointer)&cpString) == VAttrFound) { if(reorder == FALSE && flip == TRUE) { sscanf(cpString, "%f %f %f", &cp_c, &cp_r, &cp_b); cp_c *= scale_col; cp_r *= scale_row; cp_b *= scale_band; sprintf((char *)cpString, "%f %f %f", cp_c, cp_r, cp_b); VSetAttr(VImageAttrList(result), "cp", NULL, VStringRepn, cpString); } else { _issueWarning = TRUE; } } if(_issueWarning) { VWarning("Attributes 'fixpoint', 'ca' and 'cp' exist but were not corrected and are therefore likely to be wrong"); VWarning("This was caused by setting -flip to false or -reorder to true"); VWarning("Please correct the values manually using vattredit"); } /* set the attributes to the changed values */ newstr = VMalloc(80); sprintf((char *)newstr, "%f %f %f", reso, reso, reso); VSetAttr(VImageAttrList(result), "voxel", NULL, VStringRepn, newstr); VSetAttr(VImageAttrList(result), "orientation", NULL, VStringRepn, "axial"); if(flip) VSetAttr(VImageAttrList(result), "convention", NULL, VStringRepn, "natural"); else VSetAttr(VImageAttrList(result), "convention", NULL, VStringRepn, "radiologic"); } VSetAttrValue(& posn, NULL, VImageRepn, result); VDestroyImage(src); break; default: continue; } nobjects++; } /* Make History */ VHistory(VNumber(options), options, prg_name, &list, &list); /* Write the results to the output file: */ if(! VWriteFile(out_file, list)) exit(EXIT_FAILURE); fprintf(stderr, "%s: done.\n", argv[0]); return EXIT_SUCCESS; }
VImage VDoTrans(VImage src, VImage dest, VImage transform, VFloat resolution, VLong type) { VImage src1 = NULL, dest_cor = NULL, dest_sag = NULL, trans = NULL; int i, nbands1 = 0, nrows1 = 0, ncols1 = 0; int xdim, ydim, zdim; int orient = AXIAL; float b0, r0, c0; float scaleb, scaler, scalec; float scale[3], shift[3]; VString str, str1, str2, str3, str4, str5, str6; VShort buf; VDouble u; float transResX = 1.0, transResY = 1.0, transResZ = 1.0; VString _transResString; if(VGetAttr(VImageAttrList(transform), "voxel", NULL, VStringRepn, (VPointer) &_transResString) == VAttrFound) { sscanf(_transResString, "%f %f %f", &transResX, &transResY, &transResZ); } /* ** get matrix size */ xdim = 160; ydim = 200; zdim = 160; if(VGetAttr(VImageAttrList(transform), "zdim", NULL, VShortRepn, (VPointer) & buf) == VAttrFound) { zdim = buf; } if(VGetAttr(VImageAttrList(transform), "ydim", NULL, VShortRepn, (VPointer) & buf) == VAttrFound) { ydim = buf; } if(VGetAttr(VImageAttrList(transform), "xdim", NULL, VShortRepn, (VPointer) & buf) == VAttrFound) { xdim = buf; } /* ** get slice orientation */ if(VGetAttr(VImageAttrList(src), "orientation", NULL, VStringRepn, (VPointer) & str) != VAttrFound) VError(" attribute 'orientation' missing in input file."); if(strcmp(str, "coronal") == 0) { orient = CORONAL; nbands1 = ydim; nrows1 = zdim; ncols1 = xdim; } else if(strcmp(str, "axial") == 0) { orient = AXIAL; nbands1 = zdim; nrows1 = ydim; ncols1 = xdim; } else if(strcmp(str, "sagittal") == 0) { orient = SAGITTAL; nbands1 = zdim; nrows1 = xdim; ncols1 = ydim; } else VError("orientation must be axial or coronal"); nbands1 /= (resolution / transResX); nrows1 /= (resolution / transResY); ncols1 /= (resolution / transResZ); /* ** scale to size */ if(VGetAttr(VImageAttrList(src), "voxel", NULL, VStringRepn, (VPointer) & str) != VAttrFound) VError(" attribute 'voxel' missing in input file."); sscanf(str, "%f %f %f", &scalec, &scaler, &scaleb); scaleb /= (resolution / transResX); scaler /= (resolution / transResY); scalec /= (resolution / transResZ); scale[0] = scaleb; scale[1] = scaler; scale[2] = scalec; shift[0] = 0; shift[1] = (float)nrows1 * 0.5 - scaler * (float)VImageNRows(src) * 0.5; shift[2] = (float)ncols1 * 0.5 - scalec * (float)VImageNColumns(src) * 0.5; src1 = VShuffleSlices(src, NULL); switch(type) { case 0: src = VTriLinearScale3d(src1, NULL, nbands1, nrows1, ncols1, shift, scale); break; case 1: src = VNNScale3d(src1, NULL, nbands1, nrows1, ncols1, shift, scale); break; default: VError(" illegal resampling type"); } /* ** resample image */ trans = VCopyImage(transform, NULL, VAllBands); for(i = 0; i < 3; i++) { u = VPixel(trans, 0, i, 0, VDouble); u /= resolution; VPixel(trans, 0, i, 0, VDouble) = u; } b0 = (float)nbands1 * 0.5; r0 = (float)nrows1 * 0.5; c0 = (float)ncols1 * 0.5; switch(type) { case 0: dest = VTriLinearSample3d(src, dest, trans, b0, r0, c0, nbands1, nrows1, ncols1); break; case 1: dest = VNNSample3d(src, dest, trans, b0, r0, c0, nbands1, nrows1, ncols1); break; } /* ** update header */ float _cax, _cay, _caz, _cpx, _cpy, _cpz; float _fixpointx, _fixpointy, _fixpointz; str1 = str2 = str3 = str4 = NULL; str1 = (VString) VMalloc(80); sprintf(str1, "%.2f %.2f %.2f", resolution, resolution, resolution); if(VGetAttr(VImageAttrList(trans), "ca", NULL, VStringRepn, (VPointer) & str2) != VAttrFound) { str2 = NULL; } else { sscanf(str2, "%f %f %f", &_cax, &_cay, &_caz); _cax /= (resolution / transResX); _cay /= (resolution / transResY); _caz /= (resolution / transResZ); sprintf(str2, "%.2f %.2f %.2f", _cax, _cay, _caz); } if(VGetAttr(VImageAttrList(trans), "cp", NULL, VStringRepn, (VPointer) & str3) != VAttrFound) { str3 = NULL; } else { sscanf(str3, "%f %f %f", &_cpx, &_cpy, &_cpz); _cpx /= (resolution / transResX); _cpy /= (resolution / transResY); _cpz /= (resolution / transResZ); sprintf(str3, "%.2f %.2f %.2f", _cpx, _cpy, _cpz); } if(VGetAttr(VImageAttrList(trans), "extent", NULL, VStringRepn, (VPointer) & str4) != VAttrFound) str4 = NULL; if(VGetAttr(VImageAttrList(trans), "fixpoint", NULL, VStringRepn, (VPointer) & str5) != VAttrFound) { str5 = NULL; } else { sscanf(str5, "%f %f %f", &_fixpointx, &_fixpointy, &_fixpointz); _fixpointx /= (resolution / transResX); _fixpointy /= (resolution / transResY); _fixpointz /= (resolution / transResZ); sprintf(str5, "%.2f %.2f %.2f", _fixpointx, _fixpointy, _fixpointz); } if(VGetAttr(VImageAttrList(trans), "talairach", NULL, VStringRepn, (VPointer) & str6) != VAttrFound) { str6 = NULL; } if(orient == CORONAL) { dest_cor = VAxial2Coronal(dest, NULL); VDestroyImage(dest); VCopyImageAttrs(src, dest_cor); VSetAttr(VImageAttrList(dest_cor), "voxel", NULL, VStringRepn, str1); if(str2) VSetAttr(VImageAttrList(dest_cor), "ca", NULL, VStringRepn, str2); if(str3) VSetAttr(VImageAttrList(dest_cor), "cp", NULL, VStringRepn, str3); if(str4) VSetAttr(VImageAttrList(dest_cor), "extent", NULL, VStringRepn, str4); if(str5) VSetAttr(VImageAttrList(dest_cor), "fixpoint", NULL, VStringRepn, str5); if(str6) VSetAttr(VImageAttrList(dest_cor), "talairach", NULL, VStringRepn, str6); return dest_cor; } else if(orient == SAGITTAL) { dest_sag = VAxial2Sagittal(dest, NULL); VDestroyImage(dest); VCopyImageAttrs(src, dest_sag); VSetAttr(VImageAttrList(dest_sag), "voxel", NULL, VStringRepn, str1); if(str2) VSetAttr(VImageAttrList(dest_sag), "ca", NULL, VStringRepn, str2); if(str3) VSetAttr(VImageAttrList(dest_sag), "cp", NULL, VStringRepn, str3); if(str4) VSetAttr(VImageAttrList(dest_sag), "extent", NULL, VStringRepn, str4); if(str5) VSetAttr(VImageAttrList(dest_sag), "fixpoint", NULL, VStringRepn, str5); if(str6) VSetAttr(VImageAttrList(dest_sag), "talairach", NULL, VStringRepn, str6); return dest_sag; } else { VCopyImageAttrs(src, dest); VSetAttr(VImageAttrList(dest), "voxel", NULL, VStringRepn, str1); if(str2) VSetAttr(VImageAttrList(dest), "ca", NULL, VStringRepn, str2); if(str3) VSetAttr(VImageAttrList(dest), "cp", NULL, VStringRepn, str3); if(str4) VSetAttr(VImageAttrList(dest), "extent", NULL, VStringRepn, str4); if(str5) VSetAttr(VImageAttrList(dest), "fixpoint", NULL, VStringRepn, str5); if(str6) VSetAttr(VImageAttrList(dest), "talairach", NULL, VStringRepn, str6); return dest; } }