summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'leptonica/src/gplot.c')
-rw-r--r--leptonica/src/gplot.c1364
1 files changed, 1364 insertions, 0 deletions
diff --git a/leptonica/src/gplot.c b/leptonica/src/gplot.c
new file mode 100644
index 00000000..3743207b
--- /dev/null
+++ b/leptonica/src/gplot.c
@@ -0,0 +1,1364 @@
+/*====================================================================*
+ - Copyright (C) 2001 Leptonica. All rights reserved.
+ -
+ - Redistribution and use in source and binary forms, with or without
+ - modification, are permitted provided that the following conditions
+ - are met:
+ - 1. Redistributions of source code must retain the above copyright
+ - notice, this list of conditions and the following disclaimer.
+ - 2. Redistributions in binary form must reproduce the above
+ - copyright notice, this list of conditions and the following
+ - disclaimer in the documentation and/or other materials
+ - provided with the distribution.
+ -
+ - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
+ - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *====================================================================*/
+
+/*!
+ * \file gplot.c
+ * <pre>
+ *
+ * Basic plotting functions
+ * GPLOT *gplotCreate()
+ * void gplotDestroy()
+ * l_int32 gplotAddPlot()
+ * l_int32 gplotSetScaling()
+ * PIX *gplotMakeOutputPix()
+ * l_int32 gplotMakeOutput()
+ * l_int32 gplotGenCommandFile()
+ * l_int32 gplotGenDataFiles()
+ *
+ * Quick, one-line plots
+ * l_int32 gplotSimple1()
+ * l_int32 gplotSimple2()
+ * l_int32 gplotSimpleN()
+ * PIX *gplotSimplePix1()
+ * PIX *gplotSimplePix2()
+ * PIX *gplotSimplePixN()
+ * GPLOT *gplotSimpleXY1()
+ * GPLOT *gplotSimpleXY2()
+ * GPLOT *gplotSimpleXYN()
+ * PIX *gplotGeneralPix1()
+ * PIX *gplotGeneralPix2()
+ * PIX *gplotGeneralPixN()
+ *
+ * Serialize for I/O
+ * GPLOT *gplotRead()
+ * l_int32 gplotWrite()
+ *
+ *
+ * Utility for programmatic plotting using gnuplot 4.6 or later
+ * Enabled:
+ * ~ output to png (color), ps and eps (mono), latex (mono)
+ * ~ optional title for plot
+ * ~ optional x and y axis labels
+ * ~ multiple plots on one frame
+ * ~ optional label for each plot on the frame
+ * ~ optional log scaling on either or both axes
+ * ~ choice of 5 plot styles for each array of input data
+ * ~ choice of 2 plot modes, either using one input array
+ * (Y vs index) or two input arrays (Y vs X). For functions
+ * that take two arrays, the first mode (Y vs index) is
+ * employed if the first array is NULL.
+ *
+ * General usage:
+ * gplotCreate() initializes for plotting
+ * gplotAddPlot() for each plot on the frame
+ * gplotMakeOutput() to generate all output files and run gnuplot
+ * gplotDestroy() to clean up
+ *
+ * Example of use:
+ * gplot = gplotCreate("tempskew", GPLOT_PNG, "Skew score vs angle",
+ * "angle (deg)", "score");
+ * gplotAddPlot(gplot, natheta, nascore1, GPLOT_LINES, "plot 1");
+ * gplotAddPlot(gplot, natheta, nascore2, GPLOT_POINTS, "plot 2");
+ * gplotSetScaling(gplot, GPLOT_LOG_SCALE_Y);
+ * gplotMakeOutput(gplot);
+ * gplotDestroy(&gplot);
+ *
+ * Example usage of one-line plot generators:
+ *
+ * -- Simple plots --
+ * Specify the root of output files, the output format,
+ * and the title (optional), but not the x and y coordinate labels
+ * or the plot labels. The plotstyle defaults to GPLOT_LINES.
+ * gplotSimple2(na1, na2, GPLOT_PNG, "/tmp/lept/histo/gray",
+ * "gray histogram");
+ * Multiple plots can be generated using gplotSimpleN().
+ *
+ * -- Simple plots with more options --
+ * Specify the root of output files, the plotstyle, the output format,
+ * and optionally the title, but not the x and y coordinate labels
+ * or the plot labels.
+ * gplotSimpleXY1(na1, na2, GPLOT_LINES, GPLOT_PNG,
+ * "/tmp/lept/histo/gray", "gray histogram");
+ * Multiple plots can be generated using gplotSimpleXYN().
+ *
+ * -- Simple plots returning a pix --
+ * Specify only the title (optional). The plotstyle defaults
+ * GPLOT_LINES and the output format is GPLOT_PNG..
+ * You can't specify the x and y coordinate lables or the plot label.
+ * The rootname of the generated files is determined internally.
+ * Pix *pix = gplotSimplePix2(na1, na2, "gray histogram");
+ * Multiple plots can be generated using gplotSimplePixN().
+ *
+ * -- General plots returning a pix --
+ * Specify the root of the output files, the plotstyle, and optionally
+ * the title and axis labels. This does not allow the individual
+ * plots to have plot labels, or to use different plotstyles
+ * for each plot.
+ * Pix *pix = gplotGeneralPix2(na1, na2, "/tmp/lept/histo/gray",
+ * GPLOT_LINES, "gray histogram",
+ * "pix value", "num pixels");
+ * Multiple plots can be generated using gplotGeneralPixN().
+ *
+ * Note for output to GPLOT_LATEX:
+ * This creates latex output of the plot, named <rootname>.tex.
+ * It needs to be placed in a latex file <latexname>.tex
+ * that precedes the plot output with, at a minimum:
+ * \documentclass{article}
+ * \begin{document}
+ * and ends with
+ * \end{document}
+ * You can then generate a dvi file <latexname>.dvi using
+ * latex <latexname>.tex
+ * and a PostScript file <psname>.ps from that using
+ * dvips -o <psname>.ps <latexname>.dvi
+ *
+ * N.B. To generate plots, it is necessary to have gnuplot installed on
+ * your Unix system, or wgnuplot on Windows.
+ * </pre>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config_auto.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include "allheaders.h"
+
+#define Bufsize 512 /* hardcoded below in fscanf */
+
+const char *gplotstylenames[] = {"with lines",
+ "with points",
+ "with impulses",
+ "with linespoints",
+ "with dots"};
+const char *gplotfileoutputs[] = {"",
+ "PNG",
+ "PS",
+ "EPS",
+ "LATEX",
+ "PNM"};
+
+
+/*-----------------------------------------------------------------*
+ * Basic Plotting Functions *
+ *-----------------------------------------------------------------*/
+/*!
+ * \brief gplotCreate()
+ *
+ * \param[in] rootname root for all output files
+ * \param[in] outformat GPLOT_PNG, GPLOT_PS, GPLOT_EPS,
+ * GPLOT_LATEX, GPLOT_PNM
+ * \param[in] title [optional] overall title
+ * \param[in] xlabel [optional] x axis label
+ * \param[in] ylabel [optional] y axis label
+ * \return gplot, or NULL on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This initializes the plot.
+ * (2) The 'title', 'xlabel' and 'ylabel' strings can have spaces,
+ * double quotes and backquotes, but not single quotes.
+ * </pre>
+ */
+GPLOT *
+gplotCreate(const char *rootname,
+ l_int32 outformat,
+ const char *title,
+ const char *xlabel,
+ const char *ylabel)
+{
+char *newroot;
+char buf[Bufsize];
+l_int32 badchar;
+GPLOT *gplot;
+
+ PROCNAME("gplotCreate");
+
+ if (!rootname)
+ return (GPLOT *)ERROR_PTR("rootname not defined", procName, NULL);
+ if (outformat != GPLOT_PNG && outformat != GPLOT_PS &&
+ outformat != GPLOT_EPS && outformat != GPLOT_LATEX &&
+ outformat != GPLOT_PNM)
+ return (GPLOT *)ERROR_PTR("outformat invalid", procName, NULL);
+ stringCheckForChars(rootname, "`;&|><\"?*$()", &badchar);
+ if (badchar) /* danger of command injection */
+ return (GPLOT *)ERROR_PTR("invalid rootname", procName, NULL);
+
+#if !defined(HAVE_LIBPNG)
+ if (outformat == GPLOT_PNG) {
+ L_WARNING("png library missing; output pnm format\n", procName);
+ outformat = GPLOT_PNM;
+ }
+#endif
+
+ gplot = (GPLOT *)LEPT_CALLOC(1, sizeof(GPLOT));
+ gplot->cmddata = sarrayCreate(0);
+ gplot->datanames = sarrayCreate(0);
+ gplot->plotdata = sarrayCreate(0);
+ gplot->plotlabels = sarrayCreate(0);
+ gplot->plotstyles = numaCreate(0);
+
+ /* Save title, labels, rootname, outformat, cmdname, outname */
+ newroot = genPathname(rootname, NULL);
+ gplot->rootname = newroot;
+ gplot->outformat = outformat;
+ snprintf(buf, Bufsize, "%s.cmd", rootname);
+ gplot->cmdname = stringNew(buf);
+ if (outformat == GPLOT_PNG)
+ snprintf(buf, Bufsize, "%s.png", newroot);
+ else if (outformat == GPLOT_PS)
+ snprintf(buf, Bufsize, "%s.ps", newroot);
+ else if (outformat == GPLOT_EPS)
+ snprintf(buf, Bufsize, "%s.eps", newroot);
+ else if (outformat == GPLOT_LATEX)
+ snprintf(buf, Bufsize, "%s.tex", newroot);
+ else if (outformat == GPLOT_PNM)
+ snprintf(buf, Bufsize, "%s.pnm", newroot);
+ gplot->outname = stringNew(buf);
+ if (title) gplot->title = stringNew(title);
+ if (xlabel) gplot->xlabel = stringNew(xlabel);
+ if (ylabel) gplot->ylabel = stringNew(ylabel);
+
+ return gplot;
+}
+
+
+/*!
+ * \brief gplotDestroy()
+ *
+ * \param[in,out] pgplot will be set to null before returning
+ */
+void
+gplotDestroy(GPLOT **pgplot)
+{
+GPLOT *gplot;
+
+ PROCNAME("gplotDestroy");
+
+ if (pgplot == NULL) {
+ L_WARNING("ptr address is null!\n", procName);
+ return;
+ }
+
+ if ((gplot = *pgplot) == NULL)
+ return;
+
+ LEPT_FREE(gplot->rootname);
+ LEPT_FREE(gplot->cmdname);
+ sarrayDestroy(&gplot->cmddata);
+ sarrayDestroy(&gplot->datanames);
+ sarrayDestroy(&gplot->plotdata);
+ sarrayDestroy(&gplot->plotlabels);
+ numaDestroy(&gplot->plotstyles);
+ LEPT_FREE(gplot->outname);
+ if (gplot->title)
+ LEPT_FREE(gplot->title);
+ if (gplot->xlabel)
+ LEPT_FREE(gplot->xlabel);
+ if (gplot->ylabel)
+ LEPT_FREE(gplot->ylabel);
+
+ LEPT_FREE(gplot);
+ *pgplot = NULL;
+}
+
+
+/*!
+ * \brief gplotAddPlot()
+ *
+ * \param[in] gplot
+ * \param[in] nax [optional] numa: set to null for Y_VS_I;
+ * required for Y_VS_X
+ * \param[in] nay numa; required for both Y_VS_I and Y_VS_X
+ * \param[in] plotstyle GPLOT_LINES, GPLOT_POINTS, GPLOT_IMPULSES,
+ * GPLOT_LINESPOINTS, GPLOT_DOTS
+ * \param[in] plotlabel [optional] label for individual plot
+ * \return 0 if OK, 1 on error
+ *
+ * <pre>
+ * Notes:
+ * (1) There are 2 options for (x,y) values:
+ * o To plot an array vs a linear function of the
+ * index, set %nax = NULL.
+ * o To plot one array vs another, use both %nax and %nay.
+ * (2) If %nax is NULL, the x value corresponding to the i-th
+ * value of %nay is found from the startx and delx fields
+ * in %nay:
+ * x = startx + i * delx
+ * These are set with numaSetParameters(). Their default
+ * values are startx = 0.0, delx = 1.0.
+ * (3) If %nax is defined, it must be the same size as %nay, and
+ * must have at least one number.
+ * (4) The 'plotlabel' string can have spaces, double
+ * quotes and backquotes, but not single quotes.
+ * </pre>
+ */
+l_ok
+gplotAddPlot(GPLOT *gplot,
+ NUMA *nax,
+ NUMA *nay,
+ l_int32 plotstyle,
+ const char *plotlabel)
+{
+char buf[Bufsize];
+char emptystring[] = "";
+char *datastr, *title;
+l_int32 n, i;
+l_float32 valx, valy, startx, delx;
+SARRAY *sa;
+
+ PROCNAME("gplotAddPlot");
+
+ if (!gplot)
+ return ERROR_INT("gplot not defined", procName, 1);
+ if (!nay)
+ return ERROR_INT("nay not defined", procName, 1);
+ if (plotstyle < 0 || plotstyle >= NUM_GPLOT_STYLES)
+ return ERROR_INT("invalid plotstyle", procName, 1);
+
+ if ((n = numaGetCount(nay)) == 0)
+ return ERROR_INT("no points to plot", procName, 1);
+ if (nax && (n != numaGetCount(nax)))
+ return ERROR_INT("nax and nay sizes differ", procName, 1);
+ if (n == 1 && plotstyle == GPLOT_LINES) {
+ L_INFO("only 1 pt; changing style to points\n", procName);
+ plotstyle = GPLOT_POINTS;
+ }
+
+ /* Save plotstyle and plotlabel */
+ numaGetParameters(nay, &startx, &delx);
+ numaAddNumber(gplot->plotstyles, plotstyle);
+ if (plotlabel) {
+ title = stringNew(plotlabel);
+ sarrayAddString(gplot->plotlabels, title, L_INSERT);
+ } else {
+ sarrayAddString(gplot->plotlabels, emptystring, L_COPY);
+ }
+
+ /* Generate and save data filename */
+ gplot->nplots++;
+ snprintf(buf, Bufsize, "%s.data.%d", gplot->rootname, gplot->nplots);
+ sarrayAddString(gplot->datanames, buf, L_COPY);
+
+ /* Generate data and save as a string */
+ sa = sarrayCreate(n);
+ for (i = 0; i < n; i++) {
+ if (nax)
+ numaGetFValue(nax, i, &valx);
+ else
+ valx = startx + i * delx;
+ numaGetFValue(nay, i, &valy);
+ snprintf(buf, Bufsize, "%f %f\n", valx, valy);
+ sarrayAddString(sa, buf, L_COPY);
+ }
+ datastr = sarrayToString(sa, 0);
+ sarrayAddString(gplot->plotdata, datastr, L_INSERT);
+ sarrayDestroy(&sa);
+
+ return 0;
+}
+
+
+/*!
+ * \brief gplotSetScaling()
+ *
+ * \param[in] gplot
+ * \param[in] scaling GPLOT_LINEAR_SCALE, GPLOT_LOG_SCALE_X,
+ * GPLOT_LOG_SCALE_Y, GPLOT_LOG_SCALE_X_Y
+ * \return 0 if OK; 1 on error
+ *
+ * <pre>
+ * Notes:
+ * (1) By default, the x and y axis scaling is linear.
+ * (2) Call this function to set semi-log or log-log scaling.
+ * </pre>
+ */
+l_ok
+gplotSetScaling(GPLOT *gplot,
+ l_int32 scaling)
+{
+ PROCNAME("gplotSetScaling");
+
+ if (!gplot)
+ return ERROR_INT("gplot not defined", procName, 1);
+ if (scaling != GPLOT_LINEAR_SCALE &&
+ scaling != GPLOT_LOG_SCALE_X &&
+ scaling != GPLOT_LOG_SCALE_Y &&
+ scaling != GPLOT_LOG_SCALE_X_Y)
+ return ERROR_INT("invalid gplot scaling", procName, 1);
+ gplot->scaling = scaling;
+ return 0;
+}
+
+
+/*!
+ * \brief gplotMakeOutputPix()
+ *
+ * \param[in] gplot
+ * \return 0 if OK; 1 on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This wraps gplotMakeOutput(), and returns a pix.
+ * See gplotMakeOutput() for details.
+ * (2) The gplot output format must be an image (png or pnm).
+ * </pre>
+ */
+PIX *
+gplotMakeOutputPix(GPLOT *gplot)
+{
+ PROCNAME("gplotMakeOutputPix");
+
+ if (!gplot)
+ return (PIX *)ERROR_PTR("gplot not defined", procName, NULL);
+ if (gplot->outformat != GPLOT_PNG && gplot->outformat != GPLOT_PNM)
+ return (PIX *)ERROR_PTR("output format not an image", procName, NULL);
+
+ if (gplotMakeOutput(gplot))
+ return (PIX *)ERROR_PTR("plot output not made", procName, NULL);
+ return pixRead(gplot->outname);
+}
+
+
+/*!
+ * \brief gplotMakeOutput()
+ *
+ * \param[in] gplot
+ * \return 0 if OK; 1 on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This uses gplot and the new arrays to add a plot
+ * to the output, by writing a new data file and appending
+ * the appropriate plot commands to the command file.
+ * (2) Along with gplotMakeOutputPix(), these are the only functions
+ * in this file that requires the gnuplot executable to
+ * actually generate the plot.
+ * (3) The command file name for unix is canonical (i.e., directory /tmp)
+ * but the temp filename paths in the command file must be correct.
+ * (4) The gnuplot program for windows is wgnuplot.exe.
+ * </pre>
+ */
+l_ok
+gplotMakeOutput(GPLOT *gplot)
+{
+char buf[Bufsize];
+char *cmdname;
+
+ PROCNAME("gplotMakeOutput");
+
+ if (!gplot)
+ return ERROR_INT("gplot not defined", procName, 1);
+
+ if (!LeptDebugOK) {
+ L_INFO("running gnuplot is disabled; "
+ "use setLeptDebugOK(1) to enable\n", procName);
+ return 0;
+ }
+
+#ifdef OS_IOS /* iOS 11 does not support system() */
+ return ERROR_INT("iOS 11 does not support system()", procName, 0);
+#endif /* OS_IOS */
+
+ gplotGenCommandFile(gplot);
+ gplotGenDataFiles(gplot);
+ cmdname = genPathname(gplot->cmdname, NULL);
+
+#ifndef _WIN32
+ snprintf(buf, Bufsize, "gnuplot %s", cmdname);
+#else
+ snprintf(buf, Bufsize, "wgnuplot %s", cmdname);
+#endif /* _WIN32 */
+
+ callSystemDebug(buf); /* gnuplot || wgnuplot */
+ LEPT_FREE(cmdname);
+ return 0;
+}
+
+
+/*!
+ * \brief gplotGenCommandFile()
+ *
+ * \param[in] gplot
+ * \return 0 if OK, 1 on error
+ */
+l_ok
+gplotGenCommandFile(GPLOT *gplot)
+{
+char buf[Bufsize];
+char *cmdstr, *plotlabel, *dataname;
+l_int32 i, plotstyle, nplots;
+FILE *fp;
+
+ PROCNAME("gplotGenCommandFile");
+
+ if (!gplot)
+ return ERROR_INT("gplot not defined", procName, 1);
+
+ /* Remove any previous command data */
+ sarrayClear(gplot->cmddata);
+
+ /* Generate command data instructions */
+ if (gplot->title) { /* set title */
+ snprintf(buf, Bufsize, "set title '%s'", gplot->title);
+ sarrayAddString(gplot->cmddata, buf, L_COPY);
+ }
+ if (gplot->xlabel) { /* set xlabel */
+ snprintf(buf, Bufsize, "set xlabel '%s'", gplot->xlabel);
+ sarrayAddString(gplot->cmddata, buf, L_COPY);
+ }
+ if (gplot->ylabel) { /* set ylabel */
+ snprintf(buf, Bufsize, "set ylabel '%s'", gplot->ylabel);
+ sarrayAddString(gplot->cmddata, buf, L_COPY);
+ }
+
+ /* Set terminal type and output */
+ if (gplot->outformat == GPLOT_PNG) {
+ snprintf(buf, Bufsize, "set terminal png; set output '%s'",
+ gplot->outname);
+ } else if (gplot->outformat == GPLOT_PS) {
+ snprintf(buf, Bufsize, "set terminal postscript; set output '%s'",
+ gplot->outname);
+ } else if (gplot->outformat == GPLOT_EPS) {
+ snprintf(buf, Bufsize, "set terminal postscript eps; set output '%s'",
+ gplot->outname);
+ } else if (gplot->outformat == GPLOT_LATEX) {
+ snprintf(buf, Bufsize, "set terminal latex; set output '%s'",
+ gplot->outname);
+ } else if (gplot->outformat == GPLOT_PNM) {
+ snprintf(buf, Bufsize, "set terminal pbm color; set output '%s'",
+ gplot->outname);
+ }
+ sarrayAddString(gplot->cmddata, buf, L_COPY);
+
+ if (gplot->scaling == GPLOT_LOG_SCALE_X ||
+ gplot->scaling == GPLOT_LOG_SCALE_X_Y) {
+ snprintf(buf, Bufsize, "set logscale x");
+ sarrayAddString(gplot->cmddata, buf, L_COPY);
+ }
+ if (gplot->scaling == GPLOT_LOG_SCALE_Y ||
+ gplot->scaling == GPLOT_LOG_SCALE_X_Y) {
+ snprintf(buf, Bufsize, "set logscale y");
+ sarrayAddString(gplot->cmddata, buf, L_COPY);
+ }
+
+ nplots = sarrayGetCount(gplot->datanames);
+ for (i = 0; i < nplots; i++) {
+ plotlabel = sarrayGetString(gplot->plotlabels, i, L_NOCOPY);
+ dataname = sarrayGetString(gplot->datanames, i, L_NOCOPY);
+ numaGetIValue(gplot->plotstyles, i, &plotstyle);
+ if (nplots == 1) {
+ snprintf(buf, Bufsize, "plot '%s' title '%s' %s",
+ dataname, plotlabel, gplotstylenames[plotstyle]);
+ } else {
+ if (i == 0)
+ snprintf(buf, Bufsize, "plot '%s' title '%s' %s, \\",
+ dataname, plotlabel, gplotstylenames[plotstyle]);
+ else if (i < nplots - 1)
+ snprintf(buf, Bufsize, " '%s' title '%s' %s, \\",
+ dataname, plotlabel, gplotstylenames[plotstyle]);
+ else
+ snprintf(buf, Bufsize, " '%s' title '%s' %s",
+ dataname, plotlabel, gplotstylenames[plotstyle]);
+ }
+ sarrayAddString(gplot->cmddata, buf, L_COPY);
+ }
+
+ /* Write command data to file */
+ cmdstr = sarrayToString(gplot->cmddata, 1);
+ if ((fp = fopenWriteStream(gplot->cmdname, "w")) == NULL) {
+ LEPT_FREE(cmdstr);
+ return ERROR_INT("cmd stream not opened", procName, 1);
+ }
+ fwrite(cmdstr, 1, strlen(cmdstr), fp);
+ fclose(fp);
+ LEPT_FREE(cmdstr);
+ return 0;
+}
+
+
+/*!
+ * \brief gplotGenDataFiles()
+ *
+ * \param[in] gplot
+ * \return 0 if OK, 1 on error
+ *
+ * <pre>
+ * Notes:
+ * (1) The pathnames in the gplot command file are actual pathnames,
+ * which can be in temp directories. Consequently, they must not be
+ * rewritten by calling fopenWriteStream(), and we use fopen().
+ * </pre>
+ */
+l_ok
+gplotGenDataFiles(GPLOT *gplot)
+{
+char *plotdata, *dataname;
+l_int32 i, nplots;
+FILE *fp;
+
+ PROCNAME("gplotGenDataFiles");
+
+ if (!gplot)
+ return ERROR_INT("gplot not defined", procName, 1);
+
+ nplots = sarrayGetCount(gplot->datanames);
+ for (i = 0; i < nplots; i++) {
+ plotdata = sarrayGetString(gplot->plotdata, i, L_NOCOPY);
+ dataname = sarrayGetString(gplot->datanames, i, L_NOCOPY);
+ if ((fp = fopen(dataname, "w")) == NULL)
+ return ERROR_INT("datafile stream not opened", procName, 1);
+ fwrite(plotdata, 1, strlen(plotdata), fp);
+ fclose(fp);
+ }
+
+ return 0;
+}
+
+
+/*-----------------------------------------------------------------*
+ * Quick one-line plots *
+ *-----------------------------------------------------------------*/
+/*!
+ * \brief gplotSimple1()
+ *
+ * \param[in] na numa; plot Y_VS_I
+ * \param[in] outformat GPLOT_PNG, GPLOT_PS, GPLOT_EPS,
+ * GPLOT_LATEX, GPLOT_PNM
+ * \param[in] outroot root of output files
+ * \param[in] title [optional], can be NULL
+ * \return 0 if OK, 1 on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This generates a line plot of a numa, where the array value
+ * is plotted vs the array index. The plot is generated
+ * in the specified output format; the title is optional.
+ * (2) When calling these simple plot functions more than once, use
+ * different %outroot to avoid overwriting the output files.
+ * </pre>
+ */
+l_ok
+gplotSimple1(NUMA *na,
+ l_int32 outformat,
+ const char *outroot,
+ const char *title)
+{
+GPLOT *gplot;
+
+ PROCNAME("gplotSimple1");
+
+ gplot = gplotSimpleXY1(NULL, na, GPLOT_LINES, outformat, outroot, title);
+ if (!gplot)
+ return ERROR_INT("failed to generate plot", procName, 1);
+ gplotDestroy(&gplot);
+ return 0;
+}
+
+
+/*!
+ * \brief gplotSimple2()
+ *
+ * \param[in] na1 numa; plot with Y_VS_I
+ * \param[in] na2 ditto
+ * \param[in] outformat GPLOT_PNG, GPLOT_PS, GPLOT_EPS,
+ * GPLOT_LATEX, GPLOT_PNM
+ * \param[in] outroot root of output files
+ * \param[in] title [optional]
+ * \return 0 if OK, 1 on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This generates a line plot of two numa, where the array values
+ * are each plotted vs the array index. The plot is generated
+ * in the specified output format; the title is optional.
+ * (2) When calling these simple plot functions more than once, use
+ * different %outroot to avoid overwriting the output files.
+ * </pre>
+ */
+l_ok
+gplotSimple2(NUMA *na1,
+ NUMA *na2,
+ l_int32 outformat,
+ const char *outroot,
+ const char *title)
+{
+GPLOT *gplot;
+
+ PROCNAME("gplotSimple2");
+
+ gplot = gplotSimpleXY2(NULL, na1, na2, GPLOT_LINES,
+ outformat, outroot, title);
+ if (!gplot)
+ return ERROR_INT("failed to generate plot", procName, 1);
+ gplotDestroy(&gplot);
+ return 0;
+}
+
+
+/*!
+ * \brief gplotSimpleN()
+ *
+ * \param[in] naa numaa; plot Y_VS_I for each numa
+ * \param[in] outformat GPLOT_PNG, GPLOT_PS, GPLOT_EPS,
+ * GPLOT_LATEX, GPLOT_PNM
+ * \param[in] outroot root of output files
+ * \param[in] title [optional]
+ * \return 0 if OK, 1 on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This generates a line plot of all numas in a numaa (array of numa),
+ * where the array values are each plotted vs the array index.
+ * The plot is generated in the specified output format;
+ * the title is optional.
+ * (2) When calling these simple plot functions more than once, use
+ * different %outroot to avoid overwriting the output files.
+ * </pre>
+ */
+l_ok
+gplotSimpleN(NUMAA *naa,
+ l_int32 outformat,
+ const char *outroot,
+ const char *title)
+{
+GPLOT *gplot;
+
+ PROCNAME("gplotSimpleN");
+
+ gplot = gplotSimpleXYN(NULL, naa, GPLOT_LINES, outformat, outroot, title);
+ if (!gplot)
+ return ERROR_INT("failed to generate plot", procName, 1);
+ gplotDestroy(&gplot);
+ return 0;
+}
+
+
+/*!
+ * \brief gplotSimplePix1()
+ *
+ * \param[in] na numa; plot Y_VS_I
+ * \param[in] title [optional], can be NULL
+ * \return pix of plot, or null on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This generates a line plot of a numa as a pix, where the array
+ * value is plotted vs the array index. The title is optional.
+ * (2) The temporary plot file is a png; its name is generated internally
+ * and stored in gplot.
+ * </pre>
+ */
+PIX *
+gplotSimplePix1(NUMA *na,
+ const char *title)
+{
+char buf[64];
+static l_int32 index;
+GPLOT *gplot;
+PIX *pix;
+
+ PROCNAME("gplotSimplePix1");
+
+ if (!na)
+ return (PIX *)ERROR_PTR("na not defined", procName, NULL);
+
+ lept_mkdir("lept/gplot/pix");
+ snprintf(buf, sizeof(buf), "/tmp/lept/gplot/pix1.%d", index++);
+ gplot = gplotSimpleXY1(NULL, na, GPLOT_LINES, GPLOT_PNG, buf, title);
+ if (!gplot)
+ return (PIX *)ERROR_PTR("failed to generate plot", procName, NULL);
+ pix = pixRead(gplot->outname);
+ gplotDestroy(&gplot);
+ if (!pix)
+ return (PIX *)ERROR_PTR("failed to generate plot", procName, NULL);
+ return pix;
+}
+
+
+/*!
+ * \brief gplotSimplePix2()
+ *
+ * \param[in] na1 numa; plot with Y_VS_I
+ * \param[in] na2 ditto
+ * \param[in] title [optional], can be NULL
+ * \return pix of plot, or null on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This generates a pix with line plots of two numa, where each of
+ * two arrays is plotted vs the array index. the title is optional.
+ * (2) The temporary plot file is a png; its name is generated internally
+ * and stored in gplot.
+ * </pre>
+ */
+PIX *
+gplotSimplePix2(NUMA *na1,
+ NUMA *na2,
+ const char *title)
+{
+char buf[64];
+static l_int32 index;
+GPLOT *gplot;
+PIX *pix;
+
+ PROCNAME("gplotSimplePix2");
+
+ if (!na1 || !na2)
+ return (PIX *)ERROR_PTR("both na1, na2 not defined", procName, NULL);
+
+ lept_mkdir("lept/gplot/pix");
+ snprintf(buf, sizeof(buf), "/tmp/lept/gplot/pix2.%d", index++);
+ gplot = gplotSimpleXY2(NULL, na1, na2, GPLOT_LINES, GPLOT_PNG, buf, title);
+ if (!gplot)
+ return (PIX *)ERROR_PTR("failed to generate plot", procName, NULL);
+ pix = pixRead(gplot->outname);
+ gplotDestroy(&gplot);
+ if (!pix)
+ return (PIX *)ERROR_PTR("failed to generate plot", procName, NULL);
+ return pix;
+}
+
+
+/*!
+ * \brief gplotSimplePixN()
+ *
+ * \param[in] naa numaa; plot Y_VS_I for each numa
+ * \param[in] title [optional], can be NULL
+ * \return pix of plot, or null on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This generates a pix with an arbitrary number of line plots,
+ * each coming from a numa in %naa. Each array value is plotted
+ * vs the array index. The title is optional.
+ * (2) The temporary plot file is a png; its name is generated internally
+ * and stored in gplot.
+ * </pre>
+ */
+PIX *
+gplotSimplePixN(NUMAA *naa,
+ const char *title)
+{
+char buf[64];
+static l_int32 index;
+GPLOT *gplot;
+PIX *pix;
+
+ PROCNAME("gplotSimplePixN");
+
+ if (!naa)
+ return (PIX *)ERROR_PTR("naa not defined", procName, NULL);
+
+ lept_mkdir("lept/gplot/pix");
+ snprintf(buf, sizeof(buf), "/tmp/lept/gplot/pixN.%d", index++);
+ gplot = gplotSimpleXYN(NULL, naa, GPLOT_LINES, GPLOT_PNG, buf, title);
+ if (!gplot)
+ return (PIX *)ERROR_PTR("failed to generate plot", procName, NULL);
+ pix = pixRead(gplot->outname);
+ gplotDestroy(&gplot);
+ if (!pix)
+ return (PIX *)ERROR_PTR("failed to generate plot", procName, NULL);
+ return pix;
+}
+
+
+/*!
+ * \brief gplotSimpleXY1()
+ *
+ * \param[in] nax [optional]
+ * \param[in] nay [required]
+ * \param[in] plotstyle GPLOT_LINES, GPLOT_POINTS, GPLOT_IMPULSES,
+ * GPLOT_LINESPOINTS, GPLOT_DOTS
+ * \param[in] outformat GPLOT_PNG, GPLOT_PS, GPLOT_EPS,
+ * GPLOT_LATEX, GPLOT_PNM
+ * \param[in] outroot root of output files
+ * \param[in] title [optional], can be NULL
+ * \return gplot or null on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This generates a plot of a %nay vs %nax, generated in
+ * the specified output format. The title is optional.
+ * (2) Use 0 for default plotstyle (lines).
+ * (3) %nax is optional. If NULL, %nay is plotted against
+ * the array index.
+ * (4) When calling these simple plot functions more than once, use
+ * different %outroot to avoid overwriting the output files.
+ * (5) The returned gplot must be destroyed by the caller.
+ * </pre>
+ */
+GPLOT *
+gplotSimpleXY1(NUMA *nax,
+ NUMA *nay,
+ l_int32 plotstyle,
+ l_int32 outformat,
+ const char *outroot,
+ const char *title)
+{
+GPLOT *gplot;
+
+ PROCNAME("gplotSimpleXY1");
+
+ if (!nay)
+ return (GPLOT *)ERROR_PTR("nay not defined", procName, NULL);
+ if (plotstyle < 0 || plotstyle >= NUM_GPLOT_STYLES)
+ return (GPLOT *)ERROR_PTR("invalid plotstyle", procName, NULL);
+ if (outformat != GPLOT_PNG && outformat != GPLOT_PS &&
+ outformat != GPLOT_EPS && outformat != GPLOT_LATEX &&
+ outformat != GPLOT_PNM)
+ return (GPLOT *)ERROR_PTR("invalid outformat", procName, NULL);
+ if (!outroot)
+ return (GPLOT *)ERROR_PTR("outroot not specified", procName, NULL);
+
+ if ((gplot = gplotCreate(outroot, outformat, title, NULL, NULL)) == 0)
+ return (GPLOT *)ERROR_PTR("gplot not made", procName, NULL);
+ gplotAddPlot(gplot, nax, nay, plotstyle, NULL);
+ gplotMakeOutput(gplot);
+ return gplot;
+}
+
+
+/*!
+ * \brief gplotSimpleXY2()
+ *
+ * \param[in] nax [optional], can be NULL
+ * \param[in] nay1
+ * \param[in] nay2
+ * \param[in] plotstyle GPLOT_LINES, GPLOT_POINTS, GPLOT_IMPULSES,
+ * GPLOT_LINESPOINTS, GPLOT_DOTS
+ * \param[in] outformat GPLOT_PNG, GPLOT_PS, GPLOT_EPS,
+ * GPLOT_LATEX, GPLOT_PNM
+ * \param[in] outroot root of output files
+ * \param[in] title [optional]
+ * \return gplot or null on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This generates plots of %nay1 and %nay2 against %nax, generated
+ * in the specified output format. The title is optional.
+ * (2) Use 0 for default plotstyle (lines).
+ * (3) %nax is optional. If NULL, %nay1 and %nay2 are plotted
+ * against the array index.
+ * (4) When calling these simple plot functions more than once, use
+ * different %outroot to avoid overwriting the output files.
+ * (5) The returned gplot must be destroyed by the caller.
+ * </pre>
+ */
+GPLOT *
+gplotSimpleXY2(NUMA *nax,
+ NUMA *nay1,
+ NUMA *nay2,
+ l_int32 plotstyle,
+ l_int32 outformat,
+ const char *outroot,
+ const char *title)
+{
+GPLOT *gplot;
+
+ PROCNAME("gplotSimpleXY2");
+
+ if (!nay1 || !nay2)
+ return (GPLOT *)ERROR_PTR("nay1 and nay2 not both defined",
+ procName, NULL);
+ if (plotstyle < 0 || plotstyle >= NUM_GPLOT_STYLES)
+ return (GPLOT *)ERROR_PTR("invalid plotstyle", procName, NULL);
+ if (outformat != GPLOT_PNG && outformat != GPLOT_PS &&
+ outformat != GPLOT_EPS && outformat != GPLOT_LATEX &&
+ outformat != GPLOT_PNM)
+ return (GPLOT *)ERROR_PTR("invalid outformat", procName, NULL);
+ if (!outroot)
+ return (GPLOT *)ERROR_PTR("outroot not specified", procName, NULL);
+
+ if ((gplot = gplotCreate(outroot, outformat, title, NULL, NULL)) == 0)
+ return (GPLOT *)ERROR_PTR("gplot not made", procName, NULL);
+ gplotAddPlot(gplot, nax, nay1, plotstyle, NULL);
+ gplotAddPlot(gplot, nax, nay2, plotstyle, NULL);
+ gplotMakeOutput(gplot);
+ return gplot;
+}
+
+
+/*!
+ * \brief gplotSimpleXYN()
+ *
+ * \param[in] nax [optional]; can be NULL
+ * \param[in] naay numaa of arrays to plot against %nax
+ * \param[in] plotstyle GPLOT_LINES, GPLOT_POINTS, GPLOT_IMPULSES,
+ * GPLOT_LINESPOINTS, GPLOT_DOTS
+ * \param[in] outformat GPLOT_PNG, GPLOT_PS, GPLOT_EPS,
+ * GPLOT_LATEX, GPLOT_PNM
+ * \param[in] outroot root of output files
+ * \param[in] title [optional]
+ * \return gplot or null on error
+ *
+ * <pre>
+ * Notes:
+ * (1) This generates plots of each Numa in %naa against %nax,
+ * generated in the specified output format. The title is optional.
+ * (2) Use 0 for default plotstyle (lines).
+ * (3) %nax is optional. If NULL, each Numa array is plotted against
+ * the array index.
+ * (4) When calling these simple plot functions more than once, use
+ * different %outroot to avoid overwriting the output files.
+ * (5) The returned gplot must be destroyed by the caller.
+ * </pre>
+ */
+GPLOT *
+gplotSimpleXYN(NUMA *nax,
+ NUMAA *naay,
+ l_int32 plotstyle,
+ l_int32 outformat,
+ const char *outroot,
+ const char *title)
+{
+l_int32 i, n;
+GPLOT *gplot;
+NUMA *nay;
+
+ PROCNAME("gplotSimpleXYN");
+
+ if (!naay)
+ return (GPLOT *)ERROR_PTR("naay not defined", procName, NULL);
+ if ((n = numaaGetCount(naay)) == 0)
+ return (GPLOT *)ERROR_PTR("no numa in array", procName, NULL);
+ if (plotstyle < 0 || plotstyle >= NUM_GPLOT_STYLES)
+ return (GPLOT *)ERROR_PTR("invalid plotstyle", procName, NULL);
+ if (outformat != GPLOT_PNG && outformat != GPLOT_PS &&
+ outformat != GPLOT_EPS && outformat != GPLOT_LATEX &&
+ outformat != GPLOT_PNM)
+ return (GPLOT *)ERROR_PTR("invalid outformat", procName, NULL);
+ if (!outroot)
+ return (GPLOT *)ERROR_PTR("outroot not specified", procName, NULL);
+
+ if ((gplot = gplotCreate(outroot, outformat, title, NULL, NULL)) == 0)
+ return (GPLOT *)ERROR_PTR("gplot not made", procName, NULL);
+ for (i = 0; i < n; i++) {
+ nay = numaaGetNuma(naay, i, L_CLONE);
+ gplotAddPlot(gplot, nax, nay, plotstyle, NULL);
+ numaDestroy(&nay);
+ }
+ gplotMakeOutput(gplot);
+ return gplot;
+}
+
+
+/*!
+ * \brief gplotGeneralPix1()
+ *
+ * \param[in] na data array
+ * \param[in] plotstyle GPLOT_LINES, GPLOT_POINTS, GPLOT_IMPULSES,
+ * GPLOT_LINESPOINTS, GPLOT_DOTS
+ * \param[in] rootname root for all output files
+ * \param[in] title [optional] overall title
+ * \param[in] xlabel [optional] x axis label
+ * \param[in] ylabel [optional] y axis label
+ * \return pix of plot, or NULL on error
+ *
+ * <pre>
+ * Notes:
+ * (1) The 'title', 'xlabel' and 'ylabel' strings can have spaces,
+ * double quotes and backquotes, but not single quotes.
+ * </pre>
+ */
+PIX *
+gplotGeneralPix1(NUMA *na,
+ l_int32 plotstyle,
+ const char *rootname,
+ const char *title,
+ const char *xlabel,
+ const char *ylabel)
+{
+GPLOT *gplot;
+PIX *pix;
+
+ PROCNAME("gplotGeneralPix1");
+
+ if (!na)
+ return (PIX *)ERROR_PTR("na not defined", procName, NULL);
+ if (plotstyle < 0 || plotstyle >= NUM_GPLOT_STYLES)
+ return (PIX *)ERROR_PTR("invalid plotstyle", procName, NULL);
+ if (!rootname)
+ return (PIX *)ERROR_PTR("rootname not defined", procName, NULL);
+
+ gplot = gplotCreate(rootname, GPLOT_PNG, title, xlabel, ylabel);
+ if (!gplot)
+ return (PIX *)ERROR_PTR("gplot not made", procName, NULL);
+ gplotAddPlot(gplot, NULL, na, plotstyle, NULL);
+ pix = gplotMakeOutputPix(gplot);
+ gplotDestroy(&gplot);
+ return pix;
+}
+
+
+/*!
+ * \brief gplotGeneralPix2()
+ *
+ * \param[in] na1 x-axis data array
+ * \param[in] na2 y-axis data array
+ * \param[in] plotstyle GPLOT_LINES, GPLOT_POINTS, GPLOT_IMPULSES,
+ * GPLOT_LINESPOINTS, GPLOT_DOTS
+ * \param[in] rootname root for all output files
+ * \param[in] title [optional] overall title
+ * \param[in] xlabel [optional] x axis label
+ * \param[in] ylabel [optional] y axis label
+ * \return pix of plot, or NULL on error
+ *
+ * <pre>
+ * Notes:
+ * (1) The 'title', 'xlabel' and 'ylabel' strings can have spaces,
+ * double quotes and backquotes, but not single quotes.
+ * </pre>
+ */
+PIX *
+gplotGeneralPix2(NUMA *na1,
+ NUMA *na2,
+ l_int32 plotstyle,
+ const char *rootname,
+ const char *title,
+ const char *xlabel,
+ const char *ylabel)
+{
+GPLOT *gplot;
+PIX *pix;
+
+ PROCNAME("gplotGeneralPix2");
+
+ if (!na1)
+ return (PIX *)ERROR_PTR("na1 not defined", procName, NULL);
+ if (!na2)
+ return (PIX *)ERROR_PTR("na2 not defined", procName, NULL);
+ if (plotstyle < 0 || plotstyle >= NUM_GPLOT_STYLES)
+ return (PIX *)ERROR_PTR("invalid plotstyle", procName, NULL);
+ if (!rootname)
+ return (PIX *)ERROR_PTR("rootname not defined", procName, NULL);
+
+ gplot = gplotCreate(rootname, GPLOT_PNG, title, xlabel, ylabel);
+ if (!gplot)
+ return (PIX *)ERROR_PTR("gplot not made", procName, NULL);
+ gplotAddPlot(gplot, na1, na2, plotstyle, NULL);
+ pix = gplotMakeOutputPix(gplot);
+ gplotDestroy(&gplot);
+ return pix;
+}
+
+
+/*!
+ * \brief gplotGeneralPixN()
+ *
+ * \param[in] nax x-axis data array
+ * \param[in] naay array of y-axis data arrays
+ * \param[in] plotstyle GPLOT_LINES, GPLOT_POINTS, GPLOT_IMPULSES,
+ * GPLOT_LINESPOINTS, GPLOT_DOTS
+ * \param[in] rootname root for all output files
+ * \param[in] title [optional] overall title
+ * \param[in] xlabel [optional] x axis label
+ * \param[in] ylabel [optional] y axis label
+ * \return pix of plot, or NULL on error
+ *
+ * <pre>
+ * Notes:
+ * (1) The 'title', 'xlabel' and 'ylabel' strings can have spaces,
+ * double quotes and backquotes, but not single quotes.
+ * </pre>
+ */
+PIX *
+gplotGeneralPixN(NUMA *nax,
+ NUMAA *naay,
+ l_int32 plotstyle,
+ const char *rootname,
+ const char *title,
+ const char *xlabel,
+ const char *ylabel)
+{
+l_int32 i, n;
+GPLOT *gplot;
+NUMA *nay;
+PIX *pix;
+
+ PROCNAME("gplotGeneralPixN");
+
+ if (!nax)
+ return (PIX *)ERROR_PTR("nax not defined", procName, NULL);
+ if (!naay)
+ return (PIX *)ERROR_PTR("naay not defined", procName, NULL);
+ if ((n = numaaGetCount(naay)) == 0)
+ return (PIX *)ERROR_PTR("no numa in array", procName, NULL);
+ if (plotstyle < 0 || plotstyle >= NUM_GPLOT_STYLES)
+ return (PIX *)ERROR_PTR("invalid plotstyle", procName, NULL);
+ if (!rootname)
+ return (PIX *)ERROR_PTR("rootname not defined", procName, NULL);
+
+ gplot = gplotCreate(rootname, GPLOT_PNG, title, xlabel, ylabel);
+ if (!gplot)
+ return (PIX *)ERROR_PTR("gplot not made", procName, NULL);
+ for (i = 0; i < n; i++) {
+ nay = numaaGetNuma(naay, i, L_CLONE);
+ gplotAddPlot(gplot, nax, nay, plotstyle, NULL);
+ numaDestroy(&nay);
+ }
+ pix = gplotMakeOutputPix(gplot);
+ gplotDestroy(&gplot);
+ return pix;
+}
+
+
+/*-----------------------------------------------------------------*
+ * Serialize for I/O *
+ *-----------------------------------------------------------------*/
+/*!
+ * \brief gplotRead()
+ *
+ * \param[in] filename
+ * \return gplot, or NULL on error
+ */
+GPLOT *
+gplotRead(const char *filename)
+{
+char buf[Bufsize];
+char *rootname, *title, *xlabel, *ylabel, *ignores;
+l_int32 outformat, ret, version, ignore;
+FILE *fp;
+GPLOT *gplot;
+
+ PROCNAME("gplotRead");
+
+ if (!filename)
+ return (GPLOT *)ERROR_PTR("filename not defined", procName, NULL);
+
+ if ((fp = fopenReadStream(filename)) == NULL)
+ return (GPLOT *)ERROR_PTR("stream not opened", procName, NULL);
+
+ ret = fscanf(fp, "Gplot Version %d\n", &version);
+ if (ret != 1) {
+ fclose(fp);
+ return (GPLOT *)ERROR_PTR("not a gplot file", procName, NULL);
+ }
+ if (version != GPLOT_VERSION_NUMBER) {
+ fclose(fp);
+ return (GPLOT *)ERROR_PTR("invalid gplot version", procName, NULL);
+ }
+
+ ignore = fscanf(fp, "Rootname: %511s\n", buf); /* Bufsize - 1 */
+ rootname = stringNew(buf);
+ ignore = fscanf(fp, "Output format: %d\n", &outformat);
+ ignores = fgets(buf, Bufsize, fp); /* Title: ... */
+ title = stringNew(buf + 7);
+ title[strlen(title) - 1] = '\0';
+ ignores = fgets(buf, Bufsize, fp); /* X axis label: ... */
+ xlabel = stringNew(buf + 14);
+ xlabel[strlen(xlabel) - 1] = '\0';
+ ignores = fgets(buf, Bufsize, fp); /* Y axis label: ... */
+ ylabel = stringNew(buf + 14);
+ ylabel[strlen(ylabel) - 1] = '\0';
+
+ gplot = gplotCreate(rootname, outformat, title, xlabel, ylabel);
+ LEPT_FREE(rootname);
+ LEPT_FREE(title);
+ LEPT_FREE(xlabel);
+ LEPT_FREE(ylabel);
+ if (!gplot) {
+ fclose(fp);
+ return (GPLOT *)ERROR_PTR("gplot not made", procName, NULL);
+ }
+ sarrayDestroy(&gplot->cmddata);
+ sarrayDestroy(&gplot->datanames);
+ sarrayDestroy(&gplot->plotdata);
+ sarrayDestroy(&gplot->plotlabels);
+ numaDestroy(&gplot->plotstyles);
+
+ ignore = fscanf(fp, "Commandfile name: %511s\n", buf); /* Bufsize - 1 */
+ stringReplace(&gplot->cmdname, buf);
+ ignore = fscanf(fp, "\nCommandfile data:");
+ gplot->cmddata = sarrayReadStream(fp);
+ ignore = fscanf(fp, "\nDatafile names:");
+ gplot->datanames = sarrayReadStream(fp);
+ ignore = fscanf(fp, "\nPlot data:");
+ gplot->plotdata = sarrayReadStream(fp);
+ ignore = fscanf(fp, "\nPlot titles:");
+ gplot->plotlabels = sarrayReadStream(fp);
+ ignore = fscanf(fp, "\nPlot styles:");
+ gplot->plotstyles = numaReadStream(fp);
+
+ ignore = fscanf(fp, "Number of plots: %d\n", &gplot->nplots);
+ ignore = fscanf(fp, "Output file name: %511s\n", buf);
+ stringReplace(&gplot->outname, buf);
+ ignore = fscanf(fp, "Axis scaling: %d\n", &gplot->scaling);
+
+ fclose(fp);
+ return gplot;
+}
+
+
+/*!
+ * \brief gplotWrite()
+ *
+ * \param[in] filename
+ * \param[in] gplot
+ * \return 0 if OK; 1 on error
+ */
+l_ok
+gplotWrite(const char *filename,
+ GPLOT *gplot)
+{
+FILE *fp;
+
+ PROCNAME("gplotWrite");
+
+ if (!filename)
+ return ERROR_INT("filename not defined", procName, 1);
+ if (!gplot)
+ return ERROR_INT("gplot not defined", procName, 1);
+
+ if ((fp = fopenWriteStream(filename, "wb")) == NULL)
+ return ERROR_INT("stream not opened", procName, 1);
+
+ fprintf(fp, "Gplot Version %d\n", GPLOT_VERSION_NUMBER);
+ fprintf(fp, "Rootname: %s\n", gplot->rootname);
+ fprintf(fp, "Output format: %d\n", gplot->outformat);
+ fprintf(fp, "Title: %s\n", gplot->title);
+ fprintf(fp, "X axis label: %s\n", gplot->xlabel);
+ fprintf(fp, "Y axis label: %s\n", gplot->ylabel);
+
+ fprintf(fp, "Commandfile name: %s\n", gplot->cmdname);
+ fprintf(fp, "\nCommandfile data:");
+ sarrayWriteStream(fp, gplot->cmddata);
+ fprintf(fp, "\nDatafile names:");
+ sarrayWriteStream(fp, gplot->datanames);
+ fprintf(fp, "\nPlot data:");
+ sarrayWriteStream(fp, gplot->plotdata);
+ fprintf(fp, "\nPlot titles:");
+ sarrayWriteStream(fp, gplot->plotlabels);
+ fprintf(fp, "\nPlot styles:");
+ numaWriteStderr(gplot->plotstyles);
+
+ fprintf(fp, "Number of plots: %d\n", gplot->nplots);
+ fprintf(fp, "Output file name: %s\n", gplot->outname);
+ fprintf(fp, "Axis scaling: %d\n", gplot->scaling);
+
+ fclose(fp);
+ return 0;
+}