#ifndef lint static char *RCSid() { return RCSid("$Id: breaders.c,v 1.13 2014/05/09 22:14:11 broeker Exp $"); } #endif /* GNUPLOT - breaders.c */ /*[ * Copyright 2004 Petr Mikulik * * As part of the program Gnuplot, which is * * Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley * * Permission to use, copy, and distribute this software and its * documentation for any purpose with or without fee is hereby granted, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. * * Permission to modify the software is granted, but not the right to * distribute the complete modified source code. Modifications are to * be distributed as patches to the released version. Permission to * distribute binaries produced by compiling modified sources is granted, * provided you * 1. distribute the corresponding source modifications from the * released version in the form of a patch file along with the binaries, * 2. add special version identification to distinguish your version * in addition to the base release version number, * 3. provide your name and address as the primary contact for the * support of your modified version, and * 4. retain our contact information in regard to use of the base * software. * Permission to distribute the released version of the source code along * with corresponding source modifications in the form of a patch file is * granted with same provisions 2 through 4 for binary distributions. * * This software is provided "as is" without express or implied warranty * to the extent permitted by applicable law. ]*/ /* AUTHOR : Petr Mikulik */ /* * Readers to set up binary data file information for particular formats. */ #include "breaders.h" #include "datafile.h" #include "alloc.h" #include "misc.h" /* * Reader for the ESRF Header File format files (EDF / EHF). */ /* Inside datafile.c, but kept hidden. */ extern int df_no_bin_cols; /* cols to read */ extern df_endianess_type df_bin_file_endianess; extern TBOOLEAN df_matrix_file, df_binary_file; extern void *df_pixeldata; /* Reader for the ESRF Header File format files (EDF / EHF). */ /* gen_table4 */ struct gen_table4 { const char *key; int value; short signum; /* 0..unsigned, 1..signed, 2..float or double */ short sajzof; /* sizeof on 32bit architecture */ }; /* Exactly like lookup_table_nth from tables.c, but for gen_table4 instead * of gen_table. */ static int lookup_table4_nth(const struct gen_table4 *tbl, const char *search_str) { int k = -1; while (tbl[++k].key) if (tbl[k].key && !strncmp(search_str, tbl[k].key, strlen(tbl[k].key))) return k; return -1; /* not found */ } static const struct gen_table4 edf_datatype_table[] = { { "UnsignedByte", DF_UCHAR, 0, 1 }, { "SignedByte", DF_CHAR, 1, 1 }, { "UnsignedShort", DF_USHORT, 0, 2 }, { "SignedShort", DF_SHORT, 1, 2 }, { "UnsignedInteger",DF_UINT, 0, 4 }, { "SignedInteger", DF_INT, 1, 4 }, { "UnsignedLong", DF_ULONG, 0, 8 }, { "SignedLong", DF_LONG, 1, 8 }, { "FloatValue", DF_FLOAT, 2, 4 }, { "DoubleValue", DF_DOUBLE, 2, 8 }, { "Float", DF_FLOAT, 2, 4 }, /* Float and FloatValue are synonyms */ { "Double", DF_DOUBLE, 2, 8 }, /* Double and DoubleValue are synonyms */ { NULL, -1, -1, -1 } }; static const struct gen_table edf_byteorder_table[] = { { "LowByteFirst", DF_LITTLE_ENDIAN }, /* little endian */ { "HighByteFirst", DF_BIG_ENDIAN }, /* big endian */ { NULL, -1 } }; /* Orientation of axes of the raster, as the binary matrix is saved in * the file. */ enum EdfRasterAxes { EDF_RASTER_AXES_XrightYdown, /* matricial format: rows, columns */ EDF_RASTER_AXES_XrightYup /* cartesian coordinate system */ /* other 6 combinations not available (not needed until now) */ }; static const struct gen_table edf_rasteraxes_table[] = { { "XrightYdown", EDF_RASTER_AXES_XrightYdown }, { "XrightYup", EDF_RASTER_AXES_XrightYup }, { NULL, -1 } }; /* Find value_ptr as pointer to the parameter of the given key in the header. * Returns NULL on success. */ static char* edf_findInHeader ( const char* header, const char* key ) { char *value_ptr = strstr( header, key ); if (!value_ptr) return NULL; /* an edf line is "key = value ;" */ value_ptr = 1 + strchr(value_ptr + strlen(key), '='); while (isspace((unsigned char)*value_ptr)) value_ptr++; return value_ptr; } void edf_filetype_function(void) { FILE *fp; char *header = NULL; int header_size = 0; char *p; int k; /* open (header) file */ fp = loadpath_fopen(df_filename, "rb"); if (!fp) os_error(NO_CARET, "Can't open data file \"%s\"", df_filename); /* read header: it is a multiple of 512 B ending by "}\n" */ while (header_size == 0 || strncmp(&header[header_size-2],"}\n",2)) { int header_size_prev = header_size; header_size += 512; if (!header) header = gp_alloc(header_size+1, "EDF header"); else header = gp_realloc(header, header_size+1, "EDF header"); header[header_size_prev] = 0; /* protection against empty file */ k = fread(header+header_size_prev, 512, 1, fp); if (k == 0) { /* protection against indefinite loop */ free(header); os_error(NO_CARET, "Damaged EDF header of %s: not multiple of 512 B.\n", df_filename); } header[header_size] = 0; /* end of string: protection against strstr later on */ } fclose(fp); /* make sure there is a binary record structure for each image */ if (df_num_bin_records < 1) df_add_binary_records(1-df_num_bin_records, DF_CURRENT_RECORDS); /* otherwise put here: number of images (records) from this file */ if ((p = edf_findInHeader(header, "EDF_BinaryFileName"))) { int plen = strcspn(p, " ;\n"); df_filename = gp_realloc(df_filename, plen+1, "datafile name"); strncpy(df_filename, p, plen); df_filename[plen] = '\0'; if ((p = edf_findInHeader(header, "EDF_BinaryFilePosition"))) df_bin_record[0].scan_skip[0] = atoi(p); else df_bin_record[0].scan_skip[0] = 0; } else df_bin_record[0].scan_skip[0] = header_size; /* skip header */ /* set default values */ df_bin_record[0].scan_dir[0] = 1; df_bin_record[0].scan_dir[1] = -1; df_bin_record[0].scan_generate_coord = TRUE; df_bin_record[0].cart_scan[0] = DF_SCAN_POINT; df_bin_record[0].cart_scan[1] = DF_SCAN_LINE; df_extend_binary_columns(1); df_set_skip_before(1,0); df_set_skip_after(1,0); df_no_use_specs = 1; use_spec[0].column = 1; /* now parse the header */ if ((p = edf_findInHeader(header, "Dim_1"))) df_bin_record[0].scan_dim[0] = atoi(p); if ((p = edf_findInHeader(header, "Dim_2"))) df_bin_record[0].scan_dim[1] = atoi(p); if ((p = edf_findInHeader(header, "DataType"))) { k = lookup_table4_nth(edf_datatype_table, p); if (k >= 0) { /* known EDF DataType */ int s = edf_datatype_table[k].sajzof; switch (edf_datatype_table[k].signum) { case 0: df_set_read_type(1,SIGNED_TEST(s)); break; case 1: df_set_read_type(1,UNSIGNED_TEST(s)); break; case 2: df_set_read_type(1,FLOAT_TEST(s)); break; } } } if ((p = edf_findInHeader(header, "ByteOrder"))) { k = lookup_table_nth(edf_byteorder_table, p); if (k >= 0) df_bin_file_endianess = edf_byteorder_table[k].value; } /* Origin vs center: EDF specs allows only Center, but it does not hurt if Origin is supported as well; however, Center rules if both specified. */ if ((p = edf_findInHeader(header, "Origin_1"))) { df_bin_record[0].scan_cen_or_ori[0] = atof(p); df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_ORIGIN; } if ((p = edf_findInHeader(header, "Origin_2"))) { df_bin_record[0].scan_cen_or_ori[1] = atof(p); df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_ORIGIN; } if ((p = edf_findInHeader(header, "Center_1"))) { df_bin_record[0].scan_cen_or_ori[0] = atof(p); df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_CENTER; } if ((p = edf_findInHeader(header, "Center_2"))) { df_bin_record[0].scan_cen_or_ori[1] = atof(p); df_bin_record[0].scan_trans = DF_TRANSLATE_VIA_CENTER; } /* now pixel sizes and raster orientation */ if ((p = edf_findInHeader(header, "PSize_1"))) df_bin_record[0].scan_delta[0] = atof(p); if ((p = edf_findInHeader(header, "PSize_2"))) df_bin_record[0].scan_delta[1] = atof(p); if ((p = edf_findInHeader(header, "RasterAxes"))) { k = lookup_table_nth(edf_rasteraxes_table, p); switch (k) { case EDF_RASTER_AXES_XrightYup: df_bin_record[0].scan_dir[0] = 1; df_bin_record[0].scan_dir[1] = 1; df_bin_record[0].cart_scan[0] = DF_SCAN_POINT; df_bin_record[0].cart_scan[1] = DF_SCAN_LINE; break; default: /* also EDF_RASTER_AXES_XrightYdown */ df_bin_record[0].scan_dir[0] = 1; df_bin_record[0].scan_dir[1] = -1; df_bin_record[0].cart_scan[0] = DF_SCAN_POINT; df_bin_record[0].cart_scan[1] = DF_SCAN_LINE; } } free(header); } /* * Use libgd for input of binary images in PNG GIF JPEG formats * Ethan A Merritt - August 2009 */ #define GD_PNG 1 #define GD_GIF 2 #define GD_JPEG 3 void gd_filetype_function __PROTO((int filetype)); void png_filetype_function(void) { gd_filetype_function(GD_PNG); } void gif_filetype_function(void) { gd_filetype_function(GD_GIF); } void jpeg_filetype_function(void) { gd_filetype_function(GD_JPEG); } #ifndef HAVE_GD_PNG void gd_filetype_function(int type) { int_error(NO_CARET, "This copy of gnuplot cannot read png/gif/jpeg images"); } int df_libgd_get_pixel(int i, int j, int component) { return 0; } #else #include static gdImagePtr im = NULL; void gd_filetype_function(int filetype) { FILE *fp; unsigned int M, N; /* free previous image, if any */ if (im) { gdImageDestroy(im); im = NULL; } /* read image into memory */ fp = loadpath_fopen(df_filename, "rb"); if (!fp) int_error(NO_CARET, "Can't open data file \"%s\"", df_filename); switch(filetype) { case GD_PNG: im = gdImageCreateFromPng(fp); break; case GD_GIF: #ifdef HAVE_GD_GIF im = gdImageCreateFromGif(fp); #endif break; case GD_JPEG: #ifdef HAVE_GD_JPEG im = gdImageCreateFromJpeg(fp); #endif default: break; } fclose(fp); if (!im) int_error(NO_CARET, "libgd doesn't recognize the format of \"%s\"", df_filename); /* check on image properties and complain if we can't handle them */ M = im->sx; N = im->sy; FPRINTF((stderr,"This is a %u X %u %s image\n",M,N, im->trueColor ? "TrueColor" : "palette")); df_pixeldata = im->trueColor ? (void *)im->tpixels : (void *)im->pixels; df_matrix_file = FALSE; df_binary_file = TRUE; df_bin_record[0].scan_skip[0] = 0; df_bin_record[0].scan_dim[0] = M; df_bin_record[0].scan_dim[1] = N; df_bin_record[0].scan_dir[0] = 1; df_bin_record[0].scan_dir[1] = -1; df_bin_record[0].scan_generate_coord = TRUE; df_bin_record[0].cart_scan[0] = DF_SCAN_POINT; df_bin_record[0].cart_scan[1] = DF_SCAN_LINE; df_extend_binary_columns(4); df_set_read_type(1, DF_UCHAR); df_set_read_type(2, DF_UCHAR); df_set_read_type(3, DF_UCHAR); df_set_read_type(4, DF_UCHAR); df_set_skip_before(1,0); df_no_use_specs = 4; use_spec[0].column = 1; use_spec[1].column = 2; use_spec[2].column = 3; use_spec[3].column = 4; } int df_libgd_get_pixel(int i, int j, int component) { static int pixel; int alpha; switch(component) { case 0: pixel = gdImageGetTrueColorPixel(im, i,j); return gdTrueColorGetRed(pixel); case 1: return gdTrueColorGetGreen(pixel); case 2: return gdTrueColorGetBlue(pixel); case 3: /* FIXME? Supposedly runs from 0-127 rather than 0-255 */ alpha = 2 * gdTrueColorGetAlpha(pixel); return (255-alpha); default: return 0; /* shouldn't happen */ } } #endif