Initial release of Maemo 5 port of gnuplot
[gnuplot] / src / breaders.c
1 #ifndef lint
2 static char *RCSid() { return RCSid("$Id: breaders.c,v 1.3.2.1 2009/01/28 10:39:37 mikulik Exp $"); }
3 #endif
4
5 /* GNUPLOT - breaders.c */
6
7 /*[
8  * Copyright 2004  Petr Mikulik
9  *
10  * As part of the program Gnuplot, which is
11  *
12  * Copyright 1986 - 1993, 1998, 2004   Thomas Williams, Colin Kelley
13  *
14  * Permission to use, copy, and distribute this software and its
15  * documentation for any purpose with or without fee is hereby granted,
16  * provided that the above copyright notice appear in all copies and
17  * that both that copyright notice and this permission notice appear
18  * in supporting documentation.
19  *
20  * Permission to modify the software is granted, but not the right to
21  * distribute the complete modified source code.  Modifications are to
22  * be distributed as patches to the released version.  Permission to
23  * distribute binaries produced by compiling modified sources is granted,
24  * provided you
25  *   1. distribute the corresponding source modifications from the
26  *    released version in the form of a patch file along with the binaries,
27  *   2. add special version identification to distinguish your version
28  *    in addition to the base release version number,
29  *   3. provide your name and address as the primary contact for the
30  *    support of your modified version, and
31  *   4. retain our contact information in regard to use of the base
32  *    software.
33  * Permission to distribute the released version of the source code along
34  * with corresponding source modifications in the form of a patch file is
35  * granted with same provisions 2 through 4 for binary distributions.
36  *
37  * This software is provided "as is" without express or implied warranty
38  * to the extent permitted by applicable law.
39 ]*/
40
41 /* AUTHOR : Petr Mikulik */
42
43 /*
44  * Readers to set up binary data file information for particular formats.
45  */
46
47 #include "breaders.h"
48
49 #ifdef BINARY_DATA_FILE
50
51 #include "datafile.h"
52 #include "alloc.h"
53 #include "misc.h"
54
55 /*
56  * Reader for the ESRF Header File format files (EDF / EHF).
57  */
58
59 /* Inside datafile.c, but kept hidden. */
60 extern char *df_filename;       /* name of data file */
61 extern int df_no_bin_cols;      /* cols to read */
62 extern df_endianess_type df_bin_file_endianess;
63
64 /* Reader for the ESRF Header File format files (EDF / EHF).
65  */
66
67 /* gen_table4 */
68 struct gen_table4 {
69     const char *key;
70     int value;
71     short signum; /* 0..unsigned, 1..signed, 2..float or double */
72     short sajzof; /* sizeof on 32bit architecture */
73 };
74  
75 /* Exactly like lookup_table_nth from tables.c, but for gen_table4 instead
76  * of gen_table.
77  */ 
78 static int
79 lookup_table4_nth(const struct gen_table4 *tbl, const char *search_str)
80 {
81     int k = -1;
82     while (tbl[++k].key)
83         if (tbl[k].key && !strncmp(search_str, tbl[k].key, strlen(tbl[k].key)))
84             return k;
85     return -1; /* not found */
86 }
87
88 static const struct gen_table4 edf_datatype_table[] =
89 {
90     { "UnsignedByte",   DF_UCHAR,   0, 1 },
91     { "SignedByte",     DF_CHAR,    1, 1 },
92     { "UnsignedShort",  DF_USHORT,  0, 2 },
93     { "SignedShort",    DF_SHORT,   1, 2 },
94     { "UnsignedInteger",DF_UINT,    0, 4 },
95     { "SignedInteger",  DF_INT,     1, 4 },
96     { "UnsignedLong",   DF_ULONG,   0, 8 },
97     { "SignedLong",     DF_LONG,    1, 8 },
98     { "FloatValue",     DF_FLOAT,   2, 4 },
99     { "DoubleValue",    DF_DOUBLE,  2, 8 },
100     { "Float",          DF_FLOAT,   2, 4 }, /* Float and FloatValue are synonyms */
101     { "Double",         DF_DOUBLE,  2, 8 }, /* Double and DoubleValue are synonyms */
102     { NULL, -1, -1, -1 }
103 };
104
105 static const struct gen_table edf_byteorder_table[] =
106 {
107     { "LowByteFirst",   DF_LITTLE_ENDIAN }, /* little endian */
108     { "HighByteFirst",  DF_BIG_ENDIAN },    /* big endian */
109     { NULL, -1 }
110 };
111
112 /* Orientation of axes of the raster, as the binary matrix is saved in 
113  * the file.
114  */
115 enum EdfRasterAxes {
116     EDF_RASTER_AXES_XrightYdown,        /* matricial format: rows, columns */
117     EDF_RASTER_AXES_XrightYup           /* cartesian coordinate system */
118     /* other 6 combinations not available (not needed until now) */
119 };
120
121 static const struct gen_table edf_rasteraxes_table[] =
122 {
123     { "XrightYdown",    EDF_RASTER_AXES_XrightYdown },
124     { "XrightYup",      EDF_RASTER_AXES_XrightYup },
125     { NULL, -1 }
126 };
127
128
129 /* Find value_ptr as pointer to the parameter of the given key in the header.
130  * Returns NULL on success.
131  */
132 static char*
133 edf_findInHeader ( const char* header, const char* key )
134 {
135     char *value_ptr = strstr( header, key );
136     if (!value_ptr) return NULL;
137     /* an edf line is "key     = value ;" */
138     value_ptr = 1 + strchr( value_ptr + strlen(key), '=' );
139     while (isspace(*value_ptr)) value_ptr++;
140     return value_ptr;
141 }
142  
143 void
144 edf_filetype_function(void)
145 {
146     FILE *fp;
147     char *header = NULL;
148     int header_size = 0;
149     char *p;
150     int k;
151     /* open (header) file */
152     fp = loadpath_fopen(df_filename, "rb");
153     if (!fp)
154         os_error(NO_CARET, "Can't open data file \"%s\"", df_filename);
155     /* read header: it is a multiple of 512 B ending by "}\n" */
156     while (header_size == 0 || strncmp(&header[header_size-2],"}\n",2)) {
157         int header_size_prev = header_size;
158         header_size += 512;
159         if (!header)
160             header = gp_alloc(header_size+1, "EDF header");
161         else
162             header = gp_realloc(header, header_size+1, "EDF header");
163         header[header_size_prev] = 0; /* protection against empty file */
164         k = fread(header+header_size_prev, 512, 1, fp);
165         if (k == 0) { /* protection against indefinite loop */
166             free(header);
167             os_error(NO_CARET, "Damaged EDF header of %s: not multiple of 512 B.\n", df_filename);
168         }
169         header[header_size] = 0; /* end of string: protection against strstr later on */
170     }
171     fclose(fp);
172     /* make sure there is a binary record structure for each image */
173     if (df_num_bin_records < 1)
174         df_add_binary_records(1-df_num_bin_records, DF_CURRENT_RECORDS); /* otherwise put here: number of images (records) from this file */
175     if ((p = edf_findInHeader(header, "EDF_BinaryFileName"))) {
176         int plen = strcspn(p, " ;\n");
177         df_filename = gp_realloc(df_filename, plen+1, "datafile name");
178         strncpy(df_filename, p, plen);
179         df_filename[plen] = '\0';
180         if ((p = edf_findInHeader(header, "EDF_BinaryFilePosition")))
181             df_bin_record[0].scan_skip[0] = atoi(p);
182         else
183             df_bin_record[0].scan_skip[0] = 0;
184     } else
185         df_bin_record[0].scan_skip[0] = header_size; /* skip header */
186     /* set default values */
187     df_bin_record[0].scan_dir[0] = 1;
188     df_bin_record[0].scan_dir[1] = -1;
189     df_bin_record[0].scan_generate_coord = TRUE;
190     df_bin_record[0].cart_scan[0] = DF_SCAN_POINT;
191     df_bin_record[0].cart_scan[1] = DF_SCAN_LINE;
192     df_extend_binary_columns(1);
193     df_set_skip_before(1,0);
194     df_set_skip_after(1,0);
195     df_no_use_specs = 1;
196     use_spec[0].column = 1;
197     /* now parse the header */
198     if ((p = edf_findInHeader(header, "Dim_1")))
199         df_bin_record[0].scan_dim[0] = atoi(p);
200     if ((p = edf_findInHeader(header, "Dim_2")))
201         df_bin_record[0].scan_dim[1] = atoi(p);
202     if ((p = edf_findInHeader(header, "DataType"))) {
203         k = lookup_table4_nth(edf_datatype_table, p);
204         if (k >= 0) { /* known EDF DataType */
205             int s = edf_datatype_table[k].sajzof; 
206             switch (edf_datatype_table[k].signum) {
207                 case 0: df_set_read_type(1,SIGNED_TEST(s)); break;
208                 case 1: df_set_read_type(1,UNSIGNED_TEST(s)); break;
209                 case 2: df_set_read_type(1,FLOAT_TEST(s)); break;
210             }
211         }
212     }
213     if ((p = edf_findInHeader(header, "ByteOrder"))) {
214         k = lookup_table_nth(edf_byteorder_table, p);
215         if (k >= 0)
216             df_bin_file_endianess = edf_byteorder_table[k].value;
217     }
218     /* Origin vs center: EDF specs allows only Center, but it does not hurt if
219        Origin is supported as well; however, Center rules if both specified.
220     */
221     if ((p = edf_findInHeader(header, "Origin_1"))) {
222         df_bin_record[0].scan_cen_or_ori[0] = atof(p);
223         df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_ORIGIN;
224     }
225     if ((p = edf_findInHeader(header, "Origin_2"))) {
226         df_bin_record[0].scan_cen_or_ori[1] = atof(p);
227         df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_ORIGIN;
228     }
229     if ((p = edf_findInHeader(header, "Center_1"))) {
230         df_bin_record[0].scan_cen_or_ori[0] = atof(p);
231         df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_CENTER;
232     }
233     if ((p = edf_findInHeader(header, "Center_2"))) {
234         df_bin_record[0].scan_cen_or_ori[1] = atof(p);
235         df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_CENTER;
236     }
237     /* now pixel sizes and raster orientation */
238     if ((p = edf_findInHeader(header, "PSize_1")))
239         df_bin_record[0].scan_delta[0] = atof(p);
240     if ((p = edf_findInHeader(header, "PSize_2")))
241         df_bin_record[0].scan_delta[1] = atof(p);
242     if ((p = edf_findInHeader(header, "RasterAxes"))) {
243         k = lookup_table_nth(edf_rasteraxes_table, p);
244         switch (k) {
245             case EDF_RASTER_AXES_XrightYup:
246                 df_bin_record[0].scan_dir[0] = 1;
247                 df_bin_record[0].scan_dir[1] = 1;
248                 df_bin_record[0].cart_scan[0] = DF_SCAN_POINT;
249                 df_bin_record[0].cart_scan[1] = DF_SCAN_LINE;
250                 break;
251             default: /* also EDF_RASTER_AXES_XrightYdown */
252                 df_bin_record[0].scan_dir[0] = 1;
253                 df_bin_record[0].scan_dir[1] = -1;
254                 df_bin_record[0].cart_scan[0] = DF_SCAN_POINT;
255                 df_bin_record[0].cart_scan[1] = DF_SCAN_LINE;
256         }
257     }
258
259     free(header);
260 #if 0
261     /* Print results. This routine will be completely removed later. */
262     fprintf(stderr,"EDF: dim=%ix%i skip=%i datatype=%i datasize=%i dx=%g dy=%g\n",
263         df_bin_record[0].scan_dim[0], df_bin_record[0].scan_dim[1],
264         df_bin_record[0].scan_skip[0],
265         df_get_read_type(1), df_get_read_size(1),
266         df_bin_record[0].scan_delta[0], df_bin_record[0].scan_delta[1]);
267 #endif
268
269 }
270
271 #endif /* BINARY_DATA_FILE */