On Wed, Mar 19, 2008 at 2:31 PM, Andrew Ross
<[EMAIL PROTECTED]> wrote:
>
> On Wed, Mar 19, 2008 at 01:12:24PM -0500, Maurice LeBrun wrote:
> > On Wednesday, March 19, 2008 at 10:14:30 (-0700) Alan W. Irwin writes:
> > > On 2008-03-19 10:59-0400 Hezekiah M. Carty wrote:
> > >
> > > > To sum up, I would like to submit patches in the follow steps:
> > > > (1) Add coordinate transform to plimagefr and disable the dev_fastimg
> > > > rendering path, but without removing the dev_fastimg code.
> > > > (2) Update dev_fastimg to work with the updated plimagefr, but only
> > > > use it for non-transformed images.
> > > > (3) Update example 20 with some examples of what plimagefr can do,
> > > > with pages to illustrate both fixed color ranges and coordinate
> > > > transformations.
> > > >
> > > > Does this sound like a reasonable compromise?
> > >
> > > Hi Hez:
> > >
> > > Actually after sleeping on it, I am leaning toward saying do (1) (with
> code
> > > commentary where you do the disabling in plimage.c, xwin.c, etc., about
> why
> > > it was necessary) and leave (2) as a would-be-nice rather than a
> requirement
> > > since it sounds like it might be a lot of work which you could more
> > > productively spend on the OCaml bindings, for example.
> > >
> > > However, I don't feel right making this decision alone because I haven't
> > > used -dev xwin or the plimage capability for my own PLplot needs, and
> > > somebody who has more of a vested interest in those parts of PLplot may
> feel
> > > a lot stronger about their speed than I do. Thus, I am going to need
> > > advice/help from the other PLplot core developers on the decision about
> (1)
> > > and (2) so please step forward, guys, and comment.
> >
> > I use -dev xwin extensively (and its client, plframe) but not plimage.
> That
> > said, doing (1) and leaving/documenting (2) as a nice-to-have sounds fine
> to
> > me, unless someone can make a case otherwise.
>
> Ditto.
Thank you for all of the feedback, and sorry for the delayed response.
As I am sure is the case for many of you, using PLplot for research
got in the way of developing PLplot...
The attached patch does the following:
- Disables the dev_fastimg rendering path. This is done in a
(hopefully) minimally invasive manner. No dev_fastimg code is
deleted, just commented out when needed with a comment explaining why
and that this is intended to be temporary.
- Adds coordinate transformation (pltr callback) support to plimagefr
- Removes the Dxmin, Dxmax, Dymin, Dymax arguments from plimagefr as
they do not make sense when using a coordinate transform. The
associated code/logic is moved in to plimage to keep its interface and
function consistent with how it has worked in the past.
- Should fix the (occasional) off-by-one bug in the number of image
pixel rows/columns rendered when selecting a sub-image in plimage.
- Updates api.xml to reflect the changes to plimagefr.
Example 20 updates are not in place yet, but I will add them once we
get this patch sorted out.
This version of the patch works well for me.
Some questions:
- Should the name stay as plimagefr? I do not have any better ideas
at this time, but with the addition of the coordinate transform
support someone may have other naming suggestions.
- What is the proper way to restore the initial drawing color when
these functions end? Currently a call to plimage or plimagefr will
leave the color set to whichever color palette 1 color was used for
the last pixel. Ideally the color at entry would be saved at the
start of the function and set again at the end of the function. I see
examples elsewhere in the code which are specific to color palette 0
or color palette 1, but I would like to do this in a generic fashion,
regardless of the color palette in use before the call to
plimage/plimagefr.
> > Ideally someone would play with dev_fastimg vs !dev_fastimg and see if
> there's
> > a noticeable difference on mondern hardware. I'm sure many here have seen
> > hardware advances make irrelevant some "optimizations" done previously, or
> at
> > least mitigate performance concerns.
>
> I agree. If it turns out that dev_fastimg really is useful then I would
> encourage you to think about (2), i.e. still using dev_fastimg for the
> no-transform case at least. Without the tests it is hard to comment
> though.
There is a speed difference between the two - running example 20 using
the xwin driver under PLplot 5.9.0 is quicker than with the attached
patch. This only applies for the xwin driver though, as none of the
other output drivers have dev_fastimg support. Adding dev_fastimg
support back in should probably involve input from the output driver
maintainers so that the interface is reasonably easily implemented and
kept in sync with the currently popular and maintained drivers.
That said, the speed difference is negligible for smaller images. The
speed of example 20 is different but not very noticeable on my laptop
(Pentium-M 1.7ghz) though this may add up to be significant if many
images were plotted. I do not know what the speed difference would be
for 1000x1000 and larger image arrays.
I think the speed issue comes from using plfill to draw every pixel of
the image. This is how the previous implementation of the slow
rendering path works as well. The xwin dev_fastimg approach uses a
custom rasterizer in xwin.c which this patch comments out.
> > For example, the X driver was first developed on 8-bit r/w color displays
> and
> > sharing a single r/w colormap was the norm. If this didn't suffice for the
> > application, a custom colormap could be used (which I never liked very
> much).
> > Seems so quaint now. :) But when I went to 16 or 24 bit r/o colormaps on a
> > Linux box years later, the performance degradation of swapping out colors
> > really didn't seem to matter much. One of these days I'd like to give the
> > xwin driver a bit of housecleaning, starting with chopping out the custom
> > colormap support that was never really used anyway.
>
> If you can find the time, it sounds like a good idea! I still
> extensively use the xwin driver. I prefer it over the more sophisticated
> gnome driver for example for many purposes because it is quick and
> clean.
I use the xwin driver quite often as well, largely because of the
threading support. This makes it easier to quickly see results in an
interactive environment.
> P.S. Hez, is the bug fix easy to tease out from the rest of your patch?
> We should at least apply that as we think about the rest it. Committing
> this separately also makes it clear what is bug fix and what is new
> feature. This can be useful when looking back through the commits. If
> the bug is only fixed because the broken code is replaced, then don't
> worry about it.
The bug fix is something that I tackled during the rewrite, rather
than as a separate issue. I think that the bug would be fixed by
changing the following lines in plimage.c, function c_plimagefr, line
205:
dx = (xmax - xmin) / (nx - 1);
dy = (ymax - ymin) / (ny - 1);
nnx = (Dxmax-Dxmin)/dx + 1;
nny = (Dymax-Dymin)/dy + 1;
to:
dx = (xmax - xmin) / (PLFLT)nx;
dy = (ymax - ymin) / (PLFLT)ny;
nnx = ceil((Dxmax - Dxmin) / dx);
nny = ceil((Dymax - Dymin) / dy);
I have only tested this briefly, but I think it should do the trick.
My apologies for not providing a separate patch - I am not sure that
this will fix the issue, but I think it should.
Thanks again for the feedback,
Hez
--
Hezekiah M. Carty
Graduate Research Assistant
University of Maryland
Department of Atmospheric and Oceanic Science
diff --git a/doc/docbook/src/api.xml b/doc/docbook/src/api.xml
index 517e0a5..1650f68 100644
--- a/doc/docbook/src/api.xml
+++ b/doc/docbook/src/api.xml
@@ -5531,12 +5531,10 @@ device coordinates
<paramdef><parameter>ymax</parameter></paramdef>
<paramdef><parameter>zmin</parameter></paramdef>
<paramdef><parameter>zmax</parameter></paramdef>
- <paramdef><parameter>Dxmin</parameter></paramdef>
- <paramdef><parameter>Dxmax</parameter></paramdef>
- <paramdef><parameter>Dymin</parameter></paramdef>
- <paramdef><parameter>Dymax</parameter></paramdef>
<paramdef><parameter>valuemin</parameter></paramdef>
<paramdef><parameter>valuemax</parameter></paramdef>
+ <paramdef><parameter>pltr</parameter></paramdef>
+ <paramdef><parameter>pltr_data</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</para>
@@ -5595,28 +5593,52 @@ device coordinates
</varlistentry>
<varlistentry>
<term>
- <parameter>Dxmin, Dxmax, Dymin, Dymax</parameter>
+ <parameter>valuemin, valuemax</parameter>
(<literal>PLFLT</literal>, input)
</term>
<listitem>
<para>
- Plot only the window of points whose plot coordinates fall inside
- the window of (Dxmin, Dymin) to (Dxmax, Dymax).
+ The minimum and maximum data values to use for value to color
+ mappings. A datum equal to or less than valuemin will be
+ plotted with color 0.0, while a datum equal to or greater than
+ valuemax will be plotted with color 1.0. Data between valuemin
+ and valuemax map linearly to colors between 0.0 and 1.0.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
- <parameter>valuemin, valuemax</parameter>
- (<literal>PLFLT</literal>, input)
+ <parameter>pltr</parameter>
+ (<literal>void (*) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer)
+ </literal>, input)
</term>
<listitem>
<para>
- The minimum and maximum data values to use for value to color
- mappings. A datum equal to or less than valuemin will be
- plotted with color 0.0, while a datum equal to or greater than
- valuemax will be plotted with color 1.0. Data between valuemin
- and valuemax map linearly to colors between 0.0 and 1.0.
+ Pointer to function that defines transformation between indices
+ in array <literal><parameter>idata</parameter></literal> and the
+ world coordinates (C only). Transformation functions are
+ provided in the PLplot library:
+ &pltr0; for identity mapping, and &pltr1; and &pltr2; for
+ arbitrary mappings respectively defined by one- and
+ two-dimensional arrays. In addition, user-supplied routines
+ for the transformation can be used as well. Examples of
+ all of these approaches are given in
+ <xref linkend="contour-plots-c"/>.
+ The transformation function should
+ have the form given by any of &pltr0;, &pltr1;, or &pltr2;.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <parameter>pltr_data</parameter>
+ (<literal>PLPointer</literal>, input)
+ </term>
+ <listitem>
+ <para>
+ Extra parameter to help
+ pass information to &pltr0;, &pltr1;, &pltr2;, or whatever routine
+ that is externally supplied.
</para>
</listitem>
</varlistentry>
@@ -5630,8 +5652,7 @@ device coordinates
General:
<function>
plimagefr(idata, xmin, xmax, ymin, ymax,
- zmin, zmax, Dxmin, Dxmax, Dymin, Dymax,
- valuemin, valuemax)
+ zmin, zmax, valuemin, valuemax, pltr, pltr_data)
</function>
</para>
</listitem>
diff --git a/include/plplot.h b/include/plplot.h
index adf7e09..c978ddd 100644
--- a/include/plplot.h
+++ b/include/plplot.h
@@ -1460,9 +1460,10 @@ c_plstripd(PLINT id);
PLDLLIMPEXP void
c_plimagefr(PLFLT **idata, PLINT nx, PLINT ny,
- PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
- PLFLT Dxmin, PLFLT Dxmax, PLFLT Dymin, PLFLT Dymax,
- PLFLT valuemin, PLFLT valuemax);
+ PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
+ PLFLT valuemin, PLFLT valuemax,
+ void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer),
+ PLPointer pltr_data);
/* plots a 2d image (or a matrix too large for plshade() ) - colors
automatically scaled */
diff --git a/include/plplotP.h b/include/plplotP.h
index 3d9f8fe..8415497 100644
--- a/include/plplotP.h
+++ b/include/plplotP.h
@@ -874,7 +874,8 @@ plP_fill(short *x, short *y, PLINT npts);
/* draw image */
void
-plP_image(short *x, short *y, unsigned short *z, PLINT nx, PLINT ny, PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy, unsigned short zmin, unsigned short zmax);
+plP_image(PLFLT *z, PLINT nx, PLINT ny, PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy,
+ void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer), PLPointer pltr_data);
/* End of page */
@@ -956,9 +957,10 @@ int PLDLLIMPEXP
plInBuildTree();
void
-plimageslow(short *x, short *y, unsigned short *data, PLINT nx, PLINT ny,
- PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy,
- unsigned short zmin, unsigned short zmax);
+plimageslow(PLFLT *idata, PLINT nx, PLINT ny,
+ PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy,
+ void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer),
+ PLPointer pltr_data);
typedef struct {
PLFLT xmin, ymin, dx, dy;} IMG_DT;
diff --git a/src/plbuf.c b/src/plbuf.c
index f95b4e4..c8dcfce 100644
--- a/src/plbuf.c
+++ b/src/plbuf.c
@@ -659,7 +659,12 @@ rdbuf_image(PLStream *pls)
rd_data(pls, dev_iy, sizeof(short) * npts);
rd_data(pls, dev_z, sizeof(unsigned short) * (nptsX-1)*(nptsY-1));
- plP_image(dev_ix, dev_iy, dev_z, nptsX, nptsY, xmin, ymin, dx, dy, dev_zmin, dev_zmax);
+ /*
+ * COMMENTED OUT by Hezekiah Carty
+ * Commented (hopefullly temporarily) until the dev_fastimg rendering path
+ * can be updated to support the new plimage internals.
+ */
+ //plP_image(dev_ix, dev_iy, dev_z, nptsX, nptsY, xmin, ymin, dx, dy, dev_zmin, dev_zmax);
free(dev_ix);
free(dev_iy);
diff --git a/src/plcore.c b/src/plcore.c
index c8b9afd..95ce622 100644
--- a/src/plcore.c
+++ b/src/plcore.c
@@ -3418,13 +3418,30 @@ return(ret);
*
* Author: Alessandro Mirone, Nov 2001
*
- *
+ * Updated by Hezekiah Carty, Mar 2008.
+ * - Added support for pltr callback
+ * - Commented out the "dev_fastimg" rendering path
*
\*--------------------------------------------------------------------------*/
void
-plP_image(short *x, short *y, unsigned short *z , PLINT nx, PLINT ny, PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy, unsigned short zmin, unsigned short zmax)
+plP_image(PLFLT *z , PLINT nx, PLINT ny, PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy,
+ void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer), PLPointer pltr_data)
{
+ plsc->page_status = DRAWING;
+
+ plimageslow(z, nx, ny, xmin, ymin, dx, dy, pltr, pltr_data);
+
+ /*
+ * COMMENTED OUT by Hezekiah Carty, March 2008
+ * The current dev_fastimg rendering method does not work as-is with
+ * the plimagefr coordinate transform support.
+ * This is hopefully temporary, until the dev_fastimg rendering
+ * path can be updated to work with the new plimage internals.
+ * Until then, all plimage* rendering is done by the plimageslow
+ * rendering path.
+ */
+ /* BEGIN dev_fastimg COMMENT ***
PLINT i, npts;
short *xscl, *yscl;
int plbuf_write;
@@ -3456,12 +3473,12 @@ plP_image(short *x, short *y, unsigned short *z , PLINT nx, PLINT ny, PLFLT xmin
plbuf_esc(plsc, PLESC_IMAGE, &img_dt);
}
- /* avoid re-saving plot buffer while in plP_esc() */
+ // avoid re-saving plot buffer while in plP_esc()
plbuf_write = plsc->plbuf_write;
plsc->plbuf_write = 0;
npts = nx*ny;
- if (plsc->difilt) { /* isn't this odd? when replaying the plot buffer, e.g., when resizing the window, difilt() is caled again! the plot buffer should already contain the transformed data--it would save a lot of time! (and allow for differently oriented plots when in multiplot mode) */
+ if (plsc->difilt) { // isn't this odd? when replaying the plot buffer, e.g., when resizing the window, difilt() is caled again! the plot buffer should already contain the transformed data--it would save a lot of time! (and allow for differently oriented plots when in multiplot mode)
PLINT clpxmi, clpxma, clpymi, clpyma;
if (((xscl = (short *) malloc(nx*ny*sizeof(short)))==NULL)||
@@ -3490,4 +3507,5 @@ plP_image(short *x, short *y, unsigned short *z , PLINT nx, PLINT ny, PLFLT xmin
grimage(x, y, z, nx, ny );
}
plsc->plbuf_write = plbuf_write;
+ *** END dev_fastimg COMMENT */
}
diff --git a/src/plimage.c b/src/plimage.c
index 67be368..9d15200 100644
--- a/src/plimage.c
+++ b/src/plimage.c
@@ -2,6 +2,7 @@
*
* Author: Alessandro Mirone, Nov 2001
* Adapted: Joao Cardoso
+ * Updated: Hezekiah Carty 2008
*
* Copyright (C) 2004 Alan W. Irwin
*
@@ -24,6 +25,10 @@
#include "plplotP.h"
+#define COLOR_MIN 0.0
+#define COLOR_MAX 1.0
+#define COLOR_NO_PLOT (-1.0)
+
/* Get better names, those are too criptic!
*
* ZEROW2B: zero writing to buffer ?
@@ -70,55 +75,63 @@ enabledisplay()
+/*
+ * NOTE: The plshade* functions require that both pltr and pltr_data are set
+ * in order for pltr to be used. plimageslow does NOT require this, so it is
+ * up to the user to make sure pltr_data is something non-NULL if pltr
+ * requires it.
+ * Plottable values in idata must be scaled between COLOR_MIN and COLOR_MAX.
+ * This is an internal function, and should not be used directly. Its
+ * interface may change.
+ */
void
-plimageslow(short *x, short *y, unsigned short *data, PLINT nx, PLINT ny,
- PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy,
- unsigned short zmin, unsigned short zmax)
+plimageslow(PLFLT *idata, PLINT nx, PLINT ny,
+ PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy,
+ void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer),
+ PLPointer pltr_data)
{
+ // Indices
PLINT ix, iy, i;
+ // Float coordinates
PLFLT xf[4], yf[4];
- short xs[5], ys[5];
+ // Translated (by pltr) coordinates
+ PLFLT tx, ty;
+ // The corners of a single filled region
int corners[4];
- unsigned short col;
+ // The color to use in the fill
+ PLFLT color;
for (ix = 0; ix < nx ; ix++) {
for (iy = 0; iy < ny ; iy++) {
-
- col = data[ix*ny+iy];
- /* only plot points within zmin/zmax range */
- if (col < zmin || col > zmax)
- continue;
-
- plcol1(col/(float)USHRT_MAX);
-
- if (plsc->plbuf_read == 1) {
- /* buffer read, is a replot to a slow device. */
-
- corners[0] = ix*(ny+1)+iy; /* [ix][iy] */
- corners[1] = (ix+1)*(ny+1)+iy; /* [ix+1][iy] */
- corners[2] = (ix+1)*(ny+1)+iy+1; /* [ix+1][iy+1] */
- corners[3] = ix*(ny+1)+iy+1; /* [ix][iy+1] */
-
- for (i = 0; i < 4; i++) {
- xs[i] = x[corners[i]];
- ys[i] = y[corners[i]];
- }
- xs[4] = xs[0]; ys[4] = ys[0];
- plP_fill(xs, ys, 5);
-
- } else {
-
- xf[0] = xf[1] = ix;
- xf[2] = xf[3] = ix+1;
- yf[0] = yf[3] = iy;
- yf[1] = yf[2] = iy+1;
-
- for (i = 0; i < 4; i++) {
- xf[i] = xmin + xf[i]*dx;
- yf[i] = ymin + yf[i]*dy;
- }
- plfill(4, xf, yf);
+ // Only plot values within in appropriate range
+ color = idata[ix * ny + iy];
+ if (color == COLOR_NO_PLOT)
+ continue;
+
+ // The color value has to be scaled to 0.0 -> 1.0 plcol1 color values
+ plcol1(color / COLOR_MAX);
+
+ xf[0] = xf[1] = ix;
+ xf[2] = xf[3] = ix + 1;
+ yf[0] = yf[3] = iy;
+ yf[1] = yf[2] = iy + 1;
+
+ if (pltr) {
+ for (i = 0; i < 4; i++) {
+ // Translate the points
+ (*pltr) (xf[i], yf[i], &tx, &ty, pltr_data);
+ xf[i] = tx;
+ yf[i] = ty;
+ }
}
+ else {
+ for (i = 0; i < 4; i++) {
+ // Automatic translation to the specified plot area
+ xf[i] = xmin + xf[i] * dx;
+ yf[i] = ymin + yf[i] * dy;
+ }
+ }
+ plfill(4, xf, yf);
}
}
}
@@ -152,10 +165,6 @@ grimage(short *x, short *y, unsigned short *z, PLINT nx, PLINT ny)
* only data within bounds zmin <= data <= zmax will be
* plotted. If zmin == zmax, all data will be ploted.
*
- * Dxmin, Dxmax, Dymin, Dymax:
- * plots only the window of points whose(x,y)'s fall
- * inside the [Dxmin->Dxmax]X[Dymin->Dymax] window
- *
* valuemin, valuemax:
* The minimum and maximum values to use for value -> color
* mappings. A value in idata of valuemin or less will have
@@ -170,118 +179,79 @@ grimage(short *x, short *y, unsigned short *z, PLINT nx, PLINT ny)
* image content.
*
\*-------------------------------------------------------------------------*/
-
void
c_plimagefr(PLFLT **idata, PLINT nx, PLINT ny,
PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
- PLFLT Dxmin, PLFLT Dxmax, PLFLT Dymin, PLFLT Dymax,
- PLFLT valuemin, PLFLT valuemax)
+ PLFLT valuemin, PLFLT valuemax,
+ void (*pltr) (PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer),
+ PLPointer pltr_data)
{
- PLINT nnx, nny, ix, iy, ixx, iyy, xm, ym;
+ PLINT ix, iy;
PLFLT dx, dy;
- // Zf holds transformed image pixel values
- // szmin and szmax are zmin and zmax scaled to unsigned short values
- unsigned short *Zf, szmin, szmax;
- short *Xf, *Yf;
+ // z holds scaled image pixel values
+ PLFLT *z;
// This is used when looping through the image array, checking to
// make sure the values are within an acceptable range.
PLFLT datum;
if (plsc->level < 3) {
- plabort("plimage: window must be set up first");
+ plabort("plimagefr: window must be set up first");
return;
}
if (nx <= 0 || ny <= 0) {
- plabort("plimage: nx and ny must be positive");
+ plabort("plimagefr: nx and ny must be positive");
return;
}
- if (Dxmin < xmin || Dxmax > xmax || Dymin < ymin || Dymax > ymax) {
- plabort("plimage: Dxmin or Dxmax or Dymin or Dymax not compatible with xmin or xmax or ymin or ymax.");
- return;
+ if ((z = (PLFLT *) malloc(ny * nx * sizeof(PLFLT))) == NULL) {
+ plexit("plimagefr: Insufficient memory");
}
- dx = (xmax - xmin) / (nx - 1);
- dy = (ymax - ymin) / (ny - 1);
- nnx = (Dxmax-Dxmin)/dx + 1;
- nny = (Dymax-Dymin)/dy + 1;
-
- if ((Zf = (unsigned short *) malloc(nny*nnx*sizeof(unsigned short)))==NULL)
- {
- plexit("plimage: Insufficient memory");
- }
-
- xm = floor((Dxmin-xmin)/dx); ym = floor((Dymin-ymin)/dy);
+ // If no acceptable data range is given, then set the min/max data range
+ // to include all of the given data.
+ if (zmin == zmax) {
+ // Find the minimum and maximum values in the image
+ plMinMax2dGrid(idata, nx, ny, &zmax, &zmin);
+ }
- // Go through the image values and scale them to fit in an
- // unsigned short range.
+ // Go through the image values and scale them to fit in
+ // the COLOR_MIN to COLOR_MAX range.
// Any values greater than valuemax are set to valuemax,
// and values less than valuemin are set to valuemin.
- ixx=-1;
- for (ix=xm; ix<xm+nnx; ix++) {
- ixx++; iyy=0;
- for (iy=ym; iy<ym+nny; iy++) {
+ // Any values outside of zmin to zmax are flagged so they
+ // are not plotted.
+ for (ix = 0; ix < nx; ix++) {
+ for (iy = 0; iy < ny; iy++) {
datum = idata[ix][iy];
- if (datum < valuemin) {
- datum = valuemin;
+ if (datum < zmin || datum > zmax) {
+ // Set to a guaranteed-not-to-plot value
+ z[ix * ny + iy] = COLOR_NO_PLOT;
}
- else if (datum > valuemax) {
- datum = valuemax;
+ else {
+ if (datum < valuemin) {
+ datum = valuemin;
+ }
+ else if (datum > valuemax) {
+ datum = valuemax;
+ }
+ // Set to a value scaled between COLOR_MIN and COLOR_MAX
+ z[ix * ny + iy] = (datum - valuemin) / (valuemax - valuemin);
}
- Zf[ixx*nny+iyy++] =
- (datum - valuemin) / (valuemax - valuemin) * USHRT_MAX;
}
}
- if (zmin == zmax) {
- zmin = valuemin;
- zmax = valuemax;
- }
- else {
- if (zmin < valuemin)
- zmin = valuemin;
- if (zmax > valuemax)
- zmax = valuemax;
- }
-
- // The value range to plot, scaled to unsigned short values
- szmin = (zmin - valuemin) / (valuemax - valuemin) * USHRT_MAX;
- szmax = (zmax - valuemin) / (valuemax - valuemin) * USHRT_MAX;
-
- xmin = Dxmin; xmax = Dxmax;
- ymin = Dymin; ymax = Dymax;
-
- /* The X and Y arrays has size nnx*nny */
- nnx++; nny++;
-
- if (((Xf = (short *) malloc(nny*nnx*sizeof(short)))==NULL)||
- ((Yf = (short *) malloc(nny*nnx*sizeof(short)))==NULL))
- {
- plexit("plimage: Insufficient memory");
- }
-
- /* adjust the step for the X/Y arrays */
- dx = dx*(nx-1)/nx;
- dy = dy*(ny-1)/ny;
-
- for (ix = 0; ix < nnx; ix++) {
- for (iy = 0; iy < nny; iy++) {
- Xf[ix*nny+iy] = plP_wcpcx(xmin + ix*dx);
- Yf[ix*nny+iy] = plP_wcpcy(ymin + iy*dy);
- }
- }
+ // dx and dy are the plot-coordinates pixel sizes for an untransformed image
+ dx = (xmax - xmin) / (PLFLT)nx;
+ dy = (ymax - ymin) / (PLFLT)ny;
- plP_image(Xf, Yf, Zf, nnx, nny, xmin, ymin, dx, dy, szmin, szmax);
+ plP_image(z, nx, ny, xmin, ymin, dx, dy, pltr, pltr_data);
- free(Xf);
- free(Yf);
- free(Zf);
+ free(z);
}
/*-------------------------------------------------------------------------*\
* plimage
- * (***** SUBJECT TO CHANGE ******)
*
* arguments are
* idata: array containing image data
@@ -302,31 +272,81 @@ c_plimagefr(PLFLT **idata, PLINT nx, PLINT ny,
* inside the [Dxmin->Dxmax]X[Dymin->Dymax] window
*
\*-------------------------------------------------------------------------*/
-
void
c_plimage(PLFLT **idata, PLINT nx, PLINT ny,
- PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
- PLFLT Dxmin, PLFLT Dxmax, PLFLT Dymin, PLFLT Dymax)
+ PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
+ PLFLT Dxmin, PLFLT Dxmax, PLFLT Dymin, PLFLT Dymax)
{
- PLINT ix, iy;
- PLFLT data_min, data_max, iz;
+ PLINT ix, iy, ixx, iyy, xm, ym, nnx, nny;
+ PLFLT data_min, data_max, dx, dy;
+ // z holds the subimage (Dxmin, Dymin) - (Dxmax, Dymax)
+ PLFLT **z;
+ // Was any space allocated for z?
+ PLBOOL copied;
+ copied = FALSE;
- // Find the minimum and maximum values in the image, and automatically
- // scale the colors scale over this range.
- data_min = data_max = idata[0][0];
+ if (nx <= 0 || ny <= 0) {
+ plabort("plimage: nx and ny must be positive");
+ return;
+ }
- for (ix = 0; ix < nx; ix++) {
- for (iy = 0; iy < ny; iy++) {
- iz = idata[ix][iy];
- if (data_max < iz)
- data_max = iz;
- if (data_min > iz)
- data_min = iz;
+ if (Dxmin < xmin || Dxmax > xmax || Dymin < ymin || Dymax > ymax) {
+ plabort("plimage: Dxmin or Dxmax or Dymin or Dymax not compatible with xmin or xmax or ymin or ymax.");
+ return;
+ }
+
+ if (Dxmax < Dxmin || xmax < xmin || Dymax < Dymin || ymax < ymin) {
+ plabort("plimage: All (Dxmin < Dxmax) and (Dymin < Dymax) and (xmin < xmax) and (ymin < ymax) must hold.");
+ return;
+ }
+
+ // Find the minimum and maximum values in the image. Use these values to
+ // for the color scale range.
+ plMinMax2dGrid(idata, nx, ny, &data_max, &data_min);
+
+ if (xmin == Dxmin && xmax == Dxmax && ymin == Dymin && ymax == Dymax) {
+ // If the whole image should be shown, then no copying is needed.
+ z = idata;
+ nnx = nx;
+ nny = ny;
+ }
+ else {
+ // dx and dy are the plot-coordinates pixel sizes for an untransformed image
+ dx = (xmax - xmin) / (PLFLT)nx;
+ dy = (ymax - ymin) / (PLFLT)ny;
+
+ // Pixel dimensions of the (Dxmin, Dymin) to (Dxmax, Dymax) box
+ nnx = ceil((Dxmax - Dxmin) / dx);
+ nny = ceil((Dymax - Dymin) / dy);
+
+ // Call plimagefr with the value -> color range mapped to the minimum
+ // Offsets for the idata indices to select
+ // (Dxmin, Dymin) to (Dxmax, Dymax)
+ xm = floor((Dxmin - xmin) / dx);
+ ym = floor((Dymin - ymin) / dy);
+
+ // Allocate space for the sub-image
+ plAlloc2dGrid(&z, nnx, nny);
+
+ // Go through the image and select the pixels within the given
+ // (Dxmin, Dymin) - (Dxmax, Dymax) window.
+ ixx = -1;
+ for (ix = xm; ix < xm + nnx; ix++) {
+ ixx++; iyy=0;
+ for (iy = ym; iy < ym + nny; iy++) {
+ z[ixx][iyy++] = idata[ix][iy];
+ }
}
+
+ // Set the appropriate values to pass in to plimagefr
+ copied = TRUE;
}
- // Call plimagefr with the value -> color range mapped to the minimum
- // and maximum values in idata.
- plimagefr(idata, nx, ny, xmin, xmax, ymin, ymax, zmin, zmax,
- Dxmin, Dxmax, Dymin, Dymax, data_min, data_max);
+ plimagefr(z, nnx, nny, Dxmin, Dxmax, Dymin, Dymax, zmin, zmax,
+ data_min, data_max, NULL, NULL);
+
+ // Only free the memory if it was allocated by us...
+ if (copied == TRUE) {
+ plFree2dGrid(z, nnx, nny);
+ }
}
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
Plplot-devel mailing list
Plplot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/plplot-devel