PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pbm.c
Go to the documentation of this file.
1 //
2 // $Id: pbm.c 11760 2011-06-01 19:29:11Z airwin $
3 //
4 // PLplot PBM (PPM) device driver.
5 //
6 // Contributed by John C. Atkinson and Zulfi Cumali.
7 // Slightly modified by Geoffrey Furnish.
8 //
9 #include "plDevs.h"
10 
11 #ifdef PLD_pbm
12 
13 #include "plplotP.h"
14 #include "drivers.h"
15 
16 // Device info
17 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_pbm = "pbm:PDB (PPM) Driver:0:pbm:38:pbm\n";
18 
19 
21 
22 void plD_init_pbm( PLStream * );
23 void plD_line_pbm( PLStream *, short, short, short, short );
24 void plD_polyline_pbm( PLStream *, short *, short *, PLINT );
25 void plD_eop_pbm( PLStream * );
26 void plD_bop_pbm( PLStream * );
27 void plD_tidy_pbm( PLStream * );
28 void plD_state_pbm( PLStream *, PLINT );
29 void plD_esc_pbm( PLStream *, PLINT, void * );
30 
31 #undef PIXELS_X
32 #undef PIXELS_Y
33 #define PIXELS_X 640
34 #define PIXELS_Y 480
35 
36 static char *cmap;
37 
38 #undef MAX
39 #undef ABS
40 #define MAX( a, b ) ( ( a > b ) ? a : b )
41 #define ABS( a ) ( ( a < 0 ) ? -a : a )
42 
43 #define MAX_INTENSITY 255
44 
46 {
47 #ifndef ENABLE_DYNDRIVERS
48  pdt->pl_MenuStr = "PDB (PPM) Driver";
49  pdt->pl_DevName = "pbm";
50 #endif
52  pdt->pl_seq = 38;
53  pdt->pl_init = (plD_init_fp) plD_init_pbm;
54  pdt->pl_line = (plD_line_fp) plD_line_pbm;
55  pdt->pl_polyline = (plD_polyline_fp) plD_polyline_pbm;
56  pdt->pl_eop = (plD_eop_fp) plD_eop_pbm;
57  pdt->pl_bop = (plD_bop_fp) plD_bop_pbm;
58  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_pbm;
59  pdt->pl_state = (plD_state_fp) plD_state_pbm;
60  pdt->pl_esc = (plD_esc_fp) plD_esc_pbm;
61 }
62 
63 //--------------------------------------------------------------------------
64 // plD_init_pbm()
65 //
66 // Initialize device (terminal).
67 //--------------------------------------------------------------------------
68 
69 void
70 plD_init_pbm( PLStream *pls )
71 {
72 #if 1
73 
74 // Initialize family file info
75 
76  plFamInit( pls );
77 
78  plP_setpxl( (PLFLT) 5.905, (PLFLT) 5.905 );
79 
80 #endif
81 
82  pls->color = 1; // Is a color device
83  pls->dev_fill0 = 0; // Handle solid fills
84  pls->dev_fill1 = 0; // Use PLplot core fallback for pattern fills
85  pls->nopause = 1; // Don't pause between frames
86 
87 // Prompt for a file name if not already set
88 
89  plOpenFile( pls );
90  pls->pdfs = pdf_finit( pls->OutFile );
91 
92 // Allocate and initialize device-specific data
93 
94  pls->dev = NULL;
95 
96 // Set up device parameters
97 
98  if ( pls->xlength <= 0 || pls->ylength <= 0 )
99  {
100  plspage( 0., 0., PIXELS_X, PIXELS_Y, 0, 0 );
101  }
102 
103  plP_setphy( 0, pls->xlength, 0, pls->ylength );
104 }
105 
106 #if 0
107 void
108 plD_line_pbm( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
109 {
110  int steps, i, dx, dy;
111  double x_off, y_off, dx_step, dy_step;
112 
113 // This algoritm is by Steven Harrington
114 // From "Computer Graphics: A Proogramming Approach
115 
116  dx = x2a - x1a;
117  dy = y2a - y1a;
118  steps = MAX( ABS( dx ), ABS( dy ) ) + 1;
119  steps *= 2;
120  dx_step = dx / steps;
121  dy_step = dy / steps;
122  x_off = x1a + 0.5;
123  y_off = y1a + 0.5;
124 
125  for ( i = 0; i < steps; i++ )
126  {
127  cmap[(int) y_off][(int) x_off][0] = pls->curcolor.r;
128  cmap[(int) y_off][(int) x_off][1] = pls->curcolor.g;
129  cmap[(int) y_off][(int) x_off][2] = pls->curcolor.b;
130  x_off += dx_step;
131  y_off += dy_step;
132  }
133 
134  cmap[(int) y_off][(int) x_off][0] = pls->curcolor.r;
135  cmap[(int) y_off][(int) x_off][1] = pls->curcolor.g;
136  cmap[(int) y_off][(int) x_off][2] = pls->curcolor.b;
137 
138  return;
139 }
140 #endif
141 
142 #define sign( a ) ( ( a < 0 ) ? -1 : ( ( a == 0 ) ? 0 : 1 ) )
143 
144 #if 0
145 #define plot( x, y, c ) { cmap[y - 1][x - 1][0] = ( c )->curcolor.r; \
146  cmap[y - 1][x - 1][1] = ( c )->curcolor.g; \
147  cmap[y - 1][x - 1][2] = ( c )->curcolor.b; }
148 
149 // Bresnham's algorithm for line plotting on a scan lines
150 
151 void
152 plD_line_pbm( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
153 {
154  int e, x, y, dx, dy, s1, s2, temp, change, i;
155 
156  x = x1a;
157  y = y1a;
158 
159  dx = ABS( x2a - x1a );
160  dy = ABS( y2a - y1a );
161  s1 = sign( x2a - x1a );
162  s2 = sign( y2a - y1a );
163 
164  if ( dy > dx )
165  {
166  temp = dx;
167  dx = dy;
168  dy = temp;
169  change = 1;
170  }
171  else
172  {
173  change = 0;
174  }
175  e = 2 * dy - dx;
176 
177  for ( i = 1; i < dx; i++ )
178  {
179  plot( x, y, pls );
180  while ( e >= 0 )
181  {
182  if ( change == 1 )
183  x += s1;
184  else
185  y += s2;
186  e = e - 2 * dx;
187  }
188  if ( change == 1 )
189  y += s2;
190  else
191  x += s1;
192  e = e + 2 * dy;
193  }
194 }
195 #else
196 #define plot( x, y, c ) { int i = 3 * ( ( y ) * ( c )->xlength + ( x ) ); \
197  cmap[i + 0] = ( c )->curcolor.r; \
198  cmap[i + 1] = ( c )->curcolor.g; \
199  cmap[i + 2] = ( c )->curcolor.b; }
200 
201 // Modified version of the ljii routine (see ljii.c)
202 void
203 plD_line_pbm( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
204 {
205  int i;
206  int x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
207  PLINT x1b, y1b, x2b, y2b;
208  PLFLT length, fx, fy, dx, dy;
209 
210 // Take mirror image, since PCL expects (0,0) to be at top left
211 
212  y1 = pls->ylength - ( y1 - 0 );
213  y2 = pls->ylength - ( y2 - 0 );
214 
215  x1b = x1, x2b = x2, y1b = y1, y2b = y2;
216  length = (PLFLT) sqrt( (double)
217  ( ( x2b - x1b ) * ( x2b - x1b ) + ( y2b - y1b ) * ( y2b - y1b ) ) );
218 
219  if ( length == 0. )
220  length = 1.;
221  dx = ( x2 - x1 ) / length;
222  dy = ( y2 - y1 ) / length;
223 
224  fx = x1;
225  fy = y1;
226  plot( (PLINT) x1, (PLINT) y1, pls );
227  plot( (PLINT) x2, (PLINT) y2, pls );
228 
229  for ( i = 1; i <= (int) length; i++ )
230  {
231  fx += dx; fy += dy;
232  plot( (PLINT) fx, (PLINT) fy, pls );
233  }
234 }
235 #endif
236 
237 void
238 plD_polyline_pbm( PLStream *pls, short *xa, short *ya, PLINT npts )
239 {
240  int i;
241  for ( i = 0; i < npts - 1; i++ )
242  plD_line_pbm( pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
243 }
244 
245 void
246 plD_eop_pbm( PLStream *pls )
247 {
248  FILE *fp = pls->OutFile;
249  size_t im_size, nwrite;
250 
251  if ( fp != NULL )
252  {
253  fprintf( fp, "%s\n", "P6" );
254  fprintf( fp, "%d %d\n", pls->xlength, pls->ylength );
255  fprintf( fp, "%d\n", MAX_INTENSITY );
256  //
257  // {
258  // int i, j, k;
259  // for (i=0; i<PIXELS_Y; i++)
260  // for (j=0; j<PIXELS_X; j++)
261  // for (k=0; k<3; k++)
262  // fprintf(fp, "%c", cmap[i][j][k]);
263  // }
264  //
265  im_size = pls->xlength * pls->ylength * 3;
266  nwrite = fwrite( cmap, 1, im_size, fp );
267  if ( nwrite != im_size )
268  plabort( "pbm driver: Error writing pbm file" );
269 
270  plCloseFile( pls );
271  }
272  free( cmap );
273  cmap = 0;
274 }
275 
276 void
277 plD_bop_pbm( PLStream *pls )
278 {
279  int i, j, k;
280  cmap = (char *) malloc( pls->xlength * pls->ylength * 3 );
281  for ( i = 0; i < pls->ylength; i++ )
282  for ( j = 0; j < pls->xlength; j++ )
283  {
284  k = ( i * pls->xlength + j ) * 3;
285  cmap[k + 0] = pls->cmap0[0].r;
286  cmap[k + 1] = pls->cmap0[0].g;
287  cmap[k + 2] = pls->cmap0[0].b;
288  }
289 }
290 
291 void
292 plD_tidy_pbm( PLStream *pls )
293 {
294 // Nothing to do here
295 }
296 
297 void
298 plD_state_pbm( PLStream *pls, PLINT op )
299 {
300 // Nothing to do here
301 }
302 
303 void
304 plD_esc_pbm( PLStream *pls, PLINT op, void *ptr )
305 {
306 // Nothing to do here
307 }
308 
309 #else
310 int
312 {
313  return 0;
314 }
315 
316 #endif // PLD_pbm
317 
318