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 "gatan2io.h"
00037 #include "geometry.h"
00038 #include "portable_fileio.h"
00039 #include <cstring>
00040
00041 using namespace EMAN;
00042
00043 Gatan2IO::Gatan2IO(const string & file, IOMode rw)
00044 : filename(file), rw_mode(rw), gatan2_file(0), initialized(false)
00045 {
00046 is_big_endian = ByteOrder::is_host_big_endian();
00047 memset(&gatanh, 0, sizeof(Gatan2Header));
00048 }
00049
00050 Gatan2IO::~Gatan2IO()
00051 {
00052 if (gatan2_file) {
00053 fclose(gatan2_file);
00054 gatan2_file = 0;
00055 }
00056 }
00057
00058 void Gatan2IO::init()
00059 {
00060 ENTERFUNC;
00061
00062 if (initialized) {
00063 return;
00064 }
00065
00066 initialized = true;
00067
00068 bool is_new_file = false;
00069 gatan2_file = sfopen(filename, rw_mode, &is_new_file);
00070
00071 if (!is_new_file) {
00072 if (fread(&gatanh, sizeof(Gatan2Header), 1, gatan2_file) != 1) {
00073 throw ImageReadException(filename, "Gatan2 Header");
00074 }
00075
00076 if (!is_valid(&gatanh)) {
00077 throw ImageReadException(filename, "invalid Gatan2 file");
00078 }
00079
00080 is_big_endian = ByteOrder::is_data_big_endian(&gatanh.len);
00081 become_host_endian((short *) &gatanh, sizeof(Gatan2Header) / sizeof(short));
00082 }
00083 EXITFUNC;
00084 }
00085
00086 bool Gatan2IO::is_valid(const void *first_block)
00087 {
00088 ENTERFUNC;
00089 bool result = false;
00090
00091 if (!first_block) {
00092 result = false;
00093 }
00094 else {
00095 const short *data = static_cast < const short *>(first_block);
00096 short len = data[5];
00097 short type = data[6];
00098
00099 bool data_big_endian = ByteOrder::is_data_big_endian(&len);
00100
00101 if (data_big_endian != ByteOrder::is_host_big_endian()) {
00102 ByteOrder::swap_bytes(&len);
00103 ByteOrder::swap_bytes(&type);
00104 }
00105
00106 int double_size = sizeof(double);
00107 if (len > 0 && len <= double_size && type > 0 && type <= GATAN2_INVALID) {
00108 result = true;
00109 }
00110 }
00111 EXITFUNC;
00112 return result;
00113 }
00114
00115 int Gatan2IO::read_header(Dict & dict, int image_index, const Region * area, bool)
00116 {
00117 ENTERFUNC;
00118
00119 image_index = 0;
00120 check_read_access(image_index);
00121
00122 if (is_complex_mode()) {
00123 throw ImageReadException(filename, "Cannot read complex Gatan2 files");
00124 }
00125 else {
00126 check_region(area, IntSize(gatanh.nx, gatanh.ny));
00127
00128 int xlen = 0, ylen = 0;
00129 EMUtil::get_region_dims(area, gatanh.nx, &xlen, gatanh.ny, &ylen);
00130
00131 dict["nx"] = xlen;
00132 dict["ny"] = ylen;
00133 dict["nz"] = 1;
00134 dict["datatype"] = to_em_datatype(gatanh.type);
00135 }
00136
00137 EXITFUNC;
00138 return 0;
00139 }
00140
00141 int Gatan2IO::write_header(const Dict &, int, const Region* , EMUtil::EMDataType, bool)
00142 {
00143 ENTERFUNC;
00144 LOGWARN("Gatan2 write is not supported.");
00145 EXITFUNC;
00146 return 1;
00147 }
00148
00149 int Gatan2IO::read_data(float *data, int image_index, const Region * area, bool )
00150 {
00151 ENTERFUNC;
00152
00153 image_index = 0;
00154 check_read_access(image_index, data);
00155
00156 if (is_complex_mode()) {
00157 throw ImageReadException(filename, "Cannot read complex Gatan2 files");
00158 }
00159
00160 check_region(area, IntSize(gatanh.nx, gatanh.ny));
00161
00162 portable_fseek(gatan2_file, sizeof(Gatan2Header), SEEK_SET);
00163
00164 #if 0
00165 if (fread(data, gatanh.nx * gatanh.len, gatanh.ny, gatan2_file) != (unsigned int) gatanh.ny) {
00166 LOGDEBUG("Data read incomplete in Gatan file '%s'", filename.c_str());
00167 return 1;
00168 }
00169 #endif
00170
00171 int size = gatanh.nx * gatanh.ny;
00172 short *sdata = (short *) data;
00173 unsigned char *cdata = (unsigned char *) data;
00174 int *ldata = (int *) data;
00175
00176 EMUtil::process_region_io(cdata, gatan2_file, READ_ONLY, image_index, gatanh.len,
00177 gatanh.nx, gatanh.ny, 1, area);
00178
00179 switch (gatanh.type) {
00180 case GATAN2_SHORT:
00181 become_host_endian((short *) data, size);
00182 for (int i = size - 1; i >= 0; i--) {
00183 data[i] = static_cast < float >(sdata[i]);
00184 }
00185 break;
00186 case GATAN2_FLOAT:
00187 become_host_endian(data, size);
00188 break;
00189 case GATAN2_CHAR:
00190 for (int i = size - 1; i >= 0; i--) {
00191 data[i] = static_cast < float >(cdata[i]);
00192 }
00193 break;
00194 case GATAN2_INT:
00195 become_host_endian((int *) data, size);
00196 for (int i = size - 1; i >= 0; i--) {
00197 data[i] = static_cast < float >(ldata[i]);
00198 }
00199 break;
00200 default:
00201 throw ImageReadException(filename, "unsupported Gatan2 data type");
00202 }
00203 EXITFUNC;
00204 return 0;
00205 }
00206
00207 int Gatan2IO::write_data(float *, int, const Region*, EMUtil::EMDataType, bool)
00208 {
00209 ENTERFUNC;
00210 LOGWARN("Gatan2 write is not supported.");
00211 EXITFUNC;
00212 return 1;
00213 }
00214
00215 void Gatan2IO::flush()
00216 {
00217 }
00218
00219 bool Gatan2IO::is_complex_mode()
00220 {
00221 init();
00222 if (gatanh.type == GATAN2_COMPLEX || gatanh.type == GATAN2_PACKED_COMPLEX) {
00223 return true;
00224 }
00225 return false;
00226 }
00227
00228 bool Gatan2IO::is_image_big_endian()
00229 {
00230 init();
00231 return is_big_endian;
00232 }
00233
00234
00235
00236 int Gatan2IO::to_em_datatype(int gatan_type)
00237 {
00238 switch (gatan_type) {
00239 case GATAN2_SHORT:
00240 return EMUtil::EM_SHORT;
00241
00242 case GATAN2_FLOAT:
00243 return EMUtil::EM_FLOAT;
00244
00245 case GATAN2_CHAR:
00246 return EMUtil::EM_CHAR;
00247
00248 case GATAN2_INT:
00249 return EMUtil::EM_INT;
00250 }
00251
00252 return EMUtil::EM_UNKNOWN;
00253 }