amiraio.cpp

Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00007  * Copyright (c) 2000-2006 Baylor College of Medicine
00008  *
00009  * This software is issued under a joint BSD/GNU license. You may use the
00010  * source code in this file under either license. However, note that the
00011  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00012  * so you are responsible for compliance with the licenses of these packages
00013  * if you opt to use BSD licensing. The warranty disclaimer below holds
00014  * in either instance.
00015  *
00016  * This complete copyright notice must be included in any revised version of the
00017  * source code. Additional authorship citations may be added, but existing
00018  * author citations must be preserved.
00019  *
00020  * This program is free software; you can redistribute it and/or modify
00021  * it under the terms of the GNU General Public License as published by
00022  * the Free Software Foundation; either version 2 of the License, or
00023  * (at your option) any later version.
00024  *
00025  * This program is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028  * GNU General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU General Public License
00031  * along with this program; if not, write to the Free Software
00032  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00033  *
00034  * */
00035 
00036 #include "amiraio.h"
00037 #include "util.h"
00038 
00039 #ifndef WIN32
00040         #include <sys/param.h>
00041 #else
00042         #include <windows.h>
00043         #define MAXPATHLEN (MAX_PATH*4)
00044 #endif  //WIN32
00045 
00046 #include <cstdio>
00047 
00048 using namespace EMAN;
00049 
00050 const char *AmiraIO::MAGIC = "# AmiraMesh";
00051 
00052 AmiraIO::AmiraIO(const string & file, IOMode rw)
00053 :       filename(file), rw_mode(rw), amira_file(0),
00054         is_big_endian(true), initialized(false), dt(EMUtil::EM_UNKNOWN),
00055          nx(0), ny(0), nz(0),
00056          pixel(0), xorigin(0), yorigin(0), zorigin(0)
00057 {
00058 }
00059 
00060 AmiraIO::~AmiraIO()
00061 {
00062         if (amira_file) {
00063                 fclose(amira_file);
00064                 amira_file = 0;
00065         }
00066 }
00067 
00068 void AmiraIO::init()
00069 {
00070         ENTERFUNC;
00071 
00072         if (initialized) {
00073                 return;
00074         }
00075 
00076         initialized = true;
00077         bool is_new_file = false;
00078 
00079         amira_file = sfopen(filename, rw_mode, &is_new_file, true);
00080 
00081         if (!is_new_file) {
00082                 char buf[MAXPATHLEN];
00083                 if (!fgets(buf, MAXPATHLEN, amira_file)) {
00084                         throw ImageReadException(filename, "Amira Header");
00085                 }
00086 
00087                 if (!is_valid(buf)) {
00088                         throw ImageReadException(filename, "invalid Amira Mesh file");
00089                 }
00090 
00091                 if(strstr(buf,"BINARY-LITTLE-ENDIAN")!=0) {
00092                         is_big_endian = false;
00093                 }
00094                 else if(strstr(buf,"BINARY")!=0) {
00095                         is_big_endian = true;
00096                 }
00097                 else if(strstr(buf,"2.0")!=0) {
00098                         is_big_endian = true; //AMIRA convention(<=2.0): BIGENDIAN only
00099                 }
00100         }
00101         EXITFUNC;
00102 }
00103 
00104 bool AmiraIO::is_valid(const void *first_block)
00105 {
00106         ENTERFUNC;
00107         bool result = false;
00108         if (!first_block) {
00109                 result = false;
00110         }
00111         else {
00112                 result = Util::check_file_by_magic(first_block, MAGIC);
00113         }
00114         EXITFUNC;
00115         return result;
00116 }
00117 
00118 int AmiraIO::read_header(Dict & dict, int, const Region *, bool)
00119 {
00120         ENTERFUNC;
00121         init();
00122 
00123         char ll[MAXPATHLEN+10];
00124         char datatype[16] = "";
00125 
00126         do {
00127                 fgets(ll,MAXPATHLEN,amira_file);
00128 //              printf("%s", ll);
00129                 if(char* s=strstr(ll,"define Lattice ")) {
00130                         if(sscanf(s+15,"%d %d %d",&nx, &ny, &nz) == 3) {
00131                                 dict["nx"] = nx;
00132                                 dict["ny"] = ny;
00133                                 dict["nz"] = nz;
00134 //                              printf("nx = %d, ny = %d, nz = %d\n", nx, ny, nz);
00135                         };
00136                 }
00137                 else if(char* s=strstr(ll,"BoundingBoxXY")) {           //amiramesh 2.1
00138                         float bx0, bx1, by0, by1;
00139                         if (sscanf(s+13,"%f %f %f %f",&bx0, &bx1, &by0, &by1) == 4 ) {
00140                                 pixel = (bx1-bx0)/(nx-1);
00141                                 xorigin = bx0;
00142                                 yorigin = by0;
00143                                 dict["apix_x"] = pixel;
00144                                 dict["apix_y"] = pixel;
00145                                 dict["apix_z"] = pixel;
00146                                 dict["origin_x"] = xorigin;
00147                                 dict["origin_y"] = yorigin;
00148 //                              printf("pixel=%g: xorigin=%g yorigin=%g \n", pixel, xorigin, yorigin);
00149                         }
00150                 }
00151                 else if(char* s=strstr(ll,"BoundingBox")) {             //amiramesh 2.0
00152                         float bx0, bx1, by0, by1, bz0, bz1;
00153                         if (sscanf(s+11,"%f %f %f %f %f %f",&bx0, &bx1, &by0, &by1, &bz0, &bz1) == 6 ) {
00154                                 pixel = (bx1-bx0)/(nx-1);
00155                                 xorigin = bx0;
00156                                 yorigin = by0;
00157                                 zorigin = bz0;
00158                                 dict["apix_x"] = pixel;
00159                                 dict["apix_y"] = pixel;
00160                                 dict["apix_z"] = pixel;
00161                                 dict["origin_x"] = xorigin;
00162                                 dict["origin_y"] = yorigin;
00163                                 dict["origin_z"] = zorigin;
00164 //                              printf("pixel=%g: xorigin=%g yorigin=%g zorigin=%g\n", pixel, xorigin, yorigin, zorigin);
00165                         }
00166                 }
00167                 else if(char* s=strstr(ll,"Lattice { ")) {
00168                         sscanf(s+10,"%s ", datatype);
00169                         if(!strncmp(datatype, "float", 5)) {
00170                                 dt = EMUtil::EM_FLOAT;
00171                                 dict["datatype"] = EMUtil::EM_FLOAT;
00172                         }
00173                         else if(!strncmp(datatype, "short", 5)) {
00174                                 dt = EMUtil::EM_SHORT;
00175                                 dict["datatype"] = EMUtil::EM_SHORT;
00176                         }
00177                         else if(!strncmp(datatype, "byte", 4)) {
00178                                 dt = EMUtil::EM_CHAR;
00179                                 dict["datatype"] = EMUtil::EM_CHAR;
00180                         }
00181                         else {
00182                                 fprintf(stderr,"AmiraIO::read_header: data type \"%s\" is not supported yet\n", datatype);
00183                                 return -1;
00184                         }
00185                 }
00186         } while (! ( ll[0]=='@' && ll[1]=='1') );
00187 
00188         EXITFUNC;
00189         return 0;
00190 
00191 }
00192 
00193 int AmiraIO::write_header(const Dict & dict, int image_index, const Region*, EMUtil::EMDataType, bool)
00194 {
00195         ENTERFUNC;
00196         int err = 0;
00197 
00198         check_write_access(rw_mode, image_index, 1);
00199 
00200         nx = dict["nx"];
00201         ny = dict["ny"];
00202         nz = dict["nz"];
00203 
00204         float xorigin = 0.0f;
00205         if(dict.has_key("origin_x")) xorigin = dict["origin_x"];
00206         float yorigin = 0.0f;
00207         if(dict.has_key("origin_y")) yorigin = dict["origin_y"];
00208         float zorigin = 0.0f;
00209         if(dict.has_key("origin_z")) zorigin = dict["origin_z"];
00210         float pixel = 0.0f;
00211         if(dict.has_key("apix_x")) pixel = dict["apix_x"];
00212 
00213         rewind(amira_file);
00214 
00215         string line1;
00216         if(ByteOrder::is_host_big_endian()) {
00217                 line1= "# AmiraMesh 3D BINARY 2.1\n\n";
00218         }
00219         else {
00220                 line1= "# AmiraMesh BINARY-LITTLE-ENDIAN 2.1\n\n";
00221         }
00222 
00223         string type = "float";
00224 
00225         if (fprintf(amira_file,line1.c_str()) <= 0) {
00226                 LOGERR("cannot write to AmiraMesh file '%s'", filename.c_str());
00227                 err = 1;
00228         }
00229         else {
00230                 fprintf(amira_file,"define Lattice %d %d %d\n\n",nx,ny,nz);
00231                 fprintf(amira_file,"Parameters {\n");
00232                 fprintf(amira_file, "\tContent \"%dx%dx%d %s, uniform coordinates\",\n", nx,ny,nz,type.c_str());
00233                 fprintf(amira_file, "\tCoordType \"uniform\",\n");
00234                 fprintf(amira_file,"\tBoundingBox %.2f %.2f %.2f %.2f %.2f %.2f\n}\n\n",xorigin,xorigin+pixel*(nx-1),yorigin,yorigin+pixel*(ny-1),zorigin,zorigin+pixel*(nz-1));
00235 
00236                 fprintf(amira_file, "Lattice { float ScalarField } @1\n\n# Data section follows\n@1\n");
00237         }
00238 
00239         EXITFUNC;
00240         return err;
00241 }
00242 
00243 int AmiraIO::read_data(float * rdata, int, const Region *, bool)
00244 {
00245         ENTERFUNC;
00246 
00247         size_t size = nx*ny*nz;
00248         switch(dt) {
00249         case EMUtil::EM_FLOAT:
00250                 fread(rdata,nx*nz,ny*sizeof(float),amira_file);
00251                 if( (is_big_endian && ByteOrder::is_host_big_endian()) && !(is_big_endian || ByteOrder::is_host_big_endian()) ) {
00252                         char tmpdata;
00253                         char *cdata=(char*)rdata;
00254                         for(size_t i=0;i<size;++i){
00255                                 //swap 0-3
00256                                 tmpdata=cdata[4*i+3];
00257                                 cdata[4*i+3]=cdata[4*i];
00258                                 cdata[4*i] = tmpdata;
00259                                 //swap 1-2
00260                                 tmpdata=cdata[4*i+2];
00261                                 cdata[4*i+2]=cdata[4*i+1];
00262                                 cdata[4*i+1] = tmpdata;
00263                         }
00264                 }
00265                 break;
00266         case EMUtil::EM_SHORT:
00267         {
00268                 short *datashort = (short*)malloc(sizeof(short)*nx*ny*nz);
00269                 fread(datashort,nx*nz,ny*sizeof(short),amira_file);
00270                 if( (is_big_endian && ByteOrder::is_host_big_endian()) && !(is_big_endian || ByteOrder::is_host_big_endian()) ) {
00271                         char tmpdata;
00272                         char *cdata=(char*)datashort;
00273                         for(size_t i=0;i<size;i++){
00274                                 //swap 0-1
00275                                 tmpdata=cdata[2*i+1];
00276                                 cdata[2*i+1]=cdata[2*i];
00277                                 cdata[2*i] = tmpdata;
00278                         }
00279                         for(size_t i=0; i<size; i++) rdata[i] = float(datashort[i]);
00280                         free(datashort);
00281                 }
00282         }
00283                 break;
00284         case EMUtil::EM_CHAR:
00285         {
00286                 char *databyte = (char*)malloc(sizeof(char)*nx*ny*nz);
00287                 fread(databyte,nx*nz,ny*sizeof(char),amira_file);
00288                 for(size_t i=0; i<size; i++) rdata[i] = float(databyte[i]);
00289                 free(databyte);
00290         }
00291                 break;
00292         default:
00293                 fprintf(stderr,"AmiraIO::read_data: data type is not supported yet\n");
00294                 return -1;
00295         }
00296 
00297         EXITFUNC;
00298         return 0;
00299 }
00300 
00301 int AmiraIO::write_data(float *data, int image_index, const Region*, EMUtil::EMDataType, bool)
00302 {
00303         ENTERFUNC;
00304 
00305         check_write_access(rw_mode, image_index, 1, data);
00306 //      ByteOrder::become_big_endian(data, nx * ny * nz);
00307 
00308         if (fwrite(data, nx * nz, ny * sizeof(float), amira_file) != ny * sizeof(float)) {
00309                 throw ImageWriteException(filename, "incomplete file write in AmiraMesh file");
00310         }
00311 
00312         EXITFUNC;
00313         return 0;
00314 }
00315 
00316 void AmiraIO::flush()
00317 {
00318         fflush(amira_file);
00319 }
00320 
00321 bool AmiraIO::is_complex_mode()
00322 {
00323         return false;
00324 }
00325 
00326 bool AmiraIO::is_image_big_endian()
00327 {
00328         init();
00329         return is_big_endian;
00330 }
00331 

Generated on Sat Nov 21 02:19:14 2009 for EMAN2 by  doxygen 1.5.6