00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <cstring>
00037 #include "emimio.h"
00038 #include "portable_fileio.h"
00039
00040 using namespace EMAN;
00041
00042 const char *EmimIO::MAGIC = "EMIM";
00043
00044 EmimIO::EmimIO(const string & file, IOMode rw)
00045 : filename(file), rw_mode(rw), emim_file(0), initialized(false)
00046 {
00047 is_big_endian = ByteOrder::is_host_big_endian();
00048 memset(&efh, 0, sizeof(EmimFileHeader));
00049 }
00050
00051 EmimIO::~EmimIO()
00052 {
00053 if (emim_file) {
00054 fclose(emim_file);
00055 emim_file = 0;
00056 }
00057 }
00058
00059 void EmimIO::init()
00060 {
00061 ENTERFUNC;
00062 if (initialized) {
00063 return;
00064 }
00065
00066 initialized = true;
00067 bool is_new_file = false;
00068 emim_file = sfopen(filename, rw_mode, &is_new_file);
00069
00070 if (!is_new_file) {
00071 if (fread(&efh, sizeof(EmimFileHeader), 1, emim_file) != 1) {
00072 throw ImageReadException(filename, "EMIM header");
00073 }
00074
00075 if (!is_valid(&efh)) {
00076 throw ImageReadException(filename, "invalid EMIM file");
00077 }
00078
00079 become_host_endian((int *) &efh, NUM_INT_IN_FILE_HEADER);
00080 is_big_endian = ByteOrder::is_data_big_endian(&efh.count);
00081 }
00082
00083 EXITFUNC;
00084 }
00085
00086 bool EmimIO::is_valid(const void *first_block)
00087 {
00088 ENTERFUNC;
00089
00090 if (!first_block) {
00091 return false;
00092 }
00093
00094 const char *data = static_cast < const char *>(first_block);
00095 const int *idata = static_cast < const int *>(first_block);
00096 int count = idata[2];
00097
00098 if (strncmp(data, MAGIC, sizeof(MAGIC)) == 0) {
00099 bool data_big_endian = ByteOrder::is_data_big_endian(&count);
00100
00101 if (data_big_endian != ByteOrder::is_host_big_endian()) {
00102 ByteOrder::swap_bytes(&count);
00103 }
00104
00105 if (count >= 0 && count <= 1 << 20) {
00106 return true;
00107 }
00108 }
00109 EXITFUNC;
00110 return false;
00111 }
00112
00113 int EmimIO::read_header(Dict & dict, int image_index, const Region * area, bool)
00114 {
00115 ENTERFUNC;
00116
00117
00118 if(image_index == -1) {
00119 image_index = 0;
00120 }
00121 image_index = 0;
00122 check_read_access(image_index);
00123
00124 int xlen = 0, ylen = 0, zlen = 0;
00125 EMUtil::get_region_dims(area, efh.nx, &xlen, efh.ny, &ylen, efh.nz, &zlen);
00126
00127 dict["nx"] = xlen;
00128 dict["ny"] = ylen;
00129 dict["nz"] = zlen;
00130
00131 dict["datatype"] = EMUtil::EM_FLOAT;
00132 dict["pixel"] = efh.pixel;
00133
00134 off_t imgsize = (off_t)efh.nx * (off_t)efh.ny * (off_t)efh.nz * (off_t)sizeof(float) + (off_t)sizeof(EmimImageHeader);
00135 off_t offset = (off_t)sizeof(EmimFileHeader) + imgsize * (off_t)image_index;
00136
00137 portable_fseek(emim_file, offset, SEEK_SET);
00138
00139 EmimImageHeader eih;
00140 fread(&eih, sizeof(EmimImageHeader), 1, emim_file);
00141
00142 int n = eih.mgnum;
00143 become_host_endian(&n);
00144
00145 char mgnum[32];
00146 sprintf(mgnum, "%d", n);
00147
00148 dict["micrograph_id"] = mgnum;
00149 EXITFUNC;
00150 return 0;
00151
00152 }
00153
00154 int EmimIO::write_header(const Dict &, int, const Region* , EMUtil::EMDataType, bool)
00155 {
00156 ENTERFUNC;
00157 LOGWARN("EMIM write header is not supported.");
00158 EXITFUNC;
00159 return 1;
00160 }
00161
00162 int EmimIO::read_data(float *data, int image_index, const Region * area, bool)
00163 {
00164 ENTERFUNC;
00165 int err = 0;
00166
00167 image_index = 0;
00168 check_read_access(image_index, data);
00169
00170 off_t imgsize = (off_t)efh.nx * (off_t)efh.ny * (off_t)efh.nz * (off_t)sizeof(float) + (off_t)sizeof(EmimImageHeader);
00171 off_t offset = (off_t)sizeof(EmimFileHeader) + imgsize * (off_t)(image_index+1);
00172 portable_fseek(emim_file, offset, SEEK_SET);
00173
00174 unsigned char *cdata = (unsigned char *) data;
00175 EMUtil::process_region_io(cdata, emim_file, READ_ONLY, 0, sizeof(float),
00176 efh.nx, efh.ny, efh.nz, area);
00177
00178 become_host_endian(data, efh.nx * efh.ny * efh.nz);
00179
00180
00181 EXITFUNC;
00182 return err;
00183 }
00184
00185 int EmimIO::write_data(float *, int, const Region* , EMUtil::EMDataType, bool)
00186 {
00187 ENTERFUNC;
00188 LOGWARN("EMIM write data is not supported.");
00189 EXITFUNC;
00190 return 1;
00191 }
00192
00193 void EmimIO::flush()
00194 {
00195 }
00196
00197 bool EmimIO::is_complex_mode()
00198 {
00199 init();
00200 if (efh.flag & EMIM_COMPLEX) {
00201 return true;
00202 }
00203 return false;
00204 }
00205
00206 bool EmimIO::is_image_big_endian()
00207 {
00208 init();
00209 return is_big_endian;
00210 }
00211
00212 int EmimIO::get_nimg()
00213 {
00214 init();
00215 return efh.count;
00216 }