39const char *TagTable::IMAGE_WIDTH_TAG =
"Dimensions #0";
40const char *TagTable::IMAGE_HEIGHT_TAG =
"Dimensions #1";
41const char *TagTable::IMAGE_NIMG_TAG =
"Dimensions #2";
42const char *TagTable::IMAGE_DATATYPE_TAG =
"DataType";
43const char *TagTable::IMAGE_THUMB_INDEX_TAG =
"ImageIndex";
47 : img_index(0), is_big_endian(true), img_counted(1), num_images_found(0)
53 for (
unsigned int i = 0; i <
data_list.size(); i++) {
63 const char *value_str = value.c_str();
66 x_list.push_back(atoi(value_str));
69 y_list.push_back(atoi(value_str));
102 return atoi(
tags[name].c_str());
107 return static_cast < float >(atof(
tags[name].c_str()));
112 return atof(
tags[name].c_str());
117 map < string, string >::const_iterator p;
119 for (p =
tags.begin(); p !=
tags.end(); p++) {
121 printf(
" %s: %s\n", (*p).first.c_str(), (*p).second.c_str());
152 if (i != 0 && i != 1) {
178 : in(data_file), tagtable(table), name(tagname), tag_type(UNKNOWN)
194 nr = fread(&val, sz, 1,
in); nr++;
196 sprintf(val_str,
"%d", val);
199 unsigned short val = 0;
200 nr = fread(&val, sz, 1,
in); nr++;
202 sprintf(val_str,
"%d", val);
206 nr = fread(&val, sz, 1,
in); nr++;
208 sprintf(val_str,
"%d", val);
212 nr = fread(&val, sz, 1,
in); nr++;
213 sprintf(val_str,
"%d", val);
217 nr = fread(&val, sz, 1,
in); nr++;
219 sprintf(val_str,
"%d", val);
222 unsigned int val = 0;
223 nr = fread(&val, sz, 1,
in); nr++;
225 sprintf(val_str,
"%u", (
int) val);
229 nr = fread(&val, sz, 1,
in); nr++;
231 sprintf(val_str,
"%f", val);
235 nr = fread(&val, sz, 1,
in); nr++;
237 sprintf(val_str,
"%10e", val);
241 nr = fread(&val, sz, 1,
in); nr++;
243 sprintf(val_str,
"%lld", val);
246 unsigned long long val = 0;
247 nr = fread(&val, sz, 1,
in); nr++;
249 sprintf(val_str,
"%lld", val);
256 if (is_value_stored) {
260 LOGVAR(
"value = '%s'", val_str);
262 return string(val_str);
267 LOGVAR(
"TagData::read_array_types()");
269 long long array_type = 0;
271 nr = fread(&array_type,
sizeof(array_type), 1,
in); nr++;
277 vector < int >item_types;
279 if (array_type ==
STRUCT) {
282 else if (array_type ==
ARRAY) {
284 LOGERR(
"DM4: don't know how to handle this array type");
287 item_types.push_back(array_type);
300 unsigned short *buf =
new unsigned short[size];
301 char *str =
new char[size + 1];
304 nr = fread(buf, size *
sizeof(
unsigned short), 1,
in); nr++;
307 for (
int i = 0; i < size; i++) {
308 str[i] =
static_cast < char >(buf[i]);
312 string str1 = string(str);
330 if (item_types.size() == 0) {
331 LOGERR(
"DM4 item types cannot be empty");
336 long long array_size = 0;
339 nr = fread(&array_size,
sizeof(array_size), 1,
in); nr++;
342 LOGVAR(
"array size = %lld\n", array_size);
344 size_t item_size = 0;
345 for (
size_t i = 0; i < item_types.size(); i++) {
346 item_size +=
typesize(item_types[i]);
349 LOGVAR(
"%s array item size = %lld\n",
name.c_str(), item_size);
351 size_t buf_size = item_size * array_size;
353 if (item_types.size() == 1 && item_types[0] ==
USHORT && nodata) {
356 LOGVAR(
"value: %s", val.c_str());
358 else if (!nodata &&
name ==
"Data") {
365 if (image_index < 0 || buf_size % num_images != 0 || num_found == 1) {
366 data =
new char[buf_size];
367 nr = fread(data, item_size, array_size,
in); nr++;
370 size_t image_size = buf_size / num_images;
372 data =
new char[image_size];
374 nr = fread(data, image_size, 1,
in); nr++;
376 array_size = array_size / num_images;
379 if (item_size ==
sizeof(
short)) {
382 else if (item_size ==
sizeof(
int)) {
385 else if (item_size ==
sizeof(
double)) {
389 LOGERR(
"cannot handle this type of DM4 image data");
404 LOGVAR(
"TagData::read_struct_types()");
406 long long namelength = 0;
407 long long nfields = 0;
410 nr = fread(&namelength,
sizeof(namelength), 1,
in); nr++;
413 nr = fread(&nfields,
sizeof(nfields), 1,
in); nr++;
416 LOGVAR(
"namelength = %lld\n", namelength);
417 LOGVAR(
"num fields = %lld\n", nfields);
419 vector < int >field_types;
421 for (
unsigned int i = 0; i < nfields; i++) {
422 nr = fread(&namelength,
sizeof(namelength), 1,
in); nr++;
425 long long field_type = 0;
426 nr = fread(&field_type,
sizeof(field_type), 1,
in); nr++;
429 LOGVAR(
"%dth namelength = %lld, type = '%s'",
431 field_types.push_back(field_type);
455 for (
unsigned int i = 0; i < field_types.size(); i++) {
462 sprintf(int_str,
" #%d", i);
463 string fieldname =
name + string(int_str);
471 nr = fread(&str_sz,
sizeof(str_sz), 1,
in); nr++;
474 char *val =
new char[str_sz + 1];
475 nr = fread(val, str_sz, 1,
in); nr++;
477 string val_str = string(val);
495 LOGVAR(
"TagData::read_tag_data()");
498 const char *DATA_TYPE_MARK =
"%%%%";
499 const size_t mark_sz = strlen(DATA_TYPE_MARK);
500 char *mark =
new char[mark_sz + 1];
505 nr = fread(&interval,
sizeof(interval), 1,
in); nr++;
509 nr = fread(mark, mark_sz, 1,
in); nr++;
510 mark[mark_sz] =
'\0';
512 if (strcmp(mark, DATA_TYPE_MARK) != 0) {
513 LOGERR(
"data type label has been changed from '%s' to '%s'",
514 DATA_TYPE_MARK, mark);
523 long long encoded_types_size = 0;
524 nr = fread(&encoded_types_size,
sizeof(
long long), 1,
in); nr++;
527 LOGVAR(
"encoded types size = %lld\n", encoded_types_size);
529 err =
read_any(nodata, image_index, num_images);
542 Type type =
static_cast < Type > (t);
547 size =
sizeof(short);
550 size =
sizeof(
unsigned short);
556 size =
sizeof(
unsigned int);
559 size =
sizeof(float);
562 size =
sizeof(double);
572 size =
sizeof(double);
575 size =
sizeof(double);
578 LOGERR(
"no such type: '%d'\n", type);
588 : in(data_file), tagtable(table), parent_group(parent), name(
"")
598 LOGVAR(
"TagEntry::read_tag_entry()");
606 nr = fread(&tagtype,
sizeof(
char), 1,
in); nr++;
610 nr = fread(&tagtype,
sizeof(
char), 1,
in); nr++;
620 LOGERR(
"TagEntry::read_tag_entry() invalid tag type: %d @ position %lld", tagtype, pos);
626 nr = fread(&name_len,
sizeof(
short), 1,
in); nr++;
631 tmp_name =
new char[name_len + 1];
632 nr = fread(tmp_name, name_len, 1,
in); nr++;
633 tmp_name[name_len] =
'\0';
637 name_len =
static_cast < short >(parent_name.size() + 4);
638 tmp_name =
new char[name_len + 1];
642 name = string(tmp_name);
649 LOGVAR(
"\ntag name: '%s', len: %d, type: '%s'",
654 err = tag_data.
read_tag_data(nodata, image_index, num_images);
657 long long tot_size = 0;
658 nr = fread(&tot_size,
sizeof(
long long), 1,
in); nr++;
675 : in(data_file), tagtable(table), name(groupname), entry_id(0)
685 LOGVAR(
"TagGroup::read_tag_group()");
686 char is_sorted, is_open;
692 nr = fread(&is_sorted,
sizeof(is_sorted), 1,
in); nr++;
693 nr = fread(&is_open,
sizeof(is_open), 1,
in); nr++;
695 nr = fread(&ntags,
sizeof(ntags), 1,
in); nr++;
699 LOGVAR(
"DM4: ntags = %d\n", ntags);
703 for (
int i = 0; i < ntags; i++) {
775 int stream_version = 0;
776 if (fread(&stream_version,
sizeof(stream_version), 1,
file) != 1) {
781 if (fread(&recsize,
sizeof(recsize), 1,
file) != 1) {
786 if (fread(&endianness,
sizeof(endianness), 1,
file) != 1) {
796 if (endianness == 0) {
805 LOGDEBUG(
"dm4 ver = %d, image size = %d, is_big_endian = %d",
819 const int *data =
static_cast < const int *
>(first_block);
821 int img_ver = data[0];
822 int byte_order = data[3];
832 if (byte_order != 0 && byte_order != 1) {
851 if(image_index == -1) {
859 root_group.read_tag_group(
true, 0, 1);
865 int xlen = 0, ylen = 0;
886 dict[
"microscope_voltage"]=(float)dict[
"DM4.voltage"];
888 dict[
"microscope_cs"]=(float)dict[
"DM4.cs"];
897 if ((
float)dict[
"DM4.actual_mag"] >0.0) {
898 float apix=10000.0*(float)dict[
"DM4.pixel_size"]/(
float)dict[
"DM4.actual_mag"];
916 root_group.read_tag_group(
true, 0, 1);
923 root_group.read_tag_group(
false, image_index, num_images);
927 int xlen = 0, ylen = 0, x0 = 0, y0 = 0;
934 long long offset = 0;
937 int xlast = x0 + xlen;
938 int ylast = y0 + ylen;
941 bool flip_vertical =
true;
943 for (
int iy = y0; iy < ylast; iy++) {
945 off = offset + (y0 + ylast - 1 - iy) * nx;
948 off = offset + iy * nx;
953 for (
int ix = x0; ix < xlast; ix++) {
954 rdata[k] = (float) ((
char *) data)[off + ix];
959 for (
int ix = x0; ix < xlast; ix++) {
960 rdata[k] = (float) ((
unsigned char *) data)[off + ix];
965 for (
int ix = x0; ix < xlast; ix++) {
966 rdata[k] = (float) ((
short *) data)[off + ix];
971 for (
int ix = x0; ix < xlast; ix++) {
972 rdata[k] = (float) ((
unsigned short *) data)[off + ix];
977 for (
int ix = x0; ix < xlast; ix++) {
978 rdata[k] = (float) ((
int *) data)[off + ix];
983 for (
int ix = x0; ix < xlast; ix++) {
984 rdata[k] = (float) ((
unsigned int *) data)[off + ix];
989 for (
int ix = x0; ix < xlast; ix++) {
990 rdata[k] = (float) ((
float *) data)[off + ix];
995 for (
int ix = x0; ix < xlast; ix++) {
996 rdata[k] = (float) ((
double *) data)[off + ix];
1001 string desc = string(
"unsupported DM4 data type") +
1024 LOGWARN(
"DM4 write is not supported.");
1032 LOGWARN(
"DM4 write is not supported.");
1085 const char *str =
"unknown";
1088 case TagData::SHORT:
1094 case TagData::USHORT:
1095 str =
"unsigned short";
1098 str =
"unsigned int";
1100 case TagData::FLOAT:
1103 case TagData::DOUBLE:
1106 case TagData::BOOLEAN:
1112 case TagData::OCTET:
1115 case TagData::STRUCT:
1118 case TagData::STRING:
1121 case TagData::ARRAY:
1132 const char *str =
"unknown";
1135 case TagEntry::GROUP_TAG:
1138 case TagEntry::DATA_TAG:
1152 return "SIGNED_INT16_DATA";
1154 return "REAL4_DATA";
1156 return "COMPLEX8_DATA";
1158 return "OBSELETE_DATA";
1160 return "PACKED_DATA";
1162 return "UNSIGNED_INT8_DATA";
1164 return "SIGNED_INT32_DATA";
1168 return "SIGNED_INT8_DATA";
1170 return "UNSIGNED_INT16_DATA";
1172 return "UNSIGNED_INT32_DATA";
1174 return "REAL8_DATA";
1176 return "COMPLEX16_DATA";
1178 return "BINARY_DATA";
1180 return "RGB_UINT8_0_DATA";
1182 return "RGB_UINT8_1_DATA";
1184 return "RGB_UINT16_DATA";
1186 return "RGB_FLOAT32_DATA";
1188 return "RGB_FLOAT64_DATA";
1190 return "RGBA_UINT8_0_DATA";
1192 return "RGBA_UINT8_1_DATA";
1194 return "RGBA_UINT8_2_DATA";
1196 return "RGBA_UINT8_3_DATA";
1198 return "RGBA_UINT16_DATA";
1200 return "RGBA_FLOAT32_DATA";
1202 return "RGBA_FLOAT64_DATA";
1204 return "POINT2_SINT16_0_DATA";
1206 return "POINT2_SINT16_1_DATA";
1208 return "POINT2_SINT32_0_DATA";
1210 return "POINT2_FLOAT32_0_DATA";
1212 return "RECT_SINT16_1_DATA";
1214 return "RECT_SINT32_1_DATA";
1216 return "RECT_FLOAT32_1_DATA";
1218 return "RECT_FLOAT32_0_DATA";
1220 return "SIGNED_INT64_DATA";
1222 return "UNSIGNED_INT64_DATA";
1226 return "Unknown Type";
static bool is_host_big_endian()
static void swap_bytes(T *data, size_t n=1)
swap the byte order of data with 'n' T-type elements.
static bool is_data_big_endian(const T *small_num_addr)
given a pointer to a reasonable small integer number, return whether the number is big endian or not.
static void become_big_endian(T *data, size_t n=1)
convert data from host byte order to big endian order.
int get_nimg()
Return the number of images in this image file.
GatanDM4::TagTable * tagtable
DM4IO(const string &fname, IOMode rw_mode=READ_ONLY)
static bool is_valid(const void *first_block)
Dict is a dictionary to store <string, EMObject> pair.
EMDataType
Image pixel data type used in EMAN.
static void get_region_origins(const Region *area, int *p_x0, int *p_y0, int *p_z0=0, int nz=1, int image_index=0)
Get a region's original locations.
static void get_region_dims(const Region *area, int nx, int *area_x, int ny, int *area_y, int nz=1, int *area_z=0)
Get a region's dimensions.
int read_tag_data(bool nodata=false, int image_index=0, int num_images=1)
string read_string(int size)
TagData(FILE *data_file, TagTable *tagtable, const string &tagname)
vector< int > read_array_types()
int read_any(bool nodata=false, int image_index=0, int num_images=1)
int read_array_data(vector< int >item_types, bool nodata=false, int image_index=0, int num_images=1)
string read_native(bool is_value_stored)
vector< int > read_struct_types()
TagEntry(FILE *data_file, TagTable *tagtable, TagGroup *parent_group)
int read_tag_entry(bool nodata=false, int image_index=0, int num_images=1)
int read_tag_group(bool nodata=false, int image_index=0, int num_images=1)
TagGroup(FILE *data_file, TagTable *tagtable, const string &groupname)
static const char * IMAGE_HEIGHT_TAG
std::map< string, string > tags
int get_num_images_found() const
int get_int(const string &name)
vector< int > datatype_list
void become_host_endian(T *data, int n=1)
void set_endian(bool big_endian)
double get_double(const string &name)
static const char * IMAGE_NIMG_TAG
void set_num_images_found(int num_found)
string get_string(const string &name)
void add(const string &name, const string &value)
static const char * IMAGE_THUMB_INDEX_TAG
int get_image_counted() const
static const char * IMAGE_WIDTH_TAG
void set_thumb_index(int i)
void add_data(char *data)
vector< char * > data_list
float get_float(const string &name)
static const char * IMAGE_DATATYPE_TAG
ImageIO classes are designed for reading/writing various electron micrography image formats,...
void check_region(const Region *area, const FloatSize &max_size, bool is_new_file=false, bool inbounds_only=true)
Validate image I/O region.
virtual void flush()=0
Flush the IO buffer.
virtual int write_header(const Dict &dict, int image_index=0, const Region *area=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)=0
Write a header to an image.
virtual int write_data(float *data, int image_index=0, const Region *area=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)=0
Write data to an image.
virtual bool is_complex_mode()=0
Is this an complex image or not.
virtual int read_header(Dict &dict, int image_index=0, const Region *area=0, bool is_3d=false)=0
Read the header from an image.
FILE * sfopen(const string &filename, IOMode mode, bool *is_new=0, bool overwrite=false)
Run fopen safely.
void check_read_access(int image_index)
Validate 'image_index' in file reading.
virtual int read_data(float *data, int image_index=0, const Region *area=0, bool is_3d=false)=0
Read the data from an image.
virtual void init()=0
Do some initialization before doing the read/write.
virtual bool is_image_big_endian()=0
Is this image in big endian or not.
IntSize is used to describe a 1D, 2D or 3D rectangular size in integers.
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
#define ImageReadException(filename, desc)
#define OutofRangeException(low, high, input, objname)
#define NullPointerException(desc)
int to_em_datatype(int gatan_datatype)
const char * to_str(GatanDM4::TagData::Type type)
int to_em_datatype(int gatan_datatype)
int portable_fseek(FILE *fp, off_t offset, int whence)