PLplot 5.9.6
plimage.c
00001 /* plimage()
00002  *
00003  * Author: Alessandro Mirone, Nov 2001
00004  * Adapted: Joao Cardoso
00005  * Updated: Hezekiah Carty 2008
00006  *
00007  * Copyright (C) 2004  Alan W. Irwin
00008  *
00009  * This file is part of PLplot.
00010  *
00011  * PLplot is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Library Public License as published
00013  * by the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * PLplot is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU Library General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Library General Public License
00022  * along with PLplot; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00024  */
00025 
00026 #include "plplotP.h"
00027 
00028 #define COLOR_MIN        0.0
00029 #define COLOR_MAX        1.0
00030 #define COLOR_NO_PLOT    ( -1.0 )
00031 
00032 /* Get better names, those are too cryptic!
00033  *
00034  * ZEROW2B: zero writing to buffer ?
00035  * ZEROW2D: zero writing to display ?
00036  * ONEW2B: set writing to buffer ?
00037  * ONEW2D: set writing to display ?
00038  */
00039 
00040 void
00041 NoBufferNoPixmap()
00042 {
00043     PLINT op = ZEROW2B;
00044 
00045     plsc->plbuf_write = 0; /* TODO: store previous state */
00046     plP_esc( PLESC_EXPOSE, NULL );
00047     plP_esc( PLESC_IMAGEOPS, &op );
00048 }
00049 
00050 void
00051 RestoreWrite2BufferPixmap()
00052 {
00053     PLINT op = ONEW2B;
00054 
00055     plsc->plbuf_write = 1; /* TODO: revert from previous state */
00056     plP_esc( PLESC_IMAGEOPS, &op );
00057 }
00058 
00059 void
00060 disabledisplay()
00061 {
00062     PLINT op = ZEROW2D;
00063 
00064     plP_esc( PLESC_IMAGEOPS, &op );
00065 }
00066 
00067 void
00068 enabledisplay()
00069 {
00070     PLINT op = ONEW2D;
00071 
00072     plP_esc( PLESC_IMAGEOPS, &op );
00073     plP_esc( PLESC_EXPOSE, NULL );
00074 }
00075 
00076 
00077 
00078 /*
00079  * NOTE: The plshade* functions require that both pltr and pltr_data are set
00080  * in order for pltr to be used.  plimageslow does NOT require this, so it is
00081  * up to the user to make sure pltr_data is something non-NULL if pltr
00082  * requires it.
00083  * Plottable values in idata must be scaled between COLOR_MIN and COLOR_MAX.
00084  * This is an internal function, and should not be used directly.  Its
00085  * interface may change.
00086  */
00087 void
00088 plimageslow( PLFLT *idata, PLINT nx, PLINT ny,
00089              PLFLT xmin, PLFLT ymin, PLFLT dx, PLFLT dy,
00090              void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
00091              PLPointer pltr_data )
00092 {
00093     /* Indices */
00094     PLINT ix, iy, i;
00095     /* Float coordinates */
00096     PLFLT xf[4], yf[4];
00097     /* Translated (by pltr) coordinates */
00098     PLFLT tx, ty;
00099     /* The corners of a single filled region */
00100     /* int corners[4]; - unreferenced */
00101     /* The color to use in the fill */
00102     PLFLT color;
00103 
00104     plP_esc( PLESC_START_RASTERIZE, NULL );
00105     for ( ix = 0; ix < nx; ix++ )
00106     {
00107         for ( iy = 0; iy < ny; iy++ )
00108         {
00109             /* Only plot values within in appropriate range */
00110             color = idata[ix * ny + iy];
00111             if ( color == COLOR_NO_PLOT )
00112                 continue;
00113 
00114             /* The color value has to be scaled to 0.0 -> 1.0 plcol1 color values */
00115             plcol1( color / COLOR_MAX );
00116 
00117             xf[0] = xf[1] = ix;
00118             xf[2] = xf[3] = ix + 1;
00119             yf[0] = yf[3] = iy;
00120             yf[1] = yf[2] = iy + 1;
00121 
00122             if ( pltr )
00123             {
00124                 for ( i = 0; i < 4; i++ )
00125                 {
00126                     /* Translate the points */
00127                     ( *pltr )( xf[i], yf[i], &tx, &ty, pltr_data );
00128                     xf[i] = tx;
00129                     yf[i] = ty;
00130                 }
00131             }
00132             else
00133             {
00134                 for ( i = 0; i < 4; i++ )
00135                 {
00136                     /* Automatic translation to the specified plot area */
00137                     xf[i] = xmin + xf[i] * dx;
00138                     yf[i] = ymin + yf[i] * dy;
00139                 }
00140             }
00141             plfill( 4, xf, yf );
00142         }
00143     }
00144     plP_esc( PLESC_END_RASTERIZE, NULL );
00145 }
00146 
00147 void
00148 grimage( short *x, short *y, unsigned short *z, PLINT nx, PLINT ny )
00149 {
00150     plsc->dev_ix    = x;
00151     plsc->dev_iy    = y;
00152     plsc->dev_z     = z;
00153     plsc->dev_nptsX = nx;
00154     plsc->dev_nptsY = ny;
00155 
00156     plP_esc( PLESC_IMAGE, NULL );
00157 }
00158 
00159 /*-------------------------------------------------------------------------*\
00160  * plimagefr
00161  *
00162  * arguments are
00163  *   idata: array containing image data
00164  *   nx: dimension of the array in the X axis.
00165  *   ny: dimension of the  array in the Y axis
00166  *   The array data is indexed like data[ix][iy]
00167  *
00168  *   xmin, xmax, ymin, ymax:
00169  *       data[0][0] corresponds to (xmin,ymin)
00170  *       data[nx-1][ny-1] to (xmax,ymax)
00171  *
00172  *   zmin, zmax:
00173  *       only data within bounds zmin <= data <= zmax will be
00174  *       plotted. If zmin == zmax, all data will be ploted.
00175  *
00176  *   valuemin, valuemax:
00177  *       The minimum and maximum values to use for value -> color
00178  *       mappings.  A value in idata of valuemin or less will have
00179  *       color 0.0 and a value in idata of valuemax or greater will
00180  *       have color 1.0.  Values between valuemin and valuemax will
00181  *       map linearly to to the colors between 0.0 and 1.0.
00182  *       If you do not want to display values outside of the
00183  *       (valuemin -> valuemax) range, then set zmin = valuemin and
00184  *       zmax = valuemax.
00185  *       This allows for multiple plots to use the same color scale
00186  *       with a consistent value -> color mapping, regardless of the
00187  *       image content.
00188  *
00189  \*-------------------------------------------------------------------------*/
00190 void
00191 c_plimagefr( PLFLT **idata, PLINT nx, PLINT ny,
00192              PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
00193              PLFLT valuemin, PLFLT valuemax,
00194              void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
00195              PLPointer pltr_data )
00196 {
00197     plfimagefr( plf2ops_c(), ( PLPointer ) idata, nx, ny,
00198         xmin, xmax, ymin, ymax, zmin, zmax,
00199         valuemin, valuemax, pltr, pltr_data );
00200 }
00201 
00202 void
00203 plfimagefr( PLF2OPS idataops, PLPointer idatap, PLINT nx, PLINT ny,
00204             PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
00205             PLFLT valuemin, PLFLT valuemax,
00206             void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
00207             PLPointer pltr_data )
00208 {
00209     PLINT ix, iy;
00210     PLFLT dx, dy;
00211     /* z holds scaled image pixel values */
00212     PLFLT *z;
00213     /* This is used when looping through the image array, checking to
00214      * make sure the values are within an acceptable range. */
00215     PLFLT datum;
00216     /* Color palette 0 color in use before the plimage* call */
00217     PLINT init_color;
00218 
00219     if ( plsc->level < 3 )
00220     {
00221         plabort( "plimagefr: window must be set up first" );
00222         return;
00223     }
00224 
00225     if ( nx <= 0 || ny <= 0 )
00226     {
00227         plabort( "plimagefr: nx and ny must be positive" );
00228         return;
00229     }
00230 
00231     if ( ( z = (PLFLT *) malloc( ny * nx * sizeof ( PLFLT ) ) ) == NULL )
00232     {
00233         plexit( "plimagefr: Insufficient memory" );
00234     }
00235 
00236     /* Save the currently-in-use color. */
00237     init_color = plsc->icol0;
00238 
00239     /* If no acceptable data range is given, then set the min/max data range
00240      * to include all of the given data. */
00241     if ( zmin == zmax )
00242     {
00243         /* Find the minimum and maximum values in the image */
00244         idataops->minmax( idatap, nx, ny, &zmin, &zmax );
00245     }
00246 
00247     /* Go through the image values and scale them to fit in
00248      * the COLOR_MIN to COLOR_MAX range.
00249      * Any values greater than valuemax are set to valuemax,
00250      * and values less than valuemin are set to valuemin.
00251      * Any values outside of zmin to zmax are flagged so they
00252      * are not plotted. */
00253     for ( ix = 0; ix < nx; ix++ )
00254     {
00255         for ( iy = 0; iy < ny; iy++ )
00256         {
00257             if ( valuemin == valuemax )
00258             {
00259                 /* If valuemin == valuemax, avoid dividing by zero. */
00260                 z[ix * ny + iy] = ( COLOR_MAX + COLOR_MIN ) / 2.0;
00261             }
00262             else
00263             {
00264                 datum = idataops->get( idatap, ix, iy );
00265                 if ( isnan( datum ) || datum < zmin || datum > zmax )
00266                 {
00267                     /* Set to a guaranteed-not-to-plot value */
00268                     z[ix * ny + iy] = COLOR_NO_PLOT;
00269                 }
00270                 else
00271                 {
00272                     if ( datum < valuemin )
00273                     {
00274                         datum = valuemin;
00275                     }
00276                     else if ( datum > valuemax )
00277                     {
00278                         datum = valuemax;
00279                     }
00280                     /* Set to a value scaled between COLOR_MIN and COLOR_MAX. */
00281                     z[ix * ny + iy] =
00282                         ( datum - valuemin + COLOR_MIN ) / ( valuemax - valuemin ) * COLOR_MAX;
00283                 }
00284             }
00285         }
00286     }
00287 
00288     /* dx and dy are the plot-coordinates pixel sizes for an untransformed
00289      * image */
00290     dx = ( xmax - xmin ) / (PLFLT) nx;
00291     dy = ( ymax - ymin ) / (PLFLT) ny;
00292 
00293     plP_image( z, nx, ny, xmin, ymin, dx, dy, pltr, pltr_data );
00294 
00295     plcol0( init_color );
00296 
00297     free( z );
00298 }
00299 
00300 /*-------------------------------------------------------------------------*\
00301  * plimage
00302  *
00303  * arguments are
00304  *   idata: array containing image data
00305  *   nx: dimension of the array in the X axis.
00306  *   ny: dimension of the  array in the Y axis
00307  *   The array data is indexed like data[ix][iy]
00308  *
00309  *   xmin, xmax, ymin, ymax:
00310  *       data[0][0] corresponds to (xmin,ymin)
00311  *       data[nx-1][ny-1] to (xmax,ymax)
00312  *
00313  *   zmin, zmax:
00314  *       only data within bounds zmin <= data <= zmax will be
00315  *       plotted. If zmin == zmax, all data will be ploted.
00316  *
00317  *   Dxmin, Dxmax, Dymin, Dymax:
00318  *       plots only the window of points whose(x,y)'s fall
00319  *       inside the [Dxmin->Dxmax]X[Dymin->Dymax] window
00320  *
00321  \*-------------------------------------------------------------------------*/
00322 void
00323 c_plimage( PLFLT **idata, PLINT nx, PLINT ny,
00324            PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
00325            PLFLT Dxmin, PLFLT Dxmax, PLFLT Dymin, PLFLT Dymax )
00326 {
00327     plfimage( plf2ops_c(), (PLPointer) idata, nx, ny,
00328         xmin, xmax, ymin, ymax, zmin, zmax,
00329         Dxmin, Dxmax, Dymin, Dymax );
00330 }
00331 
00332 void
00333 plfimage( PLF2OPS idataops, PLPointer idatap, PLINT nx, PLINT ny,
00334           PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
00335           PLFLT Dxmin, PLFLT Dxmax, PLFLT Dymin, PLFLT Dymax )
00336 {
00337     PLINT   ix, iy, ixx, iyy, xm, ym, nnx, nny;
00338     PLFLT   data_min, data_max, dx, dy;
00339     /* z holds the subimage (Dxmin, Dymin) - (Dxmax, Dymax) */
00340     PLFLT   **z;
00341     PLF2OPS zops;
00342     /* Was any space allocated for z? */
00343     PLBOOL  copied;
00344     copied = FALSE;
00345 
00346     if ( nx <= 0 || ny <= 0 )
00347     {
00348         plabort( "plimage: nx and ny must be positive" );
00349         return;
00350     }
00351 
00352     if ( Dxmin < xmin || Dxmax > xmax || Dymin < ymin || Dymax > ymax )
00353     {
00354         plabort( "plimage: Dxmin or Dxmax or Dymin or Dymax not compatible with xmin or xmax or ymin or ymax." );
00355         return;
00356     }
00357 
00358     if ( Dxmax < Dxmin || xmax < xmin || Dymax < Dymin || ymax < ymin )
00359     {
00360         plabort( "plimage: All (Dxmin < Dxmax) and (Dymin < Dymax) and (xmin < xmax) and (ymin < ymax) must hold." );
00361         return;
00362     }
00363 
00364     /* Find the minimum and maximum values in the image.  Use these values to
00365      * for the color scale range. */
00366     idataops->minmax( idatap, nx, ny, &data_min, &data_max );
00367 
00368     if ( xmin == Dxmin && xmax == Dxmax && ymin == Dymin && ymax == Dymax )
00369     {
00370         /* If the whole image should be shown, then no copying is needed. */
00371         z    = (PLFLT **) idatap;
00372         zops = idataops;
00373         nnx  = nx;
00374         nny  = ny;
00375     }
00376     else
00377     {
00378         /* dx and dy are the plot-coordinates pixel sizes for an untransformed
00379          * image */
00380         dx = ( xmax - xmin ) / (PLFLT) nx;
00381         dy = ( ymax - ymin ) / (PLFLT) ny;
00382 
00383         /* Pixel dimensions of the (Dxmin, Dymin) to (Dxmax, Dymax) box */
00384         nnx = (PLINT) ceil( ( Dxmax - Dxmin ) / dx );
00385         nny = (PLINT) ceil( ( Dymax - Dymin ) / dy );
00386 
00387         /* Call plimagefr with the value -> color range mapped to the minimum
00388          * Offsets for the idata indices to select
00389          * (Dxmin, Dymin) to (Dxmax, Dymax) */
00390         xm = (PLINT) floor( ( Dxmin - xmin ) / dx );
00391         ym = (PLINT) floor( ( Dymin - ymin ) / dy );
00392 
00393         /* Allocate space for the sub-image */
00394         plAlloc2dGrid( &z, nnx, nny );
00395         zops = plf2ops_c();
00396 
00397         /* Go through the image and select the pixels within the given
00398          * (Dxmin, Dymin) - (Dxmax, Dymax) window. */
00399         ixx = -1;
00400         for ( ix = xm; ix < xm + nnx; ix++ )
00401         {
00402             ixx++; iyy = 0;
00403             for ( iy = ym; iy < ym + nny; iy++ )
00404             {
00405                 z[ixx][iyy++] = idataops->get( idatap, ix, iy );
00406             }
00407         }
00408 
00409         /* Set the appropriate values to pass in to plimagefr */
00410         copied = TRUE;
00411     }
00412 
00413     plfimagefr( zops, (PLPointer) z, nnx, nny, Dxmin, Dxmax, Dymin, Dymax, zmin, zmax,
00414         data_min, data_max, NULL, NULL );
00415 
00416     /* Only free the memory if it was allocated by us... */
00417     if ( copied == TRUE )
00418     {
00419         plFree2dGrid( z, nnx, nny );
00420     }
00421 }
 All Data Structures Files Functions