PageRenderTime 73ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/breaders.c

https://gitlab.com/zimumavo/gnuplot
C | 395 lines | 279 code | 44 blank | 72 comment | 33 complexity | 4ada0b34641546682f6ecfcbcc32b459 MD5 | raw file
  1. #ifndef lint
  2. static char *RCSid() { return RCSid("$Id: breaders.c,v 1.13 2014/05/09 22:14:11 broeker Exp $"); }
  3. #endif
  4. /* GNUPLOT - breaders.c */
  5. /*[
  6. * Copyright 2004 Petr Mikulik
  7. *
  8. * As part of the program Gnuplot, which is
  9. *
  10. * Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley
  11. *
  12. * Permission to use, copy, and distribute this software and its
  13. * documentation for any purpose with or without fee is hereby granted,
  14. * provided that the above copyright notice appear in all copies and
  15. * that both that copyright notice and this permission notice appear
  16. * in supporting documentation.
  17. *
  18. * Permission to modify the software is granted, but not the right to
  19. * distribute the complete modified source code. Modifications are to
  20. * be distributed as patches to the released version. Permission to
  21. * distribute binaries produced by compiling modified sources is granted,
  22. * provided you
  23. * 1. distribute the corresponding source modifications from the
  24. * released version in the form of a patch file along with the binaries,
  25. * 2. add special version identification to distinguish your version
  26. * in addition to the base release version number,
  27. * 3. provide your name and address as the primary contact for the
  28. * support of your modified version, and
  29. * 4. retain our contact information in regard to use of the base
  30. * software.
  31. * Permission to distribute the released version of the source code along
  32. * with corresponding source modifications in the form of a patch file is
  33. * granted with same provisions 2 through 4 for binary distributions.
  34. *
  35. * This software is provided "as is" without express or implied warranty
  36. * to the extent permitted by applicable law.
  37. ]*/
  38. /* AUTHOR : Petr Mikulik */
  39. /*
  40. * Readers to set up binary data file information for particular formats.
  41. */
  42. #include "breaders.h"
  43. #include "datafile.h"
  44. #include "alloc.h"
  45. #include "misc.h"
  46. /*
  47. * Reader for the ESRF Header File format files (EDF / EHF).
  48. */
  49. /* Inside datafile.c, but kept hidden. */
  50. extern int df_no_bin_cols; /* cols to read */
  51. extern df_endianess_type df_bin_file_endianess;
  52. extern TBOOLEAN df_matrix_file, df_binary_file;
  53. extern void *df_pixeldata;
  54. /* Reader for the ESRF Header File format files (EDF / EHF).
  55. */
  56. /* gen_table4 */
  57. struct gen_table4 {
  58. const char *key;
  59. int value;
  60. short signum; /* 0..unsigned, 1..signed, 2..float or double */
  61. short sajzof; /* sizeof on 32bit architecture */
  62. };
  63. /* Exactly like lookup_table_nth from tables.c, but for gen_table4 instead
  64. * of gen_table.
  65. */
  66. static int
  67. lookup_table4_nth(const struct gen_table4 *tbl, const char *search_str)
  68. {
  69. int k = -1;
  70. while (tbl[++k].key)
  71. if (tbl[k].key && !strncmp(search_str, tbl[k].key, strlen(tbl[k].key)))
  72. return k;
  73. return -1; /* not found */
  74. }
  75. static const struct gen_table4 edf_datatype_table[] =
  76. {
  77. { "UnsignedByte", DF_UCHAR, 0, 1 },
  78. { "SignedByte", DF_CHAR, 1, 1 },
  79. { "UnsignedShort", DF_USHORT, 0, 2 },
  80. { "SignedShort", DF_SHORT, 1, 2 },
  81. { "UnsignedInteger",DF_UINT, 0, 4 },
  82. { "SignedInteger", DF_INT, 1, 4 },
  83. { "UnsignedLong", DF_ULONG, 0, 8 },
  84. { "SignedLong", DF_LONG, 1, 8 },
  85. { "FloatValue", DF_FLOAT, 2, 4 },
  86. { "DoubleValue", DF_DOUBLE, 2, 8 },
  87. { "Float", DF_FLOAT, 2, 4 }, /* Float and FloatValue are synonyms */
  88. { "Double", DF_DOUBLE, 2, 8 }, /* Double and DoubleValue are synonyms */
  89. { NULL, -1, -1, -1 }
  90. };
  91. static const struct gen_table edf_byteorder_table[] =
  92. {
  93. { "LowByteFirst", DF_LITTLE_ENDIAN }, /* little endian */
  94. { "HighByteFirst", DF_BIG_ENDIAN }, /* big endian */
  95. { NULL, -1 }
  96. };
  97. /* Orientation of axes of the raster, as the binary matrix is saved in
  98. * the file.
  99. */
  100. enum EdfRasterAxes {
  101. EDF_RASTER_AXES_XrightYdown, /* matricial format: rows, columns */
  102. EDF_RASTER_AXES_XrightYup /* cartesian coordinate system */
  103. /* other 6 combinations not available (not needed until now) */
  104. };
  105. static const struct gen_table edf_rasteraxes_table[] =
  106. {
  107. { "XrightYdown", EDF_RASTER_AXES_XrightYdown },
  108. { "XrightYup", EDF_RASTER_AXES_XrightYup },
  109. { NULL, -1 }
  110. };
  111. /* Find value_ptr as pointer to the parameter of the given key in the header.
  112. * Returns NULL on success.
  113. */
  114. static char*
  115. edf_findInHeader ( const char* header, const char* key )
  116. {
  117. char *value_ptr = strstr( header, key );
  118. if (!value_ptr)
  119. return NULL;
  120. /* an edf line is "key = value ;" */
  121. value_ptr = 1 + strchr(value_ptr + strlen(key), '=');
  122. while (isspace((unsigned char)*value_ptr))
  123. value_ptr++;
  124. return value_ptr;
  125. }
  126. void
  127. edf_filetype_function(void)
  128. {
  129. FILE *fp;
  130. char *header = NULL;
  131. int header_size = 0;
  132. char *p;
  133. int k;
  134. /* open (header) file */
  135. fp = loadpath_fopen(df_filename, "rb");
  136. if (!fp)
  137. os_error(NO_CARET, "Can't open data file \"%s\"", df_filename);
  138. /* read header: it is a multiple of 512 B ending by "}\n" */
  139. while (header_size == 0 || strncmp(&header[header_size-2],"}\n",2)) {
  140. int header_size_prev = header_size;
  141. header_size += 512;
  142. if (!header)
  143. header = gp_alloc(header_size+1, "EDF header");
  144. else
  145. header = gp_realloc(header, header_size+1, "EDF header");
  146. header[header_size_prev] = 0; /* protection against empty file */
  147. k = fread(header+header_size_prev, 512, 1, fp);
  148. if (k == 0) { /* protection against indefinite loop */
  149. free(header);
  150. os_error(NO_CARET, "Damaged EDF header of %s: not multiple of 512 B.\n", df_filename);
  151. }
  152. header[header_size] = 0; /* end of string: protection against strstr later on */
  153. }
  154. fclose(fp);
  155. /* make sure there is a binary record structure for each image */
  156. if (df_num_bin_records < 1)
  157. df_add_binary_records(1-df_num_bin_records, DF_CURRENT_RECORDS); /* otherwise put here: number of images (records) from this file */
  158. if ((p = edf_findInHeader(header, "EDF_BinaryFileName"))) {
  159. int plen = strcspn(p, " ;\n");
  160. df_filename = gp_realloc(df_filename, plen+1, "datafile name");
  161. strncpy(df_filename, p, plen);
  162. df_filename[plen] = '\0';
  163. if ((p = edf_findInHeader(header, "EDF_BinaryFilePosition")))
  164. df_bin_record[0].scan_skip[0] = atoi(p);
  165. else
  166. df_bin_record[0].scan_skip[0] = 0;
  167. } else
  168. df_bin_record[0].scan_skip[0] = header_size; /* skip header */
  169. /* set default values */
  170. df_bin_record[0].scan_dir[0] = 1;
  171. df_bin_record[0].scan_dir[1] = -1;
  172. df_bin_record[0].scan_generate_coord = TRUE;
  173. df_bin_record[0].cart_scan[0] = DF_SCAN_POINT;
  174. df_bin_record[0].cart_scan[1] = DF_SCAN_LINE;
  175. df_extend_binary_columns(1);
  176. df_set_skip_before(1,0);
  177. df_set_skip_after(1,0);
  178. df_no_use_specs = 1;
  179. use_spec[0].column = 1;
  180. /* now parse the header */
  181. if ((p = edf_findInHeader(header, "Dim_1")))
  182. df_bin_record[0].scan_dim[0] = atoi(p);
  183. if ((p = edf_findInHeader(header, "Dim_2")))
  184. df_bin_record[0].scan_dim[1] = atoi(p);
  185. if ((p = edf_findInHeader(header, "DataType"))) {
  186. k = lookup_table4_nth(edf_datatype_table, p);
  187. if (k >= 0) { /* known EDF DataType */
  188. int s = edf_datatype_table[k].sajzof;
  189. switch (edf_datatype_table[k].signum) {
  190. case 0: df_set_read_type(1,SIGNED_TEST(s)); break;
  191. case 1: df_set_read_type(1,UNSIGNED_TEST(s)); break;
  192. case 2: df_set_read_type(1,FLOAT_TEST(s)); break;
  193. }
  194. }
  195. }
  196. if ((p = edf_findInHeader(header, "ByteOrder"))) {
  197. k = lookup_table_nth(edf_byteorder_table, p);
  198. if (k >= 0)
  199. df_bin_file_endianess = edf_byteorder_table[k].value;
  200. }
  201. /* Origin vs center: EDF specs allows only Center, but it does not hurt if
  202. Origin is supported as well; however, Center rules if both specified.
  203. */
  204. if ((p = edf_findInHeader(header, "Origin_1"))) {
  205. df_bin_record[0].scan_cen_or_ori[0] = atof(p);
  206. df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_ORIGIN;
  207. }
  208. if ((p = edf_findInHeader(header, "Origin_2"))) {
  209. df_bin_record[0].scan_cen_or_ori[1] = atof(p);
  210. df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_ORIGIN;
  211. }
  212. if ((p = edf_findInHeader(header, "Center_1"))) {
  213. df_bin_record[0].scan_cen_or_ori[0] = atof(p);
  214. df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_CENTER;
  215. }
  216. if ((p = edf_findInHeader(header, "Center_2"))) {
  217. df_bin_record[0].scan_cen_or_ori[1] = atof(p);
  218. df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_CENTER;
  219. }
  220. /* now pixel sizes and raster orientation */
  221. if ((p = edf_findInHeader(header, "PSize_1")))
  222. df_bin_record[0].scan_delta[0] = atof(p);
  223. if ((p = edf_findInHeader(header, "PSize_2")))
  224. df_bin_record[0].scan_delta[1] = atof(p);
  225. if ((p = edf_findInHeader(header, "RasterAxes"))) {
  226. k = lookup_table_nth(edf_rasteraxes_table, p);
  227. switch (k) {
  228. case EDF_RASTER_AXES_XrightYup:
  229. df_bin_record[0].scan_dir[0] = 1;
  230. df_bin_record[0].scan_dir[1] = 1;
  231. df_bin_record[0].cart_scan[0] = DF_SCAN_POINT;
  232. df_bin_record[0].cart_scan[1] = DF_SCAN_LINE;
  233. break;
  234. default: /* also EDF_RASTER_AXES_XrightYdown */
  235. df_bin_record[0].scan_dir[0] = 1;
  236. df_bin_record[0].scan_dir[1] = -1;
  237. df_bin_record[0].cart_scan[0] = DF_SCAN_POINT;
  238. df_bin_record[0].cart_scan[1] = DF_SCAN_LINE;
  239. }
  240. }
  241. free(header);
  242. }
  243. /*
  244. * Use libgd for input of binary images in PNG GIF JPEG formats
  245. * Ethan A Merritt - August 2009
  246. */
  247. #define GD_PNG 1
  248. #define GD_GIF 2
  249. #define GD_JPEG 3
  250. void gd_filetype_function __PROTO((int filetype));
  251. void
  252. png_filetype_function(void)
  253. {
  254. gd_filetype_function(GD_PNG);
  255. }
  256. void
  257. gif_filetype_function(void)
  258. {
  259. gd_filetype_function(GD_GIF);
  260. }
  261. void
  262. jpeg_filetype_function(void)
  263. {
  264. gd_filetype_function(GD_JPEG);
  265. }
  266. #ifndef HAVE_GD_PNG
  267. void
  268. gd_filetype_function(int type)
  269. {
  270. int_error(NO_CARET, "This copy of gnuplot cannot read png/gif/jpeg images");
  271. }
  272. int
  273. df_libgd_get_pixel(int i, int j, int component) { return 0; }
  274. #else
  275. #include <gd.h>
  276. static gdImagePtr im = NULL;
  277. void
  278. gd_filetype_function(int filetype)
  279. {
  280. FILE *fp;
  281. unsigned int M, N;
  282. /* free previous image, if any */
  283. if (im) {
  284. gdImageDestroy(im);
  285. im = NULL;
  286. }
  287. /* read image into memory */
  288. fp = loadpath_fopen(df_filename, "rb");
  289. if (!fp)
  290. int_error(NO_CARET, "Can't open data file \"%s\"", df_filename);
  291. switch(filetype) {
  292. case GD_PNG: im = gdImageCreateFromPng(fp); break;
  293. case GD_GIF:
  294. #ifdef HAVE_GD_GIF
  295. im = gdImageCreateFromGif(fp);
  296. #endif
  297. break;
  298. case GD_JPEG:
  299. #ifdef HAVE_GD_JPEG
  300. im = gdImageCreateFromJpeg(fp);
  301. #endif
  302. default: break;
  303. }
  304. fclose(fp);
  305. if (!im)
  306. int_error(NO_CARET, "libgd doesn't recognize the format of \"%s\"", df_filename);
  307. /* check on image properties and complain if we can't handle them */
  308. M = im->sx;
  309. N = im->sy;
  310. FPRINTF((stderr,"This is a %u X %u %s image\n",M,N,
  311. im->trueColor ? "TrueColor" : "palette"));
  312. df_pixeldata = im->trueColor ? (void *)im->tpixels : (void *)im->pixels;
  313. df_matrix_file = FALSE;
  314. df_binary_file = TRUE;
  315. df_bin_record[0].scan_skip[0] = 0;
  316. df_bin_record[0].scan_dim[0] = M;
  317. df_bin_record[0].scan_dim[1] = N;
  318. df_bin_record[0].scan_dir[0] = 1;
  319. df_bin_record[0].scan_dir[1] = -1;
  320. df_bin_record[0].scan_generate_coord = TRUE;
  321. df_bin_record[0].cart_scan[0] = DF_SCAN_POINT;
  322. df_bin_record[0].cart_scan[1] = DF_SCAN_LINE;
  323. df_extend_binary_columns(4);
  324. df_set_read_type(1, DF_UCHAR);
  325. df_set_read_type(2, DF_UCHAR);
  326. df_set_read_type(3, DF_UCHAR);
  327. df_set_read_type(4, DF_UCHAR);
  328. df_set_skip_before(1,0);
  329. df_no_use_specs = 4;
  330. use_spec[0].column = 1;
  331. use_spec[1].column = 2;
  332. use_spec[2].column = 3;
  333. use_spec[3].column = 4;
  334. }
  335. int
  336. df_libgd_get_pixel(int i, int j, int component)
  337. {
  338. static int pixel;
  339. int alpha;
  340. switch(component) {
  341. case 0: pixel = gdImageGetTrueColorPixel(im, i,j);
  342. return gdTrueColorGetRed(pixel);
  343. case 1: return gdTrueColorGetGreen(pixel);
  344. case 2: return gdTrueColorGetBlue(pixel);
  345. case 3: /* FIXME? Supposedly runs from 0-127 rather than 0-255 */
  346. alpha = 2 * gdTrueColorGetAlpha(pixel);
  347. return (255-alpha);
  348. default: return 0; /* shouldn't happen */
  349. }
  350. }
  351. #endif