PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plimage.c
Go to the documentation of this file.
1 // plimage()
2 //
3 // Author: Alessandro Mirone, Nov 2001
4 // Adapted: Joao Cardoso
5 // Updated: Hezekiah Carty 2008
6 //
7 // Copyright (C) 2004 Alan W. Irwin
8 //
9 // This file is part of PLplot.
10 //
11 // PLplot is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU Library General Public License as published
13 // by the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // PLplot is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Library General Public License for more details.
20 //
21 // You should have received a copy of the GNU Library General Public License
22 // along with PLplot; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 
26 #include "plplotP.h"
27 
28 #define COLOR_MIN 0.0
29 #define COLOR_MAX 1.0
30 #define COLOR_NO_PLOT ( -1.0 )
31 
32 // Get better names, those are too cryptic!
33 //
34 // ZEROW2B: zero writing to buffer ?
35 // ZEROW2D: zero writing to display ?
36 // ONEW2B: set writing to buffer ?
37 // ONEW2D: set writing to display ?
38 //
39 
40 void
42 {
43  PLINT op = ZEROW2B;
44 
45  plsc->plbuf_write = 0; // TODO: store previous state
46  plP_esc( PLESC_EXPOSE, NULL );
47  plP_esc( PLESC_IMAGEOPS, &op );
48 }
49 
50 void
52 {
53  PLINT op = ONEW2B;
54 
55  plsc->plbuf_write = 1; // TODO: revert from previous state
56  plP_esc( PLESC_IMAGEOPS, &op );
57 }
58 
59 //
60 // Unused functions - comment out
61 //
62 //void
63 //disabledisplay()
64 //{
65 // PLINT op = ZEROW2D;
66 //
67 // plP_esc( PLESC_IMAGEOPS, &op );
68 //}
69 //
70 //void
71 //enabledisplay()
72 //{
73 // PLINT op = ONEW2D;
74 //
75 // plP_esc( PLESC_IMAGEOPS, &op );
76 // plP_esc( PLESC_EXPOSE, NULL );
77 //}
78 //
79 
80 
81 //
82 // NOTE: The plshade* functions require that both pltr and pltr_data are set
83 // in order for pltr to be used. plimageslow does NOT require this, so it is
84 // up to the user to make sure pltr_data is something non-NULL if pltr
85 // requires it.
86 // Plottable values in idata must be scaled between COLOR_MIN and COLOR_MAX.
87 // This is an internal function, and should not be used directly. Its
88 // interface may change.
89 //
90 void
91 plimageslow( PLFLT *idata, PLINT nx, PLINT ny,
93  void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
94  PLPointer pltr_data )
95 {
96  // Indices
97  PLINT ix, iy, i;
98  // Float coordinates
99  PLFLT xf[4], yf[4];
100  // Translated (by pltr) coordinates
101  PLFLT tx, ty;
102  // The corners of a single filled region
103  // int corners[4]; - unreferenced
104  // The color to use in the fill
105  PLFLT color;
106 
108  for ( ix = 0; ix < nx; ix++ )
109  {
110  for ( iy = 0; iy < ny; iy++ )
111  {
112  // Only plot values within in appropriate range
113  color = idata[ix * ny + iy];
114  if ( color == COLOR_NO_PLOT )
115  continue;
116 
117  // The color value has to be scaled to 0.0 -> 1.0 plcol1 color values
118  plcol1( color / COLOR_MAX );
119 
120  xf[0] = xf[1] = ix;
121  xf[2] = xf[3] = ix + 1;
122  yf[0] = yf[3] = iy;
123  yf[1] = yf[2] = iy + 1;
124 
125  if ( pltr )
126  {
127  for ( i = 0; i < 4; i++ )
128  {
129  // Translate the points
130  ( *pltr )( xf[i], yf[i], &tx, &ty, pltr_data );
131  xf[i] = tx;
132  yf[i] = ty;
133  }
134  }
135  else
136  {
137  for ( i = 0; i < 4; i++ )
138  {
139  // Automatic translation to the specified plot area
140  xf[i] = xmin + xf[i] * dx;
141  yf[i] = ymin + yf[i] * dy;
142  }
143  }
144  plfill( 4, xf, yf );
145  }
146  }
147  plP_esc( PLESC_END_RASTERIZE, NULL );
148 }
149 
150 void
151 grimage( short *x, short *y, unsigned short *z, PLINT nx, PLINT ny )
152 {
153  plsc->dev_ix = x;
154  plsc->dev_iy = y;
155  plsc->dev_z = z;
156  plsc->dev_nptsX = nx;
157  plsc->dev_nptsY = ny;
158 
159  plP_esc( PLESC_IMAGE, NULL );
160 }
161 
162 //--------------------------------------------------------------------------
163 // plimagefr
164 //
165 // arguments are
166 // idata: array containing image data
167 // nx: dimension of the array in the X axis.
168 // ny: dimension of the array in the Y axis
169 // The array data is indexed like data[ix][iy]
170 //
171 // xmin, xmax, ymin, ymax:
172 // data[0][0] corresponds to (xmin,ymin)
173 // data[nx-1][ny-1] to (xmax,ymax)
174 //
175 // zmin, zmax:
176 // only data within bounds zmin <= data <= zmax will be
177 // plotted. If zmin == zmax, all data will be ploted.
178 //
179 // valuemin, valuemax:
180 // The minimum and maximum values to use for value -> color
181 // mappings. A value in idata of valuemin or less will have
182 // color 0.0 and a value in idata of valuemax or greater will
183 // have color 1.0. Values between valuemin and valuemax will
184 // map linearly to to the colors between 0.0 and 1.0.
185 // If you do not want to display values outside of the
186 // (valuemin -> valuemax) range, then set zmin = valuemin and
187 // zmax = valuemax.
188 // This allows for multiple plots to use the same color scale
189 // with a consistent value -> color mapping, regardless of the
190 // image content.
191 //
192 //--------------------------------------------------------------------------
193 void
194 c_plimagefr( const PLFLT * const *idata, PLINT nx, PLINT ny,
195  PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
196  PLFLT valuemin, PLFLT valuemax,
197  void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
198  PLPointer pltr_data )
199 {
200  plfimagefr( plf2ops_c(), (PLPointer) idata, nx, ny,
201  xmin, xmax, ymin, ymax, zmin, zmax,
202  valuemin, valuemax, pltr, pltr_data );
203 }
204 
205 void
206 plfimagefr( PLF2OPS idataops, PLPointer idatap, PLINT nx, PLINT ny,
207  PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
208  PLFLT valuemin, PLFLT valuemax,
209  void ( *pltr )( PLFLT, PLFLT, PLFLT *, PLFLT *, PLPointer ),
210  PLPointer pltr_data )
211 {
212  PLINT ix, iy;
213  PLFLT dx, dy;
214  // z holds scaled image pixel values
215  PLFLT *z;
216  // This is used when looping through the image array, checking to
217  // make sure the values are within an acceptable range.
218  PLFLT datum;
219  // Color palette 0 color in use before the plimage* call
220  PLINT init_color;
221  // Color range
222  PLFLT color_min, color_max, color_range;
223 
224  if ( plsc->level < 3 )
225  {
226  plabort( "plimagefr: window must be set up first" );
227  return;
228  }
229 
230  if ( nx <= 0 || ny <= 0 )
231  {
232  plabort( "plimagefr: nx and ny must be positive" );
233  return;
234  }
235 
236  if ( ( z = (PLFLT *) malloc( (size_t) ( ny * nx ) * sizeof ( PLFLT ) ) ) == NULL )
237  {
238  plexit( "plimagefr: Insufficient memory" );
239  }
240 
241  // Save the currently-in-use color.
242  init_color = plsc->icol0;
243 
244  // If no acceptable data range is given, then set the min/max data range
245  // to include all of the given data.
246  if ( zmin == zmax )
247  {
248  // Find the minimum and maximum values in the image
249  idataops->minmax( idatap, nx, ny, &zmin, &zmax );
250  }
251 
252  // Calculate the size of the color range to use
253  color_min = plsc->cmap1_min;
254  color_max = plsc->cmap1_max;
255  color_range = color_max - color_min;
256 
257  // Go through the image values and scale them to fit in
258  // the COLOR_MIN to COLOR_MAX range.
259  // Any values greater than valuemax are set to valuemax,
260  // and values less than valuemin are set to valuemin.
261  // Any values outside of zmin to zmax are flagged so they
262  // are not plotted.
263  for ( ix = 0; ix < nx; ix++ )
264  {
265  for ( iy = 0; iy < ny; iy++ )
266  {
267  if ( valuemin == valuemax )
268  {
269  // If valuemin == valuemax, avoid dividing by zero.
270  z[ix * ny + iy] = ( color_max + color_min ) / 2.0;
271  }
272  else
273  {
274  datum = idataops->get( idatap, ix, iy );
275  if ( isnan( datum ) || datum < zmin || datum > zmax )
276  {
277  // Set to a guaranteed-not-to-plot value
278  z[ix * ny + iy] = COLOR_NO_PLOT;
279  }
280  else
281  {
282  if ( datum < valuemin )
283  {
284  datum = valuemin;
285  }
286  else if ( datum > valuemax )
287  {
288  datum = valuemax;
289  }
290  // Set to a value scaled between color_min and color_max.
291  z[ix * ny + iy] =
292  color_min + ( datum - valuemin + COLOR_MIN ) / ( valuemax - valuemin ) * COLOR_MAX * color_range;
293  }
294  }
295  }
296  }
297 
298  // dx and dy are the plot-coordinates pixel sizes for an untransformed
299  // image
300  dx = ( xmax - xmin ) / (PLFLT) nx;
301  dy = ( ymax - ymin ) / (PLFLT) ny;
302 
303  plP_image( z, nx, ny, xmin, ymin, dx, dy, pltr, pltr_data );
304 
305  plcol0( init_color );
306 
307  free( z );
308 }
309 
310 //--------------------------------------------------------------------------
311 // plimage
312 //
313 // arguments are
314 // idata: array containing image data
315 // nx: dimension of the array in the X axis.
316 // ny: dimension of the array in the Y axis
317 // The array data is indexed like data[ix][iy]
318 //
319 // xmin, xmax, ymin, ymax:
320 // data[0][0] corresponds to (xmin,ymin)
321 // data[nx-1][ny-1] to (xmax,ymax)
322 //
323 // zmin, zmax:
324 // only data within bounds zmin <= data <= zmax will be
325 // plotted. If zmin == zmax, all data will be ploted.
326 //
327 // Dxmin, Dxmax, Dymin, Dymax:
328 // plots only the window of points whose(x,y)'s fall
329 // inside the [Dxmin->Dxmax]X[Dymin->Dymax] window
330 //
331 //--------------------------------------------------------------------------
332 void
333 c_plimage( const PLFLT * const *idata, PLINT nx, PLINT ny,
334  PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
335  PLFLT Dxmin, PLFLT Dxmax, PLFLT Dymin, PLFLT Dymax )
336 {
337  plfimage( plf2ops_c(), (PLPointer) idata, nx, ny,
338  xmin, xmax, ymin, ymax, zmin, zmax,
339  Dxmin, Dxmax, Dymin, Dymax );
340 }
341 
342 void
343 plfimage( PLF2OPS idataops, PLPointer idatap, PLINT nx, PLINT ny,
344  PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax, PLFLT zmin, PLFLT zmax,
345  PLFLT Dxmin, PLFLT Dxmax, PLFLT Dymin, PLFLT Dymax )
346 {
347  PLINT ix, iy, ixx, iyy, xm, ym, nnx, nny;
348  PLFLT data_min, data_max, dx, dy;
349  // z holds the subimage (Dxmin, Dymin) - (Dxmax, Dymax)
350  PLFLT **z;
351  PLF2OPS zops;
352  // Was any space allocated for z?
353  PLBOOL copied;
354  copied = FALSE;
355 
356  if ( nx <= 0 || ny <= 0 )
357  {
358  plabort( "plimage: nx and ny must be positive" );
359  return;
360  }
361 
362  if ( Dxmin < xmin || Dxmax > xmax || Dymin < ymin || Dymax > ymax )
363  {
364  plabort( "plimage: Dxmin or Dxmax or Dymin or Dymax not compatible with xmin or xmax or ymin or ymax." );
365  return;
366  }
367 
368  if ( Dxmax < Dxmin || xmax < xmin || Dymax < Dymin || ymax < ymin )
369  {
370  plabort( "plimage: All (Dxmin < Dxmax) and (Dymin < Dymax) and (xmin < xmax) and (ymin < ymax) must hold." );
371  return;
372  }
373 
374  // Find the minimum and maximum values in the image. Use these values to
375  // for the color scale range.
376  idataops->minmax( idatap, nx, ny, &data_min, &data_max );
377 
378  if ( xmin == Dxmin && xmax == Dxmax && ymin == Dymin && ymax == Dymax )
379  {
380  // If the whole image should be shown, then no copying is needed.
381  z = (PLFLT **) idatap;
382  zops = idataops;
383  nnx = nx;
384  nny = ny;
385  }
386  else
387  {
388  // dx and dy are the plot-coordinates pixel sizes for an untransformed
389  // image
390  dx = ( xmax - xmin ) / (PLFLT) nx;
391  dy = ( ymax - ymin ) / (PLFLT) ny;
392 
393  // Pixel dimensions of the (Dxmin, Dymin) to (Dxmax, Dymax) box
394  nnx = (PLINT) ceil( ( Dxmax - Dxmin ) / dx );
395  nny = (PLINT) ceil( ( Dymax - Dymin ) / dy );
396 
397  // Call plimagefr with the value -> color range mapped to the minimum
398  // Offsets for the idata indices to select
399  // (Dxmin, Dymin) to (Dxmax, Dymax)
400  xm = (PLINT) floor( ( Dxmin - xmin ) / dx );
401  ym = (PLINT) floor( ( Dymin - ymin ) / dy );
402 
403  // Allocate space for the sub-image
404  plAlloc2dGrid( &z, nnx, nny );
405  zops = plf2ops_c();
406 
407  // Go through the image and select the pixels within the given
408  // (Dxmin, Dymin) - (Dxmax, Dymax) window.
409  ixx = -1;
410  for ( ix = xm; ix < xm + nnx; ix++ )
411  {
412  ixx++; iyy = 0;
413  for ( iy = ym; iy < ym + nny; iy++ )
414  {
415  z[ixx][iyy++] = idataops->get( idatap, ix, iy );
416  }
417  }
418 
419  // Set the appropriate values to pass in to plimagefr
420  copied = TRUE;
421  }
422 
423  plfimagefr( zops, (PLPointer) z, nnx, nny, Dxmin, Dxmax, Dymin, Dymax, zmin, zmax,
424  data_min, data_max, NULL, NULL );
425 
426  // Only free the memory if it was allocated by us...
427  if ( copied == TRUE )
428  {
429  plFree2dGrid( z, nnx, nny );
430  }
431 }