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 "dm4io.h"
00037 #include "portable_fileio.h"
00038 #include "geometry.h"
00039
00040 using namespace EMAN;
00041 using namespace EMAN::GatanDM4;
00042
00043 const char *TagTable::IMAGE_WIDTH_TAG = "Dimensions #0";
00044 const char *TagTable::IMAGE_HEIGHT_TAG = "Dimensions #1";
00045 const char *TagTable::IMAGE_DATATYPE_TAG = "DataType";
00046 const char *TagTable::IMAGE_THUMB_INDEX_TAG = "ImageIndex";
00047
00048
00049 TagTable::TagTable()
00050 : img_index(0), is_big_endian(true)
00051 {
00052 }
00053
00054 TagTable::~TagTable()
00055 {
00056 for (unsigned int i = 0; i < data_list.size(); i++) {
00057 if (data_list[i]) {
00058 delete[]data_list[i];
00059 data_list[i] = 0;
00060 }
00061 }
00062 }
00063
00064
00065 void TagTable::add(const string & name, const string & value)
00066 {
00067 const char *value_str = value.c_str();
00068
00069 if (name == IMAGE_WIDTH_TAG) {
00070 x_list.push_back(atoi(value_str));
00071 }
00072 else if (name == IMAGE_HEIGHT_TAG) {
00073 y_list.push_back(atoi(value_str));
00074 }
00075 else if (name == IMAGE_DATATYPE_TAG) {
00076 datatype_list.push_back(atoi(value_str));
00077 }
00078 else if (name == IMAGE_THUMB_INDEX_TAG) {
00079 set_thumb_index(atoi(value_str));
00080 }
00081 else {
00082 tags[name] = value;
00083 }
00084 }
00085
00086 void TagTable::add_data(char *data)
00087 {
00088 if (!data) {
00089 throw NullPointerException("DM4 data is NULL");
00090 }
00091 else {
00092 data_list.push_back(data);
00093 }
00094 }
00095
00096 string TagTable::get_string(const string & name)
00097 {
00098 return tags[name];
00099 }
00100
00101 int TagTable::get_int(const string & name)
00102 {
00103 return atoi(tags[name].c_str());
00104 }
00105
00106 float TagTable::get_float(const string & name)
00107 {
00108 return static_cast < float >(atof(tags[name].c_str()));
00109 }
00110
00111 double TagTable::get_double(const string & name)
00112 {
00113 return atof(tags[name].c_str());
00114 }
00115
00116 void TagTable::dump() const
00117 {
00118 map < string, string >::const_iterator p;
00119
00120 for (p = tags.begin(); p != tags.end(); p++) {
00121
00122 printf(" %s: %s\n", (*p).first.c_str(), (*p).second.c_str());
00123 }
00124 }
00125
00126 int TagTable::get_xsize() const
00127 {
00128 return x_list[img_index];
00129 }
00130
00131 int TagTable::get_ysize() const
00132 {
00133 return y_list[img_index];
00134 }
00135
00136 int TagTable::get_datatype() const
00137 {
00138 return datatype_list[img_index];
00139 }
00140
00141 char *TagTable::get_data() const
00142 {
00143 return data_list[img_index];
00144 }
00145
00146 void TagTable::set_thumb_index(int i)
00147 {
00148 if (i != 0 && i != 1) {
00149 throw OutofRangeException(0, 1, i, "image index");
00150 }
00151 else {
00152 if (i == 0) {
00153 img_index = 1;
00154 }
00155 else {
00156 img_index = 0;
00157 }
00158 }
00159 }
00160
00162
00163 TagData::TagData(FILE * data_file, TagTable * table, const string & tagname)
00164 : in(data_file), tagtable(table), name(tagname), tag_type(UNKNOWN)
00165 {
00166 }
00167
00168 TagData::~TagData()
00169 {
00170 }
00171
00172 string TagData::read_native(bool is_value_stored)
00173 {
00174 size_t sz = typesize();
00175 char val_str[32];
00176
00177 if (tag_type == SHORT) {
00178 short val = 0;
00179 fread(&val, sz, 1, in);
00180 tagtable->become_host_endian(&val);
00181 sprintf(val_str, "%d", val);
00182 }
00183 else if (tag_type == USHORT) {
00184 unsigned short val = 0;
00185 fread(&val, sz, 1, in);
00186 tagtable->become_host_endian(&val);
00187 sprintf(val_str, "%d", val);
00188 }
00189 else if (tag_type == INT) {
00190 int val = 0;
00191 fread(&val, sz, 1, in);
00192 tagtable->become_host_endian(&val);
00193 sprintf(val_str, "%d", val);
00194 }
00195 else if (tag_type == CHAR || tag_type == OCTET) {
00196 char val = 0;
00197 fread(&val, sz, 1, in);
00198 sprintf(val_str, "%d", val);
00199 }
00200 else if (tag_type == BOOLEAN) {
00201 bool val = false;
00202 fread(&val, sz, 1, in);
00203 tagtable->become_host_endian(&val);
00204 sprintf(val_str, "%d", val);
00205 }
00206 else if (tag_type == UINT) {
00207 unsigned int val = 0;
00208 fread(&val, sz, 1, in);
00209 tagtable->become_host_endian(&val);
00210 sprintf(val_str, "%d", (int) val);
00211 }
00212 else if (tag_type == FLOAT) {
00213 float val = 0;
00214 fread(&val, sz, 1, in);
00215 tagtable->become_host_endian(&val);
00216 sprintf(val_str, "%f", val);
00217 }
00218 else if (tag_type == DOUBLE) {
00219 double val = 0;
00220 fread(&val, sz, 1, in);
00221 tagtable->become_host_endian(&val);
00222 sprintf(val_str, "%10e", val);
00223 }
00224 else if (tag_type == OCTEU) {
00225 double val = 0;
00226 fread(&val, sz, 1, in);
00227 tagtable->become_host_endian(&val);
00228 sprintf(val_str, "%10e", val);
00229 }
00230 else if (tag_type == OCTEV) {
00231 double val = 0;
00232 fread(&val, sz, 1, in);
00233 tagtable->become_host_endian(&val);
00234 sprintf(val_str, "%10e", val);
00235 }
00236 else {
00237 LOGERR("invalid tag type: '%d'", tag_type);
00238 exit(1);
00239 }
00240
00241 if (is_value_stored) {
00242 tagtable->add(name, val_str);
00243 }
00244
00245 LOGVAR("value = '%s'", val_str);
00246
00247 return string(val_str);
00248 }
00249
00250 vector < int >TagData::read_array_types()
00251 {
00252 LOGVAR("TagData::read_array_types()");
00253
00254 long array_type = 0;
00255 fread(&array_type, sizeof(array_type), 1, in);
00256
00257 ByteOrder::become_big_endian(&array_type);
00258
00259 LOGVAR("array data type = '%s'", GatanDM4::to_str((Type) array_type));
00260
00261 vector < int >item_types;
00262
00263 if (array_type == STRUCT) {
00264 item_types = read_struct_types();
00265 }
00266 else if (array_type == ARRAY) {
00267 item_types = read_array_types();
00268 LOGERR("DM4: don't know how to handle this array type");
00269 }
00270 else {
00271 item_types.push_back(array_type);
00272 }
00273
00274 return item_types;
00275 }
00276
00277
00278 string TagData::read_string(int size)
00279 {
00280 if (size <= 0) {
00281 return string("");
00282 }
00283
00284 unsigned short *buf = new unsigned short[size];
00285 char *str = new char[size + 1];
00286
00287 fread(buf, size * sizeof(unsigned short), 1, in);
00288 tagtable->become_host_endian < unsigned short >(buf, size);
00289
00290 for (int i = 0; i < size; i++) {
00291 str[i] = static_cast < char >(buf[i]);
00292 }
00293
00294 str[size] = '\0';
00295 string str1 = string(str);
00296
00297 if( str )
00298 {
00299 delete[]str;
00300 str = 0;
00301 }
00302 if( buf )
00303 {
00304 delete[]buf;
00305 buf = 0;
00306 }
00307
00308 return str1;
00309 }
00310
00311 int TagData::read_array_data(vector < int >item_types, bool nodata)
00312 {
00313 ENTERFUNC;
00314 if (item_types.size() == 0) {
00315 LOGERR("DM4 item types cannot be empty");
00316 return 1;
00317 }
00318
00319 int err = 0;
00320 long array_size = 0;
00321
00322 fread(&array_size, sizeof(array_size), 1, in);
00323 ByteOrder::become_big_endian(&array_size);
00324
00325 LOGVAR("array size = %d\n", array_size);
00326
00327 size_t item_size = 0;
00328 for (size_t i = 0; i < item_types.size(); i++) {
00329 item_size += typesize(item_types[i]);
00330 }
00331
00332 LOGVAR("%s array item size = %d\n", name.c_str(), item_size);
00333
00334 size_t buf_size = item_size * array_size;
00335
00336 if (item_types.size() == 1 && item_types[0] == USHORT && nodata) {
00337 string val = read_string(array_size);
00338 tagtable->add(name, val);
00339 LOGVAR("value: %s", val.c_str());
00340 }
00341 else if (!nodata && name == "Data") {
00342 char *data = new char[buf_size];
00343 fread(data, buf_size, 1, in);
00344
00345 if (item_size == sizeof(short)) {
00346 tagtable->become_host_endian((short *) data, array_size);
00347 }
00348 else if (item_size == sizeof(int)) {
00349 tagtable->become_host_endian((int *) data, array_size);
00350 }
00351 else if (item_size == sizeof(double)) {
00352 tagtable->become_host_endian((double *) data, array_size);
00353 }
00354 else {
00355 LOGERR("cannot handle this type of DM4 image data");
00356 return 1;
00357 }
00358
00359 tagtable->add_data(data);
00360 }
00361 else {
00362 portable_fseek(in, buf_size, SEEK_CUR);
00363 }
00364 EXITFUNC;
00365 return err;
00366 }
00367
00368 vector < int >TagData::read_struct_types()
00369 {
00370 LOGVAR("TagData::read_struct_types()");
00371
00372 long namelength = 0;
00373 long nfields = 0;
00374
00375 fread(&namelength, sizeof(namelength), 1, in);
00376 ByteOrder::become_big_endian(&namelength);
00377
00378 fread(&nfields, sizeof(nfields), 1, in);
00379 ByteOrder::become_big_endian(&nfields);
00380
00381 LOGVAR("namelength = %d\n", namelength);
00382 LOGVAR("num fields = %d\n", nfields);
00383
00384 vector < int >field_types;
00385
00386 for (unsigned int i = 0; i < nfields; i++) {
00387 fread(&namelength, sizeof(namelength), 1, in);
00388 ByteOrder::become_big_endian(&namelength);
00389
00390 long field_type = 0;
00391 fread(&field_type, sizeof(field_type), 1, in);
00392 ByteOrder::become_big_endian(&field_type);
00393
00394 LOGVAR("%dth namelength = %d, type = '%s'",
00395 i, namelength, GatanDM4::to_str((Type) field_type));
00396 field_types.push_back(field_type);
00397 }
00398
00399 return field_types;
00400 }
00401
00402 int TagData::read_any(bool nodata)
00403 {
00404 int err = 0;
00405
00406 fread(&tag_type, sizeof(tag_type), 1, in);
00407
00408 ByteOrder::become_big_endian(&tag_type);
00409 LOGVAR("TagData::read_any tag type = '%s'\n", GatanDM4::to_str((Type) tag_type));
00410
00411
00412 if (tag_type == ARRAY) {
00413 vector < int >item_types = read_array_types();
00414 err = read_array_data(item_types, nodata);
00415 }
00416 else if (tag_type == STRUCT) {
00417 vector < int >field_types = read_struct_types();
00418
00419 for (unsigned int i = 0; i < field_types.size(); i++) {
00420
00421 tag_type = static_cast < Type > (field_types[i]);
00422
00423 string val = read_native(false);
00424
00425 char int_str[32];
00426 sprintf(int_str, " #%d", i);
00427 string fieldname = name + string(int_str);
00428 tagtable->add(fieldname, val);
00429 }
00430 }
00431 else if (tag_type == STRING) {
00432
00433 int str_sz = 0;
00434 fread(&str_sz, sizeof(str_sz), 1, in);
00435 ByteOrder::become_big_endian(&str_sz);
00436
00437 char *val = new char[str_sz + 1];
00438 fread(val, str_sz, 1, in);
00439 val[str_sz] = '\0';
00440 string val_str = string(val);
00441 if( val )
00442 {
00443 delete[]val;
00444 val = 0;
00445 }
00446
00447 tagtable->add(name, val_str);
00448 }
00449 else {
00450 read_native(true);
00451 }
00452
00453 return err;
00454 }
00455
00456 int TagData::read(bool nodata)
00457 {
00458 LOGVAR("TagData::read()");
00459 int err = 0;
00460
00461 const char *DATA_TYPE_MARK = "%%%%";
00462 const size_t mark_sz = strlen(DATA_TYPE_MARK);
00463 char *mark = new char[mark_sz + 1];
00464
00465 long interval;
00466
00467 fread(&interval, sizeof(interval), 1, in);
00468
00469 ByteOrder::become_big_endian(&interval);
00470
00471 fread(mark, mark_sz, 1, in);
00472 mark[mark_sz] = '\0';
00473
00474 if (strcmp(mark, DATA_TYPE_MARK) != 0) {
00475 LOGERR("data type label has been changed from '%s' to '%s'",
00476 DATA_TYPE_MARK, mark);
00477 return 1;
00478 }
00479
00480 if( mark )
00481 {
00482 delete[]mark;
00483 mark = 0;
00484 }
00485
00486 long encoded_types_size = 0;
00487 fread(&encoded_types_size, sizeof(long), 1, in);
00488 ByteOrder::become_big_endian(&encoded_types_size);
00489
00490 LOGVAR("encoded types size = %d\n", encoded_types_size);
00491
00492 err = read_any(nodata);
00493
00494 return err;
00495 }
00496
00497 size_t TagData::typesize() const
00498 {
00499 return typesize((int) tag_type);
00500 }
00501
00502 size_t TagData::typesize(int t) const
00503 {
00504 size_t size = 0;
00505 Type type = static_cast < Type > (t);
00506
00507
00508 switch (type) {
00509 case SHORT:
00510 size = sizeof(short);
00511 break;
00512 case USHORT:
00513 size = sizeof(unsigned short);
00514 break;
00515 case INT:
00516 size = sizeof(int);
00517 break;
00518 case UINT:
00519 size = sizeof(unsigned int);
00520 break;
00521 case FLOAT:
00522 size = sizeof(float);
00523 break;
00524 case DOUBLE:
00525 size = sizeof(double);
00526 break;
00527 case BOOLEAN:
00528 size = sizeof(bool);
00529 break;
00530 case CHAR:
00531 case OCTET:
00532 size = sizeof(char);
00533 break;
00534 case OCTEU:
00535 size = sizeof(double);
00536 break;
00537 case OCTEV:
00538 size = sizeof(double);
00539 break;
00540 default:
00541 LOGERR("no such type: '%d'\n", type);
00542 break;
00543 }
00544
00545 return size;
00546 }
00547
00549
00550 TagEntry::TagEntry(FILE * data_file, TagTable * table, TagGroup * parent)
00551 : in(data_file), tagtable(table), parent_group(parent), name("")
00552 {
00553 }
00554
00555 TagEntry::~TagEntry()
00556 {
00557 }
00558
00559 int TagEntry::read(bool nodata)
00560 {
00561 LOGVAR("TagEntry::read()");
00562 int err = 0;
00563 char tag_type = 0;
00564 char *tmp_name = 0;
00565
00566 fread(&tag_type, sizeof(char), 1, in);
00567
00568 if (tag_type != GROUP_TAG && tag_type != DATA_TAG) {
00569 portable_fseek(in, sizeof(char) * 7, SEEK_CUR);
00570 fread(&tag_type, sizeof(char), 1, in);
00571 }
00572
00573 if (tag_type != GROUP_TAG && tag_type != DATA_TAG) {
00574 tag_type =fgetc(in);
00575 if (tag_type ==EOF)
00576 {
00577 return 1;
00578 }
00579 else{
00580 LOGERR("TagEntry::read() invalid tag type: %d", tag_type);
00581 return 1;
00582 }
00583 }
00584
00585
00586 short name_len = 0;
00587 fread(&name_len, sizeof(short), 1, in);
00588
00589 ByteOrder::become_big_endian(&name_len);
00590
00591 if (name_len != 0) {
00592 tmp_name = new char[name_len + 1];
00593 fread(tmp_name, name_len, 1, in);
00594 tmp_name[name_len] = '\0';
00595 }
00596 else {
00597 string parent_name = parent_group->get_name();
00598 name_len = static_cast < short >(parent_name.size() + 4);
00599 tmp_name = new char[name_len + 1];
00600 sprintf(tmp_name, "%s #%d", parent_name.c_str(), parent_group->get_entry_id());
00601 }
00602
00603 name = string(tmp_name);
00604 if( tmp_name )
00605 {
00606 delete[]tmp_name;
00607 tmp_name = 0;
00608 }
00609
00610 LOGVAR("\ntag name: '%s', len: %d, type: '%s'",
00611 name.c_str(), name_len, GatanDM4::to_str((EntryType) tag_type));
00612
00613 if (tag_type == DATA_TAG) {
00614
00615 TagData tag_data(in, tagtable, name);
00616 err = tag_data.read(nodata);
00617 }
00618 else if (tag_type == GROUP_TAG) {
00619
00620 TagGroup group(in, tagtable, name);
00621 err = group.read(nodata);
00622 }
00623
00624
00625
00626
00627
00628 return err;
00629 }
00630
00632
00633 TagGroup::TagGroup(FILE * data_file, TagTable * table, const string & groupname)
00634 : in(data_file), tagtable(table), name(groupname), entry_id(0)
00635 {
00636 }
00637
00638 TagGroup::~TagGroup()
00639 {
00640 }
00641
00642 int TagGroup::read(bool nodata)
00643 {
00644 LOGVAR("TagGroup::read()");
00645
00646 long ntags = 0;
00647
00648 portable_fseek(in, sizeof(char) * 2, SEEK_CUR);
00649
00650 fread(&ntags, sizeof(ntags), 1, in);
00651
00652 ByteOrder::become_big_endian(&ntags);
00653
00654 LOGVAR("DM4: ntags = %d\n", ntags);
00655
00656 int err = 0;
00657 char flagend;
00658 for (int i = 0; i < ntags; i++) {
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 TagEntry tag_entry(in, tagtable, this);
00673 err = tag_entry.read(nodata);
00674
00675 if (err) {
00676 break;
00677 }
00678 }
00679
00680 return err;
00681 }
00682
00683 string TagGroup::get_name() const
00684 {
00685 return name;
00686 }
00687
00688 int TagGroup::get_entry_id()
00689 {
00690 int id = entry_id;
00691 entry_id++;
00692 return id;
00693 }
00694
00696
00697 DM4IO::DM4IO(const string & dm4_filename, IOMode rw)
00698 : filename(dm4_filename), rw_mode(rw), dm4file(0), initialized(false)
00699 {
00700 is_big_endian = ByteOrder::is_host_big_endian();
00701 tagtable = new TagTable();
00702 }
00703
00704 DM4IO::~DM4IO()
00705 {
00706 if (dm4file) {
00707 fclose(dm4file);
00708 dm4file = 0;
00709 }
00710 if (tagtable) {
00711 delete tagtable;
00712 tagtable = 0;
00713 }
00714 }
00715
00716 void DM4IO::init()
00717 {
00718 ENTERFUNC;
00719 if (initialized) {
00720 return;
00721 }
00722 initialized = true;
00723
00724 if (rw_mode != READ_ONLY) {
00725 throw ImageReadException(filename, "only support DM4 read-only");
00726 }
00727
00728 dm4file = sfopen(filename, READ_ONLY);
00729
00730 int stream_version = 0;
00731 if (fread(&stream_version, sizeof(stream_version), 1, dm4file) != 1) {
00732 throw ImageReadException(filename, "read stream version of DM4 file");
00733 }
00734
00735 long recsize;
00736 if (fread(&recsize, sizeof(recsize), 1, dm4file) != 1) {
00737 throw ImageReadException(filename, "read size of TagGroup recoed of DM4 file");
00738 }
00739
00740 int endianness;
00741 if (fread(&endianness, sizeof(endianness), 1, dm4file) != 1) {
00742 throw ImageReadException(filename, "read endianness indicator of DM4 file");
00743 }
00744
00745 if (ByteOrder::is_data_big_endian(&stream_version) != ByteOrder::is_host_big_endian()) {
00746 ByteOrder::swap_bytes(&stream_version);
00747 ByteOrder::swap_bytes(&recsize);
00748 ByteOrder::swap_bytes(&endianness);
00749 }
00750
00751 if (endianness == 0) {
00752 is_big_endian = true;
00753 }
00754 else {
00755 is_big_endian = false;
00756 }
00757
00758 tagtable->set_endian(is_big_endian);
00759
00760 LOGDEBUG("dm3 ver = %d, image size = %d, is_big_endian = %d",
00761 stream_version, recsize, (int) is_big_endian);
00762
00763 EXITFUNC;
00764 }
00765
00766 bool DM4IO::is_valid(const void *first_block)
00767 {
00768 ENTERFUNC;
00769
00770 if (!first_block) {
00771 return false;
00772 }
00773
00774 const int *data = static_cast < const int *>(first_block);
00775
00776 int img_ver = data[0];
00777 int byte_order = data[3];
00778 if (ByteOrder::is_data_big_endian(&img_ver) != ByteOrder::is_host_big_endian()) {
00779 ByteOrder::swap_bytes(&img_ver);
00780 ByteOrder::swap_bytes(&byte_order);
00781 }
00782
00783 if (img_ver != 4) {
00784 return false;
00785 }
00786
00787 if (byte_order != 0 && byte_order != 1) {
00788 return false;
00789 }
00790
00791 return true;
00792 }
00793
00794 bool DM4IO::is_image_big_endian()
00795 {
00796 init();
00797 return is_big_endian;
00798 }
00799
00800 int DM4IO::read_header(Dict & dict, int image_index, const Region * area, bool)
00801 {
00802 ENTERFUNC;
00803 int err = 0;
00804
00805
00806 if(image_index == -1) {
00807 image_index = 0;
00808 }
00809 image_index = 0;
00810 check_read_access(image_index);
00811
00812 portable_fseek(dm4file, NUM_ID_INT * sizeof(int), SEEK_SET);
00813 TagGroup root_group(dm4file, tagtable, "");
00814 root_group.read(true);
00815
00816 int nx = tagtable->get_xsize();
00817 int ny = tagtable->get_ysize();
00818
00819 check_region(area, IntSize(nx, ny));
00820 int xlen = 0, ylen = 0;
00821 EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen);
00822
00823 dict["nx"] = xlen;
00824 dict["ny"] = ylen;
00825 dict["nz"] = 1;
00826
00827 dict["DM4.acq_date"] = tagtable->get_string("Acquisition Date");
00828 dict["DM4.acq_time"] = tagtable->get_string("Acquisition Time");
00829 dict["DM4.source"] = tagtable->get_string("Source");
00830 dict["DM4.exposure_number"] = tagtable->get_int("Exposure Number");
00831 dict["DM4.exposure_time"] = tagtable->get_double("Exposure (s)");
00832 dict["DM4.zoom"] = tagtable->get_double("Zoom");
00833 dict["DM4.antiblooming"] = tagtable->get_int("Antiblooming");
00834 dict["DM4.indicated_mag"] = tagtable->get_double("Indicated Magnification");
00835 dict["DM4.actual_mag"] = tagtable->get_double("Actual Magnification");
00836 dict["DM4.pixel_size"] = tagtable->get_double("Pixel Size (um) #0");
00837 dict["DM4.name"] = tagtable->get_string("Name");
00838
00839 dict["DM4.voltage"] = tagtable->get_double("Voltage")/1000.0;
00840 dict["microscope_voltage"]=(float)dict["DM4.voltage"];
00841 dict["DM4.cs"] = tagtable->get_double("Cs(mm)");
00842 dict["microscope_cs"]=(float)dict["DM4.cs"];
00843
00844 dict["DM4.frame_type"] = tagtable->get_string("Processing");
00845 dict["DM4.camera_x"] = tagtable->get_int("Active Size (pixels) #0");
00846 dict["DM4.camera_y"] = tagtable->get_int("Active Size (pixels) #1");
00847 dict["DM4.binning_x"] = tagtable->get_int("Binning #0");
00848 dict["DM4.binning_y"] = tagtable->get_int("Binning #1");
00849 dict["datatype"] = to_em_datatype(tagtable->get_datatype());
00850
00851 if ((float)dict["DM4.actual_mag"] >0.0) {
00852 float apix=10000.0*(float)dict["DM4.pixel_size"]/(float)dict["DM4.actual_mag"];
00853 dict["apix_x"]=apix;
00854 dict["apix_y"]=apix;
00855 dict["apix_z"]=apix;
00856 }
00857
00858 EXITFUNC;
00859 return err;
00860 }
00861
00862 int DM4IO::read_data(float *rdata, int image_index, const Region * area, bool)
00863 {
00864 ENTERFUNC;
00865
00866
00867 image_index = 0;
00868 check_read_access(image_index, rdata);
00869
00870 portable_fseek(dm4file, NUM_ID_INT * sizeof(int), SEEK_SET);
00871 TagGroup root_group(dm4file, tagtable, "");
00872 root_group.read(false);
00873
00874 int nx = tagtable->get_xsize();
00875 int ny = tagtable->get_ysize();
00876
00877 check_region(area, IntSize(nx, ny));
00878
00879 int xlen = 0, ylen = 0, x0 = 0, y0 = 0;
00880 EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen);
00881 EMUtil::get_region_origins(area, &x0, &y0);
00882
00883 char *data = tagtable->get_data();
00884 int data_type = tagtable->get_datatype();
00885
00886 int k = 0;
00887 for (int i = y0; i < y0 + ylen; i++) {
00888 for (int j = x0; j < x0 + xlen; j++) {
00889 switch (data_type) {
00890 case GatanDM4::DataType::SIGNED_INT8_DATA:
00891 rdata[k] = (float) ((char *) data)[i * nx + j];
00892 break;
00893 case GatanDM4::DataType::UNSIGNED_INT8_DATA:
00894 rdata[k] = (float) ((unsigned char *) data)[i * nx + j];
00895 break;
00896 case GatanDM4::DataType::SIGNED_INT16_DATA:
00897 rdata[k] = (float) ((short *) data)[i * nx + j];
00898 break;
00899 case GatanDM4::DataType::UNSIGNED_INT16_DATA:
00900 rdata[k] = (float) ((unsigned short *) data)[i * nx + j];
00901 break;
00902 case GatanDM4::DataType::SIGNED_INT32_DATA:
00903 rdata[k] = (float) ((int *) data)[i * nx + j];
00904 break;
00905 case GatanDM4::DataType::UNSIGNED_INT32_DATA:
00906 rdata[k] = (float) ((unsigned int *) data)[i * nx + j];
00907 break;
00908 case GatanDM4::DataType::REAL4_DATA:
00909 rdata[k] = (float) ((float *) data)[i * nx + j];
00910 break;
00911 case GatanDM4::DataType::REAL8_DATA:
00912 rdata[k] = (double) ((float *) data)[i * nx + j];
00913 break;
00914 default:
00915 string desc = string("unsupported DM3 data type") +
00916 string(GatanDM4::to_str((GatanDM4::DataType::GatanDataType) data_type));
00917 throw ImageReadException(filename, desc);
00918 }
00919 k++;
00920 }
00921 }
00922 EXITFUNC;
00923 return 0;
00924
00925 EXITFUNC;
00926 }
00927
00928 bool DM4IO::is_complex_mode()
00929 {
00930 return false;
00931 }
00932
00933 int DM4IO::write_header(const Dict &, int, const Region* , EMUtil::EMDataType, bool)
00934 {
00935 ENTERFUNC;
00936 LOGWARN("DM4 write is not supported.");
00937 EXITFUNC;
00938 return 1;
00939 }
00940
00941 int DM4IO::write_data(float *, int, const Region* , EMUtil::EMDataType, bool)
00942 {
00943 ENTERFUNC;
00944 LOGWARN("DM4 write is not supported.");
00945 EXITFUNC;
00946 return 1;
00947 }
00948
00949 void DM4IO::flush()
00950 {
00951 }
00952
00953 int GatanDM4::to_em_datatype(int gatan_datatype)
00954 {
00955 DataType::GatanDataType type = static_cast < DataType::GatanDataType > (gatan_datatype);
00956 int t = 0;
00957
00958 switch (type) {
00959 case GatanDM4::DataType::SIGNED_INT8_DATA:
00960 t = EMUtil::EM_CHAR;
00961 break;
00962 case GatanDM4::DataType::UNSIGNED_INT8_DATA:
00963 t = EMUtil::EM_UCHAR;
00964 break;
00965 case GatanDM4::DataType::SIGNED_INT16_DATA:
00966 t = EMUtil::EM_SHORT;
00967 break;
00968 case GatanDM4::DataType::UNSIGNED_INT16_DATA:
00969 t = EMUtil::EM_USHORT;
00970 break;
00971 case GatanDM4::DataType::SIGNED_INT32_DATA:
00972 t = EMUtil::EM_INT;
00973 break;
00974 case GatanDM4::DataType::UNSIGNED_INT32_DATA:
00975 t = EMUtil::EM_UINT;
00976 break;
00977 default:
00978 t = EMUtil::EM_UNKNOWN;
00979 }
00980
00981 return t;
00982 }
00983
00984
00985 const char *GatanDM4::to_str(TagData::Type type)
00986 {
00987 const char *str = "unknown";
00988
00989 switch (type) {
00990 case TagData::SHORT:
00991 str = "short";
00992 break;
00993 case TagData::INT:
00994 str = "int";
00995 break;
00996 case TagData::USHORT:
00997 str = "unsigned short";
00998 break;
00999 case TagData::UINT:
01000 str = "unsigned int";
01001 break;
01002 case TagData::FLOAT:
01003 str = "float";
01004 break;
01005 case TagData::DOUBLE:
01006 str = "double";
01007 break;
01008 case TagData::BOOLEAN:
01009 str = "boolean";
01010 break;
01011 case TagData::CHAR:
01012 str = "char";
01013 break;
01014 case TagData::OCTET:
01015 str = "octet";
01016 break;
01017 case TagData::STRUCT:
01018 str = "struct";
01019 break;
01020 case TagData::STRING:
01021 str = "string";
01022 break;
01023 case TagData::ARRAY:
01024 str = "array";
01025 break;
01026 default:
01027 str = "unknown";
01028 }
01029 return str;
01030 }
01031
01032 const char *GatanDM4::to_str(TagEntry::EntryType type)
01033 {
01034 const char *str = "unknown";
01035
01036 switch (type) {
01037 case TagEntry::GROUP_TAG:
01038 str = "Group";
01039 break;
01040 case TagEntry::DATA_TAG:
01041 str = "Data";
01042 break;
01043 default:
01044 str = "unknown";
01045 }
01046 return str;
01047 }
01048
01049
01050 const char *GatanDM4::to_str(GatanDM4::DataType::GatanDataType type)
01051 {
01052 switch (type) {
01053 case GatanDM4::DataType::SIGNED_INT16_DATA:
01054 return "SIGNED_INT16_DATA";
01055 case GatanDM4::DataType::REAL4_DATA:
01056 return "REAL4_DATA";
01057 case GatanDM4::DataType::COMPLEX8_DATA:
01058 return "COMPLEX8_DATA";
01059 case GatanDM4::DataType::OBSELETE_DATA:
01060 return "OBSELETE_DATA";
01061 case GatanDM4::DataType::PACKED_DATA:
01062 return "PACKED_DATA";
01063 case GatanDM4::DataType::UNSIGNED_INT8_DATA:
01064 return "UNSIGNED_INT8_DATA";
01065 case GatanDM4::DataType::SIGNED_INT32_DATA:
01066 return "SIGNED_INT32_DATA";
01067 case GatanDM4::DataType::RGB_DATA:
01068 return "RGB_DATA";
01069 case GatanDM4::DataType::SIGNED_INT8_DATA:
01070 return "SIGNED_INT8_DATA";
01071 case GatanDM4::DataType::UNSIGNED_INT16_DATA:
01072 return "UNSIGNED_INT16_DATA";
01073 case GatanDM4::DataType::UNSIGNED_INT32_DATA:
01074 return "UNSIGNED_INT32_DATA";
01075 case GatanDM4::DataType::REAL8_DATA:
01076 return "REAL8_DATA";
01077 case GatanDM4::DataType::COMPLEX16_DATA:
01078 return "COMPLEX16_DATA";
01079 case GatanDM4::DataType::BINARY_DATA:
01080 return "BINARY_DATA";
01081 case GatanDM4::DataType::RGB_UINT8_0_DATA:
01082 return "RGB_UINT8_0_DATA";
01083 case GatanDM4::DataType::RGB_UINT8_1_DATA:
01084 return "RGB_UINT8_1_DATA";
01085 case GatanDM4::DataType::RGB_UINT16_DATA:
01086 return "RGB_UINT16_DATA";
01087 case GatanDM4::DataType::RGB_FLOAT32_DATA:
01088 return "RGB_FLOAT32_DATA";
01089 case GatanDM4::DataType::RGB_FLOAT64_DATA:
01090 return "RGB_FLOAT64_DATA";
01091 case GatanDM4::DataType::RGBA_UINT8_0_DATA:
01092 return "RGBA_UINT8_0_DATA";
01093 case GatanDM4::DataType::RGBA_UINT8_1_DATA:
01094 return "RGBA_UINT8_1_DATA";
01095 case GatanDM4::DataType::RGBA_UINT8_2_DATA:
01096 return "RGBA_UINT8_2_DATA";
01097 case GatanDM4::DataType::RGBA_UINT8_3_DATA:
01098 return "RGBA_UINT8_3_DATA";
01099 case GatanDM4::DataType::RGBA_UINT16_DATA:
01100 return "RGBA_UINT16_DATA";
01101 case GatanDM4::DataType::RGBA_FLOAT32_DATA:
01102 return "RGBA_FLOAT32_DATA";
01103 case GatanDM4::DataType::RGBA_FLOAT64_DATA:
01104 return "RGBA_FLOAT64_DATA";
01105 case GatanDM4::DataType::POINT2_SINT16_0_DATA:
01106 return "POINT2_SINT16_0_DATA";
01107 case GatanDM4::DataType::POINT2_SINT16_1_DATA:
01108 return "POINT2_SINT16_1_DATA";
01109 case GatanDM4::DataType::POINT2_SINT32_0_DATA:
01110 return "POINT2_SINT32_0_DATA";
01111 case GatanDM4::DataType::POINT2_FLOAT32_0_DATA:
01112 return "POINT2_FLOAT32_0_DATA";
01113 case GatanDM4::DataType::RECT_SINT16_1_DATA:
01114 return "RECT_SINT16_1_DATA";
01115 case GatanDM4::DataType::RECT_SINT32_1_DATA:
01116 return "RECT_SINT32_1_DATA";
01117 case GatanDM4::DataType::RECT_FLOAT32_1_DATA:
01118 return "RECT_FLOAT32_1_DATA";
01119 case GatanDM4::DataType::RECT_FLOAT32_0_DATA:
01120 return "RECT_FLOAT32_0_DATA";
01121 case GatanDM4::DataType::SIGNED_INT64_DATA:
01122 return "SIGNED_INT64_DATA";
01123 case GatanDM4::DataType::UNSIGNED_INT64_DATA:
01124 return "UNSIGNED_INT64_DATA";
01125 default:
01126 break;
01127 }
01128 return "Unknown Type";
01129 }
01130
01131