Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

dm4io.cpp

Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00007  * Copyright (c) 2000-2006 Baylor College of Medicine
00008  *
00009  * This software is issued under a joint BSD/GNU license. You may use the
00010  * source code in this file under either license. However, note that the
00011  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00012  * so you are responsible for compliance with the licenses of these packages
00013  * if you opt to use BSD licensing. The warranty disclaimer below holds
00014  * in either instance.
00015  *
00016  * This complete copyright notice must be included in any revised version of the
00017  * source code. Additional authorship citations may be added, but existing
00018  * author citations must be preserved.
00019  *
00020  * This program is free software; you can redistribute it and/or modify
00021  * it under the terms of the GNU General Public License as published by
00022  * the Free Software Foundation; either version 2 of the License, or
00023  * (at your option) any later version.
00024  *
00025  * This program is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028  * GNU General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU General Public License
00031  * along with this program; if not, write to the Free Software
00032  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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 //              LOGDEBUG("  %s: %s", (*p).first.c_str(), (*p).second.c_str());
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 // string tag data are stored in unicode
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         long tot_size = 0;      //size of DataType record + size of data
00626         fread(&tot_size, sizeof(long), 1, in);
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                 portable_fseek(in, sizeof(char) * 9, SEEK_CUR);
00661                 fread(&flagend, sizeof(char), 1, in);
00662                 
00663                 if (flagend ==EOF){
00664                         break;
00665                 }
00666                 else{
00667                         portable_fseek(in, -sizeof(char) * 10, SEEK_CUR);;
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         //single image format, index can only be zero
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         //single image format, index can only be zero
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 

Generated on Tue Jun 11 13:46:13 2013 for EMAN2 by  doxygen 1.3.9.1