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