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 "icosio.h"
00038 #include "portable_fileio.h"
00039 #include "geometry.h"
00040
00041 using namespace EMAN;
00042
00043
00044 IcosIO::IcosIO(const string & file, IOMode rw)
00045 : filename(file), rw_mode(rw), icos_file(0), initialized(false)
00046 {
00047 is_big_endian = ByteOrder::is_host_big_endian();
00048 is_new_file = false;
00049 memset(&icosh, 0, sizeof(IcosHeader));
00050 }
00051
00052 IcosIO::~IcosIO()
00053 {
00054 if (icos_file) {
00055 fclose(icos_file);
00056 icos_file = 0;
00057 }
00058 }
00059
00060 void IcosIO::init()
00061 {
00062 ENTERFUNC;
00063 if (initialized) {
00064 return ;
00065 }
00066
00067 initialized = true;
00068 icos_file = sfopen(filename, rw_mode, &is_new_file);
00069
00070 if (!is_new_file) {
00071 if (fread(&icosh, sizeof(IcosHeader), 1, icos_file) != 1) {
00072 throw ImageReadException(filename, "ICOS header");
00073 }
00074
00075 if (!is_valid(&icosh)) {
00076 throw ImageReadException(filename, "invalid ICOS file");
00077 }
00078 is_big_endian = ByteOrder::is_data_big_endian(&icosh.stamp);
00079 become_host_endian((int *) &icosh, sizeof(IcosHeader) / sizeof(int));
00080 }
00081 EXITFUNC;
00082 }
00083
00084 bool IcosIO::is_valid(const void *first_block)
00085 {
00086 ENTERFUNC;
00087 bool result = false;
00088 if (!first_block) {
00089 result = false;
00090 }
00091 else {
00092 const int *data = static_cast < const int *>(first_block);
00093 int stamp = data[0];
00094 int stamp1 = data[19];
00095 int stamp2 = data[20];
00096 int stamp3 = data[26];
00097
00098 bool data_big_endian = ByteOrder::is_data_big_endian(&stamp);
00099
00100 if (data_big_endian != ByteOrder::is_host_big_endian()) {
00101 ByteOrder::swap_bytes(&stamp);
00102 ByteOrder::swap_bytes(&stamp1);
00103 ByteOrder::swap_bytes(&stamp2);
00104 ByteOrder::swap_bytes(&stamp3);
00105 }
00106
00107 if (stamp == STAMP && stamp1 == STAMP1 && stamp2 == STAMP2 && stamp3 == STAMP3) {
00108 result = true;
00109 }
00110 }
00111 EXITFUNC;
00112 return result;
00113 }
00114
00115 int IcosIO::read_header(Dict & dict, int image_index, const Region * area, bool)
00116 {
00117 ENTERFUNC;
00118
00119
00120 if(image_index == -1) {
00121 image_index = 0;
00122 }
00123
00124 if(image_index != 0) {
00125 throw ImageReadException(filename, "no stack allowed for MRC image. For take 2D slice out of 3D image, read the 3D image first, then use get_clip().");
00126 }
00127
00128 init();
00129
00130 check_region(area, IntSize(icosh.nx, icosh.ny, icosh.nz),false,false);
00131
00132 int xlen = 0, ylen = 0, zlen = 0;
00133 EMUtil::get_region_dims(area, icosh.nx, &xlen, icosh.ny, &ylen, icosh.nz, &zlen);
00134
00135 dict["nx"] = xlen;
00136 dict["ny"] = ylen;
00137 dict["nz"] = zlen;
00138 dict["datatype"] = EMUtil::EM_FLOAT;
00139 dict["minimum"] = icosh.min;
00140 dict["maximum"] = icosh.max;
00141
00142 EXITFUNC;
00143 return 0;
00144 }
00145
00146 int IcosIO::write_header(const Dict & dict, int image_index, const Region* ,
00147 EMUtil::EMDataType, bool)
00148 {
00149 ENTERFUNC;
00150 int err = 0;
00151
00152 if(image_index == -1) {
00153 image_index = 0;
00154 }
00155 if(image_index != 0) {
00156 throw ImageWriteException(filename, "ICOS file does not support stack.");
00157 }
00158 check_write_access(rw_mode, image_index, 1);
00159
00160 icosh.stamp = STAMP;
00161 icosh.stamp1 = STAMP1;
00162 icosh.stamp2 = STAMP2;
00163 icosh.stamp3 = STAMP3;
00164
00165 icosh.nx = dict["nx"];
00166 icosh.ny = dict["ny"];
00167 icosh.nz = dict["nz"];
00168
00169 icosh.min = dict["minimum"];
00170 icosh.max = dict["maximum"];
00171
00172 rewind(icos_file);
00173
00174 if (fwrite(&icosh, sizeof(IcosHeader), 1, icos_file) != 1) {
00175 throw ImageWriteException(filename, "ICOS header write");
00176 }
00177
00178 EXITFUNC;
00179 return err;
00180 }
00181
00182 int IcosIO::read_data(float *data, int image_index, const Region * area, bool)
00183 {
00184 ENTERFUNC;
00185
00186
00187 image_index = 0;
00188 check_read_access(image_index, data);
00189 check_region(area, IntSize(icosh.nx, icosh.ny, icosh.nz),false,false);
00190
00191 portable_fseek(icos_file, sizeof(IcosHeader), SEEK_SET);
00192
00193 EMUtil::process_region_io((unsigned char *) data, icos_file,
00194 READ_ONLY, image_index,
00195 sizeof(float), icosh.nx, icosh.ny, icosh.nz,
00196 area, false, EMUtil::IMAGE_ICOS, sizeof(int), sizeof(int));
00197
00198 int xlen = 0, ylen = 0, zlen = 0;
00199 EMUtil::get_region_dims(area, icosh.nx, &xlen, icosh.ny, &ylen, icosh.nz, &zlen);
00200 become_host_endian(data, xlen * ylen * zlen);
00201
00202
00203 EXITFUNC;
00204 return 0;
00205 }
00206
00207 int IcosIO::write_data(float *data, int image_index, const Region* area,
00208 EMUtil::EMDataType, bool)
00209 {
00210 ENTERFUNC;
00211
00212 image_index = 0;
00213 check_write_access(rw_mode, image_index, 1, data);
00214 portable_fseek(icos_file, sizeof(IcosHeader), SEEK_SET);
00215
00216 EMUtil::process_region_io(data, icos_file, rw_mode, image_index,
00217 sizeof(float), icosh.nx, icosh.ny, icosh.nz, area,
00218 false, EMUtil::IMAGE_ICOS, sizeof(int), sizeof(int));
00219
00220 #if 0
00221 size_t float_size = sizeof(float);
00222 int nx = icosh.nx;
00223 float *buf = new float[nx + 2];
00224 buf[0] = (float)float_size * nx;
00225 buf[nx + 1] = buf[0];
00226 int nrows = icosh.ny * icosh.nz;
00227
00228 int row_size = (nx + 2) * float_size;
00229
00230
00231 for (int j = 0; j < nrows; j++) {
00232 memcpy(&buf[1], &data[nx * j], nx * float_size);
00233 if (fwrite(buf, row_size, 1, icos_file) != 1) {
00234 throw ImageWriteException(filename, "ICOS data");
00235 }
00236 }
00237
00238 if( buf )
00239 {
00240 delete[]buf;
00241 buf = 0;
00242 }
00243 #endif
00244 EXITFUNC;
00245 return 0;
00246 }
00247
00248 void IcosIO::flush()
00249 {
00250 fflush(icos_file);
00251 }
00252
00253 bool IcosIO::is_complex_mode()
00254 {
00255 return false;
00256 }
00257
00258 bool IcosIO::is_image_big_endian()
00259 {
00260 init();
00261 return is_big_endian;
00262 }
00263