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 image_index = 0;
00119 check_read_access(image_index);
00120
00121 int xlen = 0, ylen = 0, zlen = 0;
00122 EMUtil::get_region_dims(area, efh.nx, &xlen, efh.ny, &ylen, efh.nz, &zlen);
00123
00124 dict["nx"] = xlen;
00125 dict["ny"] = ylen;
00126 dict["nz"] = zlen;
00127
00128 dict["datatype"] = EMUtil::EM_FLOAT;
00129 dict["pixel"] = efh.pixel;
00130
00131 off_t imgsize = (off_t)efh.nx * (off_t)efh.ny * (off_t)efh.nz * (off_t)sizeof(float) + (off_t)sizeof(EmimImageHeader);
00132 off_t offset = (off_t)sizeof(EmimFileHeader) + imgsize * (off_t)image_index;
00133
00134 portable_fseek(emim_file, offset, SEEK_SET);
00135
00136 EmimImageHeader eih;
00137 fread(&eih, sizeof(EmimImageHeader), 1, emim_file);
00138
00139 int n = eih.mgnum;
00140 become_host_endian(&n);
00141
00142 char mgnum[32];
00143 sprintf(mgnum, "%d", n);
00144
00145 dict["micrograph_id"] = mgnum;
00146 EXITFUNC;
00147 return 0;
00148
00149 }
00150
00151 int EmimIO::write_header(const Dict &, int, const Region* , EMUtil::EMDataType, bool)
00152 {
00153 ENTERFUNC;
00154 LOGWARN("EMIM write header is not supported.");
00155 EXITFUNC;
00156 return 1;
00157 }
00158
00159 int EmimIO::read_data(float *data, int image_index, const Region * area, bool)
00160 {
00161 ENTERFUNC;
00162 int err = 0;
00163
00164 image_index = 0;
00165 check_read_access(image_index, data);
00166
00167 off_t imgsize = (off_t)efh.nx * (off_t)efh.ny * (off_t)efh.nz * (off_t)sizeof(float) + (off_t)sizeof(EmimImageHeader);
00168 off_t offset = (off_t)sizeof(EmimFileHeader) + imgsize * (off_t)(image_index+1);
00169 portable_fseek(emim_file, offset, SEEK_SET);
00170
00171 unsigned char *cdata = (unsigned char *) data;
00172 EMUtil::process_region_io(cdata, emim_file, READ_ONLY, 0, sizeof(float),
00173 efh.nx, efh.ny, efh.nz, area);
00174
00175 become_host_endian(data, efh.nx * efh.ny * efh.nz);
00176
00177
00178 EXITFUNC;
00179 return err;
00180 }
00181
00182 int EmimIO::write_data(float *, int, const Region* , EMUtil::EMDataType, bool)
00183 {
00184 ENTERFUNC;
00185 LOGWARN("EMIM write data is not supported.");
00186 EXITFUNC;
00187 return 1;
00188 }
00189
00190 void EmimIO::flush()
00191 {
00192 }
00193
00194 bool EmimIO::is_complex_mode()
00195 {
00196 init();
00197 if (efh.flag & EMIM_COMPLEX) {
00198 return true;
00199 }
00200 return false;
00201 }
00202
00203 bool EmimIO::is_image_big_endian()
00204 {
00205 init();
00206 return is_big_endian;
00207 }
00208
00209 int EmimIO::get_nimg()
00210 {
00211 init();
00212 return efh.count;
00213 }