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 "serio.h"
00037 #include "util.h"
00038 #include "portable_fileio.h"
00039
00040 #include <cassert>
00041
00042 using namespace EMAN;
00043
00044 static const short SER_BYTE_ORDER = 0x4949;
00045 static const short SER_SERIES_ID = 0x0197;
00046 static const short SER_SERIES_VERSION = 0x0210;
00047 static const int ValidNumberElementsOffset = 18;
00048
00049 SerIO::SerIO(const string & file, IOMode rw) :
00050 filename(file), rw_mode(rw), serfile(0), initialized(false),
00051 is_new_file(false), data_offset_array(0),tag_offset_array(0),
00052 nimg(0), nx(0), ny(0), nz(0), datatypeid(0), datamode(0)
00053 {
00054 }
00055
00056 SerIO::~SerIO()
00057 {
00058 if (serfile) {
00059 fclose(serfile);
00060 serfile = 0;
00061 }
00062
00063 if (data_offset_array) {
00064 delete [] data_offset_array;
00065 data_offset_array = 0;
00066 }
00067
00068 if (tag_offset_array) {
00069 delete [] tag_offset_array;
00070 tag_offset_array = 0;
00071 }
00072 }
00073
00074 void SerIO::init()
00075 {
00076 ENTERFUNC;
00077
00078 if (initialized) {
00079 return;
00080 }
00081
00082 initialized = true;
00083 serfile = sfopen(filename, rw_mode, &is_new_file);
00084
00085 if (!is_new_file) {
00086 if (fread(&serh, sizeof(SerHeader), 1, serfile) != 1) {
00087 throw ImageReadException(filename, "SER header");
00088 }
00089
00090 if (!is_valid(&serh)) {
00091 throw ImageReadException(filename, "invalid SER");
00092 }
00093 }
00094
00095 EXITFUNC;
00096 }
00097
00098 bool SerIO::is_valid(const void *first_block)
00099 {
00100 ENTERFUNC;
00101
00102 if (!first_block) {
00103 return false;
00104 }
00105
00106 const short *data = static_cast < const short *>(first_block);
00107 short ByteOrder = data[0];
00108 short SeriesID = data[1];
00109
00110 if(ByteOrder != 0x4949 || SeriesID != 0x0197) {
00111 return false;
00112 }
00113
00114 EXITFUNC;
00115 return true;
00116 }
00117
00118 int SerIO::read_header(Dict & dict, int image_index, const Region * area, bool is_3d)
00119 {
00120 ENTERFUNC;
00121 init();
00122 rewind(serfile);
00123
00124 short hitem1[3];
00125 if (fread(hitem1, sizeof(short), 3, serfile) != 3) {
00126 throw ImageReadException(filename, "SER header");
00127 }
00128
00129 dict["SER.ByteOrder"] = hitem1[0];
00130 dict["SER.SeriesID"] = hitem1[1];
00131 dict["SER.SeriesVersion"] = hitem1[2];
00132
00133 if((hitem1[0]!=SER_BYTE_ORDER) || (hitem1[1]!=SER_SERIES_ID) || (hitem1[2]!=SER_SERIES_VERSION) ) {
00134 throw ImageReadException(filename, "SER header");
00135 }
00136
00137 int hitem2[6];
00138 if (fread(hitem2, sizeof(int), 6, serfile) != 6) {
00139 throw ImageReadException(filename, "SER header");
00140 }
00141
00142 dict["SER.DataTypeID"] = hitem2[0];
00143 dict["SER.TagTypeID"] = hitem2[1];
00144 dict["SER.TotalNumberElements"] = hitem2[2];
00145 dict["SER.ValidNumberElements"] = hitem2[3];
00146 dict["SER.OffsetArrayOffset"] = hitem2[4];
00147 dict["SER.NumberDimensions"] = hitem2[5];
00148
00149 nimg = (int)dict["SER.ValidNumberElements"];
00150
00151 if(image_index >= (int)dict["SER.ValidNumberElements"]) {
00152 throw ImageReadException(filename, "Image index out of bound");
00153 }
00154
00155 for(int idx=0; idx<(int)dict["SER.NumberDimensions"]; idx++) {
00156 read_dim_arr(dict, idx);
00157 }
00158
00159 long pos = ftell(serfile);
00160 assert(pos == (int)dict["SER.OffsetArrayOffset"]);
00161
00162 int tot = (int)dict["SER.TotalNumberElements"];
00163
00164 data_offset_array = new int[tot];
00165 if (fread(data_offset_array, sizeof(int), tot, serfile) != (unsigned int)tot) {
00166 throw ImageReadException(filename, "SER header");
00167 }
00168
00169 tag_offset_array = new int[tot];
00170 if (fread(tag_offset_array, sizeof(int), tot, serfile) != (unsigned int)tot) {
00171 throw ImageReadException(filename, "SER header");
00172 }
00173
00174 this->datatypeid = (int)dict["SER.DataTypeID"];
00175
00176 int dataoffset = data_offset_array[image_index];
00177 portable_fseek(serfile, dataoffset, SEEK_SET);
00178
00179
00180 read_data_element(dict);
00181
00182 int tagoffset = tag_offset_array[image_index];
00183 portable_fseek(serfile, tagoffset, SEEK_SET);
00184
00185
00186 read_data_tag(dict);
00187
00188 EXITFUNC;
00189 return 0;
00190 }
00191
00192 int SerIO::write_header(const Dict & dict, int image_index, const Region* area,
00193 EMUtil::EMDataType filestoragetype, bool use_host_endian)
00194 {
00195 ENTERFUNC;
00196
00197 throw ImageWriteException(filename, "SER Writing not supported");
00198
00199 EXITFUNC;
00200 return 0;
00201 }
00202
00203 int SerIO::read_data(float *rdata, int image_index, const Region *, bool )
00204 {
00205 ENTERFUNC;
00206
00207 if(!data_offset_array) {
00208 throw ImageReadException(filename, "SER header, empty DataOffsetarray");
00209 }
00210
00211 size_t size = (size_t)nx * ny * nz;
00212 int data_offset = data_offset_array[image_index];
00213
00214 size_t i;
00215 unsigned char * puchar = 0;
00216 char * pchar = 0;
00217 int * pint = 0;
00218 unsigned int * puint = 0;
00219 short * pshort = 0;
00220 unsigned short * pushort = 0;
00221 double * pdouble = 0;
00222 switch(this->datatypeid) {
00223 case oneD:
00224 portable_fseek(serfile, data_offset+26, SEEK_SET);
00225 break;
00226 case twoD:
00227 portable_fseek(serfile, data_offset+50, SEEK_SET);
00228 break;
00229 default:
00230 throw ImageReadException(filename, "SER header, wrong DataTypeID");
00231 }
00232
00233 switch(this->datamode) {
00234 case SER_UCHAR:
00235 puchar = new unsigned char[size];
00236 if (fread(puchar, sizeof(unsigned char), size, serfile) != size) {
00237 throw ImageReadException(filename, "SER data");
00238 }
00239 for (i = 0; i<size; ++i) {
00240 rdata[i] = static_cast<float>(puchar[i]);
00241 }
00242 delete [] puchar;
00243 break;
00244 case SER_USHORT:
00245 pushort = new unsigned short[size];
00246 if (fread(pushort, sizeof(unsigned short), size, serfile) != size) {
00247 throw ImageReadException(filename, "SER data");
00248 }
00249 for (i = 0; i<size; ++i) {
00250 rdata[i] = static_cast<float>(pushort[i]);
00251 }
00252 delete [] pushort;
00253 break;
00254 case SER_UINT:
00255 puint = new unsigned int[size];
00256 if (fread(puint, sizeof(unsigned int), size, serfile) != size) {
00257 throw ImageReadException(filename, "SER data");
00258 }
00259 for (i = 0; i<size; ++i) {
00260 rdata[i] = static_cast<float>(puint[i]);
00261 }
00262 delete [] puint;
00263 break;
00264 case SER_CHAR:
00265 pchar = new char[size];
00266 if (fread(pchar, sizeof(unsigned char), size, serfile) != size) {
00267 throw ImageReadException(filename, "SER data");
00268 }
00269 for (i = 0; i<size; ++i) {
00270 rdata[i] = static_cast<float>(pchar[i]);
00271 }
00272 delete [] pchar;
00273 break;
00274 case SER_SHORT:
00275 pshort = new short[size];
00276 if (fread(pshort, sizeof(short), size, serfile) != size) {
00277 throw ImageReadException(filename, "SER data");
00278 }
00279 for (i = 0; i<size; ++i) {
00280 rdata[i] = static_cast<float>(pshort[i]);
00281 }
00282 delete [] pshort;
00283 break;
00284 case SER_INT:
00285 pint = new int[size];
00286 if (fread(pint, sizeof(int), size, serfile) != size) {
00287 throw ImageReadException(filename, "SER data");
00288 }
00289 for (i = 0; i<size; ++i) {
00290 rdata[i] = static_cast<float>(pint[i]);
00291 }
00292 delete [] pint;
00293 break;
00294 case SER_FLOAT:
00295 if (fread(rdata, sizeof(float), size, serfile) != size) {
00296 throw ImageReadException(filename, "SER data");
00297 }
00298 break;
00299 case SER_DOUBLE:
00300 pdouble = new double[size];
00301 if (fread(pdouble, sizeof(double), size, serfile) != size) {
00302 throw ImageReadException(filename, "SER data");
00303 }
00304 for (i = 0; i<size; ++i) {
00305 rdata[i] = static_cast<float>(pdouble[i]);
00306 }
00307 delete [] pdouble;
00308 break;
00309 case SER_COMPLEX8:
00310 case SER_COMPLEX16:
00311 throw ImageReadException(filename, "complex data not supported.");
00312 break;
00313 default:
00314 throw ImageReadException(filename, "Unknown data value type");
00315 }
00316
00317 EXITFUNC;
00318 return 0;
00319 }
00320
00321 int SerIO::write_data(float *data, int image_index, const Region* area,
00322 EMUtil::EMDataType, bool use_host_endian)
00323 {
00324 ENTERFUNC;
00325
00326 throw ImageWriteException(filename, "SER Writing not supported");
00327
00328 EXITFUNC;
00329 return 0;
00330 }
00331
00332 bool SerIO::is_complex_mode()
00333 {
00334 return false;
00335 }
00336
00337 void SerIO::flush()
00338 {
00339 fflush(serfile);
00340 }
00341
00342 bool SerIO::is_image_big_endian()
00343 {
00344 return false;
00345 }
00346
00347 int SerIO::get_nimg() {
00348 init();
00349
00350 portable_fseek(serfile, ValidNumberElementsOffset, SEEK_SET);
00351 int nimg;
00352 if (fread(&nimg, sizeof(int), 1, serfile) != 1) {
00353 throw ImageReadException(filename, "SER header");
00354 }
00355
00356 return nimg;
00357 }
00358
00359 void SerIO::read_dim_arr(Dict & dict, int idx)
00360 {
00361 int dimsize;
00362 if (fread(&dimsize, sizeof(int), 1, serfile) != 1) {
00363 throw ImageReadException(filename, "SER header");
00364 }
00365
00366 string sidx = Util::int2str(idx);
00367 dict["SER.DimensionSize"+sidx] = dimsize;
00368
00369 double hitem3[2];
00370 if (fread(hitem3, sizeof(double), 2, serfile) != 2) {
00371 throw ImageReadException(filename, "SER header");
00372 }
00373 dict["SER.CalibrationOffset"+sidx] = hitem3[0];
00374 dict["SER.CalibrationDelta"+sidx] = hitem3[1];
00375
00376 int celement;
00377 if (fread(&celement, sizeof(int), 1, serfile) != 1) {
00378 throw ImageReadException(filename, "SER header");
00379 }
00380 dict["SER.CalibrationElement"+sidx] = celement;
00381
00382 int desclen;
00383 if (fread(&desclen, sizeof(int), 1, serfile) != 1) {
00384 throw ImageReadException(filename, "SER header");
00385 }
00386 dict["SER.DescriptionLength"+sidx] = desclen;
00387
00388 if(desclen != 0) {
00389 char * descr = new char[desclen+1];
00390
00391 if (fread(descr, sizeof(char), desclen, serfile) != (unsigned int)desclen) {
00392 throw ImageReadException(filename, "SER header");
00393 }
00394 descr[desclen] = '\0';
00395 string sdescr(descr);
00396 dict["SER.Description"+sidx] = sdescr;
00397 delete [] descr;
00398 }
00399
00400 int unitslen;
00401 if (fread(&unitslen, sizeof(int), 1, serfile) != 1) {
00402 throw ImageReadException(filename, "SER header");
00403 }
00404 dict["SER.UnitsLength"+sidx] = unitslen;
00405
00406 if(unitslen != 0) {
00407 char * units = new char[unitslen+1];
00408
00409 if (fread(units, sizeof(int), unitslen, serfile) != (unsigned int)unitslen) {
00410 throw ImageReadException(filename, "SER header");
00411 }
00412 units[unitslen] = '\0';
00413 string sunits(units);
00414 dict["SER.Units"+sidx] = sunits;
00415 delete [] units;
00416 }
00417
00418 }
00419
00420 void SerIO::read_data_element(Dict & dict)
00421 {
00422 if(this->datatypeid == oneD) {
00423 double hitem4[2];
00424 if (fread(hitem4, sizeof(double), 2, serfile) != 2) {
00425 throw ImageReadException(filename, "SER header");
00426 }
00427 dict["SER.CalibrationOffset"] = hitem4[0];
00428 dict["SER.CalibrationDelta"] = hitem4[1];
00429
00430 int cali;
00431 if (fread(&cali, sizeof(int), 1, serfile) != 1) {
00432 throw ImageReadException(filename, "SER header");
00433 }
00434 dict["SER.CalibrationElement"] = cali;
00435
00436 short datatype;
00437 if (fread(&datatype, sizeof(short), 1, serfile) != 1) {
00438 throw ImageReadException(filename, "SER header");
00439 }
00440 dict["SER.DataType"] = datatype;
00441
00442 int arrlen;
00443 if (fread(&arrlen, sizeof(int), 1, serfile) != 1) {
00444 throw ImageReadException(filename, "SER header");
00445 }
00446 dict["nx"] = arrlen;
00447 dict["ny"] = 1;
00448 dict["nz"] = 1;
00449
00450 nx = arrlen;
00451 ny = 1;
00452 nz = 1;
00453 }
00454 else if(this->datatypeid == twoD) {
00455 double hitem4[2];
00456 if (fread(hitem4, sizeof(double), 2, serfile) != 2) {
00457 throw ImageReadException(filename, "SER header");
00458 }
00459 dict["SER.CalibrationOffsetX"] = hitem4[0];
00460 dict["SER.CalibrationDeltaX"] = hitem4[1];
00461
00462 int calix;
00463 if (fread(&calix, sizeof(int), 1, serfile) != 1) {
00464 throw ImageReadException(filename, "SER header");
00465 }
00466 dict["SER.CalibrationElementX"] = calix;
00467
00468 double hitem5[2];
00469 if (fread(hitem5, sizeof(double), 2, serfile) != 2) {
00470 throw ImageReadException(filename, "SER header");
00471 }
00472 dict["SER.CalibrationOffsetX"] = hitem5[0];
00473 dict["SER.CalibrationDeltaX"] = hitem5[1];
00474
00475 int caliy;
00476 if (fread(&caliy, sizeof(int), 1, serfile) != 1) {
00477 throw ImageReadException(filename, "SER header");
00478 }
00479 dict["SER.CalibrationElementY"] = caliy;
00480
00481 short datatype;
00482 if (fread(&datatype, sizeof(short), 1, serfile) != 1) {
00483 throw ImageReadException(filename, "SER header");
00484 }
00485 dict["SER.DataType"] = datatype;
00486 this->datamode = datatype;
00487
00488 int arrsize[2];
00489 if (fread(&arrsize, sizeof(int), 2, serfile) != 2) {
00490 throw ImageReadException(filename, "SER header");
00491 }
00492 dict["nx"] = arrsize[0];
00493 dict["ny"] = arrsize[1];
00494 dict["nz"] = 1;
00495
00496 nx = arrsize[0];
00497 ny = arrsize[1];
00498 nz = 1;
00499 }
00500 }
00501
00502 void SerIO::read_data_tag(Dict & dict)
00503 {
00504 int tag_type = (int)dict["SER.TagTypeID"];
00505 if( tag_type == timeOnly ) {
00506 short tagtype;
00507 if (fread(&tagtype, sizeof(short), 1, serfile) != 1) {
00508 throw ImageReadException(filename, "SER header");
00509 }
00510 assert((int)tagtype == tag_type);
00511
00512 int sertime;
00513 if (fread(&sertime, sizeof(int), 1, serfile) != 1) {
00514 throw ImageReadException(filename, "SER header");
00515 }
00516 dict["SER.Time"] = sertime;
00517 }
00518 else if( tag_type == posTime ) {
00519 short tagtype;
00520 if (fread(&tagtype, sizeof(short), 1, serfile) != 1) {
00521 throw ImageReadException(filename, "SER header");
00522 }
00523 assert((int)tagtype == tag_type);
00524
00525 int sertime;
00526 if (fread(&sertime, sizeof(int), 1, serfile) != 1) {
00527 throw ImageReadException(filename, "SER header");
00528 }
00529 dict["SER.Time"] = sertime;
00530
00531 double pos[2];
00532 if (fread(&pos, sizeof(double), 2, serfile) != 2) {
00533 throw ImageReadException(filename, "SER header");
00534 }
00535 dict["SER.PosionX"] = pos[0];
00536 dict["SER.PosionY"] = pos[1];
00537 }
00538 else {
00539 throw ImageReadException(filename, "SER header, wrong TagTypeID");
00540 }
00541 }