EMAN2
salio.cpp
Go to the documentation of this file.
1/*
2 * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
3 * Copyright (c) 2000-2006 Baylor College of Medicine
4 *
5 * This software is issued under a joint BSD/GNU license. You may use the
6 * source code in this file under either license. However, note that the
7 * complete EMAN2 and SPARX software packages have some GPL dependencies,
8 * so you are responsible for compliance with the licenses of these packages
9 * if you opt to use BSD licensing. The warranty disclaimer below holds
10 * in either instance.
11 *
12 * This complete copyright notice must be included in any revised version of the
13 * source code. Additional authorship citations may be added, but existing
14 * author citations must be preserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * */
31
32#include "salio.h"
33#include "util.h"
34#include "geometry.h"
35
36#ifndef WIN32
37#include <sys/param.h>
38#else
39#define MAXPATHLEN (MAX_PATH * 4)
40#endif
41
42#include <cstdio>
43#include <climits>
44#include <cstring>
45
46using namespace EMAN;
47
48const char *SalIO::HDR_EXT = "hdr";
49const char *SalIO::IMG_EXT = "img";
50const char *SalIO::MAGIC = " IDENTIFICATION";
51
52
53SalIO::SalIO(const string & fname, IOMode rw)
54: ImageIO(fname, rw)
55{
56 nx = 0;
57 ny = 0;
58 record_length = 512;
60 pixel = 4.6667f;
61}
62
64{
65 if (file) {
66 fclose(file);
67 file = 0;
68 }
69}
70
71void SalIO::init()
72{
74
75 if (initialized) {
76 return;
77 }
78
79 initialized = true;
80
81 string hdr_filename = Util::change_filename_ext(filename, HDR_EXT);
82 string img_filename = Util::change_filename_ext(filename, IMG_EXT);
83
84 bool is_new_file = false;
85 file = sfopen(hdr_filename, rw_mode, &is_new_file);
86
87 char scan_type[MAXPATHLEN];
88 ScanAxis axis = X_SCAN_AXIS;
89
90 if (!is_new_file) {
91 char buf[MAXPATHLEN];
92 if (fgets(buf, MAXPATHLEN, file)) {
93 if (!is_valid(buf)) {
94 throw ImageReadException(filename, "ivalid SAL");
95 }
96 }
97
98 while (fgets(buf, MAXPATHLEN, file)) {
99 const char *buf1 = buf + 1;
100
101 if (Util::sstrncmp(buf1, "NXP")) {
102 sscanf(strchr(buf, '=') + 1, " %d", &nx);
103 }
104 else if (Util::sstrncmp(buf1, "NYP")) {
105 sscanf(strchr(buf, '=') + 1, " %d", &ny);
106 }
107 else if (Util::sstrncmp(buf1, "AXSCAN")) {
108 char *t = strrchr(buf, '\'');
109 if (t && t[-1] == 'Y') {
110 axis = Y_SCAN_AXIS;
111 }
112 }
113 else if (Util::sstrncmp(buf1, "FILE REC LEN")) {
114 sscanf(strchr(buf, '=') + 1, " %d", &record_length);
115 }
116 else if (Util::sstrncmp(buf1, "SCAN TYPE")) {
117 sscanf(strchr(buf, '\'') + 1, " %s", scan_type);
118 if (scan_type[0] == 'R') {
120 }
121 }
122 else if (Util::sstrncmp(buf1, "DELTAX")) {
123 sscanf(strchr(buf, '=') + 1, " %f", &pixel);
124 pixel /= 3.0;
125 }
126 }
127
128
129 if (axis == Y_SCAN_AXIS) {
130 int t = nx;
131 nx = ny;
132 ny = t;
133 }
134 }
135 fclose(file);
136 file = sfopen(img_filename, rw_mode);
137
138 EXITFUNC;
139}
140
141bool SalIO::is_valid(const void *first_block)
142{
143 ENTERFUNC;
144 bool result = false;
145
146 if (!first_block) {
147 result = false;
148 }
149 result = Util::check_file_by_magic(first_block, MAGIC);
150 EXITFUNC;
151 return result;
152}
153
154int SalIO::read_header(Dict & dict, int image_index, const Region * area, bool)
155{
156 ENTERFUNC;
157
158 //single image format, index can only be zero
159 if(image_index == -1) {
160 image_index = 0;
161 }
162
163 if(image_index != 0) {
164 throw ImageReadException(filename, "no stack allowed for MRC image. For take 2D slice out of 3D image, read the 3D image first, then use get_clip().");
165 }
166
167 init();
168
169 check_region(area, IntSize(nx, ny));
170
171 int xlen = 0, ylen = 0;
172 EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen);
173
174 dict["nx"] = xlen;
175 dict["ny"] = ylen;
176 dict["nz"] = 1;
177 dict["datatype"] = EMUtil::EM_SHORT;
178 dict["SAL.pixel"] = pixel;
179
180 EXITFUNC;
181 return 0;
182}
183
184int SalIO::write_header(const Dict &, int, const Region* , EMUtil::EMDataType, bool)
185{
186 ENTERFUNC;
187 LOGWARN("SAL write is not supported.");
188 EXITFUNC;
189 return 1;
190}
191
192int SalIO::read_data(float *data, int image_index, const Region * area, bool)
193{
194 ENTERFUNC;
195
196 //single image format, index can only be zero
197 image_index = 0;
198 check_read_access(image_index, data);
199 check_region(area, IntSize(nx, ny));
200
201 if (scan_mode != NON_RASTER_SCAN) {
202 LOGERR("only NON_RASTER_SCAN scan mode is supported in a SAL image");
203 return 1;
204 }
205
206 rewind(file);
207
208 int mode_size = (int)sizeof(short);
209 unsigned char *cdata = (unsigned char *) data;
210 short *sdata = (short *) data;
211 size_t row_size = nx * mode_size;
212 size_t block_size = (((row_size - 1) / record_length) + 1) * record_length;
213 size_t post_row = block_size - row_size;
214
215 EMUtil::process_region_io(cdata, file, READ_ONLY, image_index,
216 mode_size, nx, ny, 1, area, false,
217 EMUtil::IMAGE_SAL, 0, post_row);
218
219#if 0
220 int row_size = nx * mode_size;
221 int block_size = (((row_size - 1) / record_length) + 1) * record_length;
222
223 for (int j = 0; j < ny; j++) {
224 if (fread(&cdata[j * row_size], block_size, 1, file) != 1) {
225 LOGERR("Incomplete SAL data read %d/%d blocks", j, ny);
226 return 1;
227 }
228 }
229#endif
230
231 int xlen = 0, ylen = 0;
232 EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen);
233
234 if (scan_mode == NON_RASTER_SCAN) {
235 become_host_endian(sdata, xlen * ylen);
236
237 for (int i = 0; i < ylen; i += 2) {
238 for (int j = 0; j < xlen / 2; j++) {
239 short sw = sdata[i * xlen + j];
240 sdata[i * xlen + j] = sdata[i * xlen + xlen - j - 1];
241 sdata[i * xlen + xlen - j - 1] = sw;
242 }
243 }
244 }
245
246 for (int i = xlen * ylen - 1; i >= 0; i--) {
247 data[i] = static_cast < float >((cdata[i * 2 + 1] * UCHAR_MAX) + cdata[i * 2]);
248 }
249 EXITFUNC;
250 return 0;
251}
252
253int SalIO::write_data(float *, int, const Region* , EMUtil::EMDataType, bool)
254{
255 ENTERFUNC;
256 LOGWARN("SAL write is not supported.");
257 EXITFUNC;
258 return 1;
259}
260
261void SalIO::flush()
262{
263}
264
265
267{
268 return false;
269}
270
272{
273 return false;
274}
275
Dict is a dictionary to store <string, EMObject> pair.
Definition: emobject.h:385
static void process_region_io(void *cdata, FILE *file, int rw_mode, int image_index, size_t mode_size, int nx, int ny, int nz=1, const Region *area=0, bool need_flip=false, ImageType imgtype=IMAGE_UNKNOWN, int pre_row=0, int post_row=0)
Process image region IO.
Definition: emutil.cpp:931
EMDataType
Image pixel data type used in EMAN.
Definition: emutil.h:92
@ EM_SHORT
Definition: emutil.h:96
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.
Definition: emutil.cpp:860
ImageIO classes are designed for reading/writing various electron micrography image formats,...
Definition: imageio.h:127
IOMode rw_mode
Definition: imageio.h:353
string filename
Definition: imageio.h:352
void check_region(const Region *area, const FloatSize &max_size, bool is_new_file=false, bool inbounds_only=true)
Validate image I/O region.
Definition: imageio.cpp:58
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.
bool initialized
Definition: imageio.h:355
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.
Definition: imageio.cpp:135
void check_read_access(int image_index)
Validate 'image_index' in file reading.
Definition: imageio.cpp:95
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.
FILE * file
Definition: imageio.h:354
virtual void init()=0
Do some initialization before doing the read/write.
void become_host_endian(T *data, size_t n=1)
Convert data of this image into host endian format.
Definition: imageio.h:261
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.
Definition: geometry.h:49
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
Definition: geometry.h:497
int ny
Definition: salio.h:75
int nx
Definition: salio.h:74
@ NON_RASTER_SCAN
Definition: salio.h:69
@ RASTER_SCAN
Definition: salio.h:70
static const char * MAGIC
Definition: salio.h:59
@ Y_SCAN_AXIS
Definition: salio.h:64
@ X_SCAN_AXIS
Definition: salio.h:63
float pixel
Definition: salio.h:78
static const char * IMG_EXT
Definition: salio.h:58
int record_length
Definition: salio.h:76
ScanMode scan_mode
Definition: salio.h:77
static bool is_valid(const void *first_block)
Definition: salio.cpp:141
static const char * HDR_EXT
Definition: salio.h:57
static bool sstrncmp(const char *s1, const char *s2)
Safe string compare.
Definition: util.cpp:306
static bool check_file_by_magic(const void *first_block, const char *magic)
check whether a file starts with certain magic string.
Definition: util.cpp:239
static string change_filename_ext(const string &old_filename, const string &new_ext)
Change a file's extension and return the new filename.
Definition: util.cpp:485
#define ImageReadException(filename, desc)
Definition: exception.h:204
#define LOGWARN
Definition: log.h:53
#define LOGERR
Definition: log.h:51
#define ENTERFUNC
Definition: log.h:48
#define EXITFUNC
Definition: log.h:49
E2Exception class.
Definition: aligner.h:40