xref: /petsc/src/sys/classes/draw/impls/image/drawimage.c (revision db2b9530cea7203cdddcdfcaf19eada576ef3459)
1 #include <../src/sys/classes/draw/impls/image/drawimage.h>   /*I  "petscdraw.h" I*/
2 #include <petsc/private/drawimpl.h>                          /*I  "petscdraw.h" I*/
3 
4 #if defined(PETSC_USE_DEBUG)
5 #define PetscDrawValidColor(color) PetscCheck((color)>=0&&(color)<256,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Color value %" PetscInt_FMT " out of range [0..255]",(PetscInt)(color))
6 #else
7 #define PetscDrawValidColor(color) do {} while (0)
8 #endif
9 
10 #define XTRANS(draw,img,x)  ((int)(((img)->w-1)*((draw)->port_xl + ((((x) - (draw)->coor_xl)*((draw)->port_xr - (draw)->port_xl))/((draw)->coor_xr - (draw)->coor_xl)))))
11 #define YTRANS(draw,img,y)  (((img)->h-1) - (int)(((img)->h-1)*((draw)->port_yl + ((((y) - (draw)->coor_yl)*((draw)->port_yr - (draw)->port_yl))/((draw)->coor_yr - (draw)->coor_yl)))))
12 
13 #define ITRANS(draw,img,i)  ((draw)->coor_xl + (((PetscReal)(i))*((draw)->coor_xr - (draw)->coor_xl)/((img)->w-1) - (draw)->port_xl)/((draw)->port_xr - (draw)->port_xl))
14 #define JTRANS(draw,img,j)  ((draw)->coor_yl + (((PetscReal)(j))/((img)->h-1) + (draw)->port_yl - 1)*((draw)->coor_yr - (draw)->coor_yl)/((draw)->port_yl - (draw)->port_yr))
15 
16 static PetscErrorCode PetscDrawSetViewport_Image(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr)
17 {
18   PetscImage img = (PetscImage)draw->data;
19   PetscFunctionBegin;
20   {
21     int xmax = img->w - 1,   ymax = img->h - 1;
22     int xa = (int)(xl*xmax), ya = ymax - (int)(yr*ymax);
23     int xb = (int)(xr*xmax), yb = ymax - (int)(yl*ymax);
24     PetscImageSetClip(img,xa,ya,xb+1-xa,yb+1-ya);
25   }
26   PetscFunctionReturn(0);
27 }
28 
29 /*
30 static PetscErrorCode PetscDrawSetCoordinates_Image(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr)
31 {
32   PetscFunctionBegin;
33   PetscFunctionReturn(0);
34 }*/
35 #define PetscDrawSetCoordinates_Image NULL
36 
37 static PetscErrorCode PetscDrawCoordinateToPixel_Image(PetscDraw draw,PetscReal x,PetscReal y,int *i,int *j)
38 {
39   PetscImage img = (PetscImage)draw->data;
40   PetscFunctionBegin;
41   if (i) *i = XTRANS(draw,img,x);
42   if (j) *j = YTRANS(draw,img,y);
43   PetscFunctionReturn(0);
44 }
45 
46 static PetscErrorCode PetscDrawPixelToCoordinate_Image(PetscDraw draw,int i,int j,PetscReal *x,PetscReal *y)
47 {
48   PetscImage img = (PetscImage)draw->data;
49   PetscFunctionBegin;
50   if (x) *x = ITRANS(draw,img,i);
51   if (y) *y = JTRANS(draw,img,j);
52   PetscFunctionReturn(0);
53 }
54 
55 /*
56 static PetscErrorCode PetscDrawPointSetSize_Image(PetscDraw draw,PetscReal width)
57 {
58   PetscFunctionBegin;
59   PetscFunctionReturn(0);
60 }*/
61 #define PetscDrawPointSetSize_Image NULL
62 
63 static PetscErrorCode PetscDrawPoint_Image(PetscDraw draw,PetscReal x,PetscReal y,int c)
64 {
65   PetscImage img = (PetscImage)draw->data;
66   PetscFunctionBegin;
67   PetscDrawValidColor(c);
68   {
69     int j, xx = XTRANS(draw,img,x);
70     int i, yy = YTRANS(draw,img,y);
71     for (i=-1; i<=1; i++)
72       for (j=-1; j<=1; j++)
73         PetscImageDrawPixel(img,xx+j,yy+i,c);
74   }
75   PetscFunctionReturn(0);
76 }
77 
78 static PetscErrorCode PetscDrawPointPixel_Image(PetscDraw draw,int x,int y,int c)
79 {
80   PetscImage img = (PetscImage)draw->data;
81   PetscFunctionBegin;
82   PetscDrawValidColor(c);
83   {
84     PetscImageDrawPixel(img,x,y,c);
85   }
86   PetscFunctionReturn(0);
87 }
88 
89 /*
90 static PetscErrorCode PetscDrawLineSetWidth_Image(PetscDraw draw,PetscReal width)
91 {
92   PetscFunctionBegin;
93   PetscFunctionReturn(0);
94 }*/
95 #define PetscDrawLineSetWidth_Image NULL
96 
97 static PetscErrorCode PetscDrawLineGetWidth_Image(PetscDraw draw,PetscReal *width)
98 {
99   PetscImage img = (PetscImage)draw->data;
100   PetscFunctionBegin;
101   {
102     int lw = 1;
103     *width = lw*(draw->coor_xr - draw->coor_xl)/(img->w*(draw->port_xr - draw->port_xl));
104   }
105   PetscFunctionReturn(0);
106 }
107 
108 static PetscErrorCode PetscDrawLine_Image(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c)
109 {
110   PetscImage img = (PetscImage)draw->data;
111   PetscFunctionBegin;
112   {
113     int x_1 = XTRANS(draw,img,xl), x_2 = XTRANS(draw,img,xr);
114     int y_1 = YTRANS(draw,img,yl), y_2 = YTRANS(draw,img,yr);
115     PetscImageDrawLine(img,x_1,y_1,x_2,y_2,c);
116   }
117   PetscFunctionReturn(0);
118 }
119 
120 static PetscErrorCode PetscDrawArrow_Image(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c)
121 {
122   PetscImage img = (PetscImage)draw->data;
123   PetscFunctionBegin;
124   PetscDrawValidColor(c);
125   {
126     int x_1 = XTRANS(draw,img,xl), x_2 = XTRANS(draw,img,xr);
127     int y_1 = YTRANS(draw,img,yl), y_2 = YTRANS(draw,img,yr);
128     if (x_1 == x_2 && y_1 == y_2) PetscFunctionReturn(0);
129     PetscImageDrawLine(img,x_1,y_1,x_2,y_2,c);
130     if (x_1 == x_2 && PetscAbs(y_1 - y_2) > 7) {
131       if (y_2 > y_1) {
132         PetscImageDrawLine(img,x_2,y_2,x_2-3,y_2-3,c);
133         PetscImageDrawLine(img,x_2,y_2,x_2+3,y_2-3,c);
134       } else {
135         PetscImageDrawLine(img,x_2,y_2,x_2-3,y_2+3,c);
136         PetscImageDrawLine(img,x_2,y_2,x_2+3,y_2+3,c);
137       }
138     }
139     if (y_1 == y_2 && PetscAbs(x_1 - x_2) > 7) {
140       if (x_2 > x_1) {
141         PetscImageDrawLine(img,x_2-3,y_2-3,x_2,y_2,c);
142         PetscImageDrawLine(img,x_2-3,y_2+3,x_2,y_2,c);
143       } else {
144         PetscImageDrawLine(img,x_2,y_2,x_2+3,y_2-3,c);
145         PetscImageDrawLine(img,x_2,y_2,x_2+3,y_2+3,c);
146       }
147     }
148    }
149   PetscFunctionReturn(0);
150 }
151 
152 static PetscErrorCode PetscDrawRectangle_Image(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
153 {
154   PetscImage img = (PetscImage)draw->data;
155   PetscFunctionBegin;
156   PetscDrawValidColor(c1);
157   PetscDrawValidColor(c2);
158   PetscDrawValidColor(c3);
159   PetscDrawValidColor(c4);
160   {
161     int x = XTRANS(draw,img,xl), w = XTRANS(draw,img,xr) + 1 - x;
162     int y = YTRANS(draw,img,yr), h = YTRANS(draw,img,yl) + 1 - y;
163     int c  = (c1 + c2 + c3 + c4)/4;
164     PetscImageDrawRectangle(img,x,y,w,h,c);
165   }
166   PetscFunctionReturn(0);
167 }
168 
169 static PetscErrorCode PetscDrawEllipse_Image(PetscDraw draw,PetscReal x,PetscReal y,PetscReal a,PetscReal b,int c)
170 {
171   PetscImage img = (PetscImage)draw->data;
172   PetscFunctionBegin;
173   PetscDrawValidColor(c);
174   a = PetscAbsReal(a);
175   b = PetscAbsReal(b);
176   {
177     int xc = XTRANS(draw,img,x), w = XTRANS(draw,img,x + a/2) + 0 - xc;
178     int yc = YTRANS(draw,img,y), h = YTRANS(draw,img,y - b/2) + 0 - yc;
179     if (PetscAbsReal(a-b) <= 0)  w = h = PetscMin(w,h); /* workaround truncation errors */
180     PetscImageDrawEllipse(img,xc,yc,w,h,c);
181   }
182   PetscFunctionReturn(0);
183 }
184 
185 static PetscErrorCode PetscDrawTriangle_Image(PetscDraw draw,PetscReal X_1,PetscReal Y_1,PetscReal X_2,PetscReal Y_2,PetscReal X_3,PetscReal Y_3,int c1,int c2,int c3)
186 {
187   PetscImage img = (PetscImage)draw->data;
188   PetscFunctionBegin;
189   PetscDrawValidColor(c1);
190   PetscDrawValidColor(c2);
191   PetscDrawValidColor(c3);
192   {
193     int x_1 = XTRANS(draw,img,X_1), x_2 = XTRANS(draw,img,X_2), x_3 = XTRANS(draw,img,X_3);
194     int y_1 = YTRANS(draw,img,Y_1), y_2 = YTRANS(draw,img,Y_2), y_3 = YTRANS(draw,img,Y_3);
195     PetscImageDrawTriangle(img,x_1,y_1,c1,x_2,y_2,c2,x_3,y_3,c3);
196   }
197   PetscFunctionReturn(0);
198 }
199 
200 /*
201 static PetscErrorCode PetscDrawStringSetSize_Image(PetscDraw draw,PetscReal w,PetscReal h)
202 {
203   PetscFunctionBegin;
204   PetscFunctionReturn(0);
205 }*/
206 #define PetscDrawStringSetSize_Image NULL
207 
208 static PetscErrorCode PetscDrawStringGetSize_Image(PetscDraw draw,PetscReal *w,PetscReal  *h)
209 {
210   PetscImage img = (PetscImage)draw->data;
211   PetscFunctionBegin;
212   {
213     int tw = PetscImageFontWidth;
214     int th = PetscImageFontHeight;
215     if (w) *w = tw*(draw->coor_xr - draw->coor_xl)/(img->w*(draw->port_xr - draw->port_xl));
216     if (h) *h = th*(draw->coor_yr - draw->coor_yl)/(img->h*(draw->port_yr - draw->port_yl));
217   }
218   PetscFunctionReturn(0);
219 }
220 
221 static PetscErrorCode PetscDrawString_Image(PetscDraw draw,PetscReal x,PetscReal y,int c,const char text[])
222 {
223   PetscImage     img = (PetscImage)draw->data;
224   PetscToken     token;
225   char           *subtext;
226   PetscErrorCode ierr;
227   PetscFunctionBegin;
228   PetscDrawValidColor(c);
229   {
230     int xx = XTRANS(draw,img,x);
231     int yy = YTRANS(draw,img,y);
232     ierr = PetscTokenCreate(text,'\n',&token);CHKERRQ(ierr);
233     ierr = PetscTokenFind(token,&subtext);CHKERRQ(ierr);
234     while (subtext) {
235       PetscImageDrawText(img,xx,yy,c,subtext);
236       yy += PetscImageFontHeight;
237       ierr = PetscTokenFind(token,&subtext);CHKERRQ(ierr);
238     }
239     ierr = PetscTokenDestroy(&token);CHKERRQ(ierr);
240   }
241   PetscFunctionReturn(0);
242 }
243 
244 static PetscErrorCode PetscDrawStringVertical_Image(PetscDraw draw,PetscReal x,PetscReal y,int c,const char text[])
245 {
246   PetscImage img = (PetscImage)draw->data;
247   PetscFunctionBegin;
248   PetscDrawValidColor(c);
249   {
250     char chr[2] = {0, 0};
251     int  xx = XTRANS(draw,img,x);
252     int  yy = YTRANS(draw,img,y);
253     int  offset = PetscImageFontHeight;
254     while ((chr[0] = *text++)) {
255       PetscImageDrawText(img,xx,yy+offset,c,chr);
256       yy += PetscImageFontHeight;
257     }
258   }
259   PetscFunctionReturn(0);
260 }
261 
262 /*
263 static PetscErrorCode PetscDrawStringBoxed_Image(PetscDraw draw,PetscReal sxl,PetscReal syl,int sc,int bc,const char text[],PetscReal *w,PetscReal *h)
264 {
265   PetscFunctionBegin;
266   if (w) *w = 0;
267   if (h) *h = 0;
268   PetscFunctionReturn(0);
269 */
270 #define PetscDrawStringBoxed_Image NULL
271 
272 /*
273 static PetscErrorCode PetscDrawFlush_Image(PetscDraw draw)
274 {
275   PetscFunctionBegin;
276   PetscFunctionReturn(0);
277 }*/
278 #define PetscDrawFlush_Image NULL
279 
280 static PetscErrorCode PetscDrawClear_Image(PetscDraw draw)
281 {
282   PetscImage     img = (PetscImage)draw->data;
283   PetscFunctionBegin;
284   {
285     PetscImageClear(img);
286   }
287   PetscFunctionReturn(0);
288 }
289 
290 /*
291 static PetscErrorCode PetscDrawSetDoubleBuffer_Image(PetscDraw draw)
292 {
293   PetscFunctionBegin;
294   PetscFunctionReturn(0);
295 }*/
296 #define PetscDrawSetDoubleBuffer_Image NULL
297 
298 static PetscErrorCode PetscDrawGetPopup_Image(PetscDraw draw,PetscDraw *popup)
299 {
300   PetscBool      flg = PETSC_FALSE;
301   PetscErrorCode ierr;
302 
303   PetscFunctionBegin;
304   ierr = PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_popup",&flg,NULL);CHKERRQ(ierr);
305   if (!flg) {*popup = NULL; PetscFunctionReturn(0);}
306   ierr = PetscDrawCreate(PetscObjectComm((PetscObject)draw),NULL,NULL,0,0,220,220,popup);CHKERRQ(ierr);
307   ierr = PetscDrawSetType(*popup,PETSC_DRAW_IMAGE);CHKERRQ(ierr);
308   ierr = PetscObjectSetOptionsPrefix((PetscObject)*popup,"popup_");CHKERRQ(ierr);
309   ierr = PetscObjectAppendOptionsPrefix((PetscObject)*popup,((PetscObject)draw)->prefix);CHKERRQ(ierr);
310   draw->popup = *popup;
311   PetscFunctionReturn(0);
312 }
313 
314 /*
315 static PetscErrorCode PetscDrawSetTitle_Image(PetscDraw draw,const char title[])
316 {
317   PetscFunctionBegin;
318   PetscFunctionReturn(0);
319 }*/
320 #define PetscDrawSetTitle_Image NULL
321 
322 /*
323 static PetscErrorCode PetscDrawCheckResizedWindow_Image(PetscDraw draw)
324 {
325   PetscFunctionBegin;
326   PetscFunctionReturn(0);
327 }*/
328 #define PetscDrawCheckResizedWindow_Image NULL
329 
330 static PetscErrorCode PetscDrawResizeWindow_Image(PetscDraw draw,int w,int h)
331 {
332   PetscImage     img = (PetscImage)draw->data;
333   PetscErrorCode ierr;
334 
335   PetscFunctionBegin;
336   if (w == img->w && h == img->h) PetscFunctionReturn(0);
337   ierr = PetscFree(img->buffer);CHKERRQ(ierr);
338 
339   img->w = w; img->h = h;
340   ierr = PetscCalloc1((size_t)(img->w*img->h),&img->buffer);CHKERRQ(ierr);
341   ierr = PetscDrawSetViewport_Image(draw,draw->port_xl,draw->port_yl,draw->port_xr,draw->port_yr);CHKERRQ(ierr);
342   PetscFunctionReturn(0);
343 }
344 
345 static PetscErrorCode PetscDrawDestroy_Image(PetscDraw draw)
346 {
347   PetscImage     img = (PetscImage)draw->data;
348   PetscErrorCode ierr;
349 
350   PetscFunctionBegin;
351   ierr = PetscDrawDestroy(&draw->popup);CHKERRQ(ierr);
352   ierr = PetscFree(img->buffer);CHKERRQ(ierr);
353   ierr = PetscFree(draw->data);CHKERRQ(ierr);
354   PetscFunctionReturn(0);
355 }
356 
357 /*
358 static PetscErrorCode PetscDrawView_Image(PetscDraw draw,PetscViewer viewer)
359 {
360   PetscFunctionBegin;
361   PetscFunctionReturn(0);
362 }*/
363 #define PetscDrawView_Image NULL
364 
365 /*
366 static PetscErrorCode PetscDrawGetMouseButton_Image(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
367 {
368   PetscFunctionBegin;
369   *button = PETSC_BUTTON_NONE;
370   if (x_user) *x_user = 0;
371   if (y_user) *y_user = 0;
372   if (x_phys) *x_phys = 0;
373   if (y_phys) *y_phys = 0;
374   PetscFunctionReturn(0);
375 }*/
376 #define PetscDrawGetMouseButton_Image NULL
377 
378 /*
379 static PetscErrorCode PetscDrawPause_Image(PetscDraw draw)
380 {
381   PetscFunctionBegin;
382   PetscFunctionReturn(0);
383 }*/
384 #define PetscDrawPause_Image NULL
385 
386 /*
387 static PetscErrorCode PetscDrawBeginPage_Image(PetscDraw draw)
388 {
389   PetscFunctionBegin;
390   PetscFunctionReturn(0);
391 }*/
392 #define PetscDrawBeginPage_Image NULL
393 
394 /*
395 static PetscErrorCode PetscDrawEndPage_Image(PetscDraw draw)
396 {
397   PetscFunctionBegin;
398   PetscFunctionReturn(0);
399 }*/
400 #define PetscDrawEndPage_Image NULL
401 
402 static PetscErrorCode PetscDrawGetSingleton_Image(PetscDraw draw,PetscDraw *sdraw)
403 {
404   PetscImage     pimg = (PetscImage)draw->data;
405   PetscImage     simg;
406   PetscErrorCode ierr;
407 
408   PetscFunctionBegin;
409   ierr = PetscDrawCreate(PETSC_COMM_SELF,NULL,NULL,0,0,draw->w,draw->h,sdraw);CHKERRQ(ierr);
410   ierr = PetscDrawSetType(*sdraw,PETSC_DRAW_IMAGE);CHKERRQ(ierr);
411   (*sdraw)->ops->resizewindow = NULL;
412   simg = (PetscImage)(*sdraw)->data;
413   ierr = PetscArraycpy(simg->buffer,pimg->buffer,pimg->w*pimg->h);CHKERRQ(ierr);
414   PetscFunctionReturn(0);
415 }
416 
417 static PetscErrorCode PetscDrawRestoreSingleton_Image(PetscDraw draw,PetscDraw *sdraw)
418 {
419   PetscImage     pimg = (PetscImage)draw->data;
420   PetscImage     simg = (PetscImage)(*sdraw)->data;
421   PetscErrorCode ierr;
422 
423   PetscFunctionBegin;
424   ierr = PetscArraycpy(pimg->buffer,simg->buffer,pimg->w*pimg->h);CHKERRQ(ierr);
425   ierr = PetscDrawDestroy(sdraw);CHKERRQ(ierr);
426   PetscFunctionReturn(0);
427 }
428 
429 /*
430 static PetscErrorCode PetscDrawSave_Image(PetscDraw draw)
431 {
432   PetscFunctionBegin;
433   PetscFunctionReturn(0);
434 }*/
435 #define PetscDrawSave_Image NULL
436 
437 static PetscErrorCode PetscDrawGetImage_Image(PetscDraw draw,unsigned char palette[256][3],unsigned int *w,unsigned int *h,unsigned char *pixels[])
438 {
439   PetscImage     img = (PetscImage)draw->data;
440   unsigned char  *buffer = NULL;
441   PetscMPIInt    rank,size;
442   PetscErrorCode ierr;
443 
444   PetscFunctionBegin;
445   if (w) *w = (unsigned int)img->w;
446   if (h) *h = (unsigned int)img->h;
447   if (pixels) *pixels = NULL;
448   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRMPI(ierr);
449   if (rank == 0) {
450     ierr = PetscMemcpy(palette,img->palette,sizeof(img->palette));CHKERRQ(ierr);
451     ierr = PetscMalloc1((size_t)(img->w*img->h),&buffer);CHKERRQ(ierr);
452     if (pixels) *pixels = buffer;
453   }
454   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)draw),&size);CHKERRMPI(ierr);
455   if (size == 1) {
456     ierr = PetscArraycpy(buffer,img->buffer,img->w*img->h);CHKERRQ(ierr);
457   } else {
458     ierr = MPI_Reduce(img->buffer,buffer,img->w*img->h,MPI_UNSIGNED_CHAR,MPI_MAX,0,PetscObjectComm((PetscObject)draw));CHKERRMPI(ierr);
459   }
460   PetscFunctionReturn(0);
461 }
462 
463 static struct _PetscDrawOps DvOps = {
464   PetscDrawSetDoubleBuffer_Image,
465   PetscDrawFlush_Image,
466   PetscDrawLine_Image,
467   PetscDrawLineSetWidth_Image,
468   PetscDrawLineGetWidth_Image,
469   PetscDrawPoint_Image,
470   PetscDrawPointSetSize_Image,
471   PetscDrawString_Image,
472   PetscDrawStringVertical_Image,
473   PetscDrawStringSetSize_Image,
474   PetscDrawStringGetSize_Image,
475   PetscDrawSetViewport_Image,
476   PetscDrawClear_Image,
477   PetscDrawRectangle_Image,
478   PetscDrawTriangle_Image,
479   PetscDrawEllipse_Image,
480   PetscDrawGetMouseButton_Image,
481   PetscDrawPause_Image,
482   PetscDrawBeginPage_Image,
483   PetscDrawEndPage_Image,
484   PetscDrawGetPopup_Image,
485   PetscDrawSetTitle_Image,
486   PetscDrawCheckResizedWindow_Image,
487   PetscDrawResizeWindow_Image,
488   PetscDrawDestroy_Image,
489   PetscDrawView_Image,
490   PetscDrawGetSingleton_Image,
491   PetscDrawRestoreSingleton_Image,
492   PetscDrawSave_Image,
493   PetscDrawGetImage_Image,
494   PetscDrawSetCoordinates_Image,
495   PetscDrawArrow_Image,
496   PetscDrawCoordinateToPixel_Image,
497   PetscDrawPixelToCoordinate_Image,
498   PetscDrawPointPixel_Image,
499   PetscDrawStringBoxed_Image
500 };
501 
502 static const unsigned char BasicColors[PETSC_DRAW_BASIC_COLORS][3] = {
503   { 255, 255, 255 }, /* white */
504   {   0,   0,   0 }, /* black */
505   { 255,   0,   0 }, /* red */
506   {   0, 255,   0 }, /* green */
507   {   0, 255, 255 }, /* cyan */
508   {   0,   0, 255 }, /* blue */
509   { 255,   0, 255 }, /* magenta */
510   { 127, 255, 212 }, /* aquamarine */
511   {  34, 139,  34 }, /* forestgreen */
512   { 255, 165,   0 }, /* orange */
513   { 238, 130, 238 }, /* violet */
514   { 165,  42,  42 }, /* brown */
515   { 255, 192, 203 }, /* pink */
516   { 255, 127,  80 }, /* coral */
517   { 190, 190, 190 }, /* gray */
518   { 255, 255,   0 }, /* yellow */
519   { 255, 215,   0 }, /* gold */
520   { 255, 182, 193 }, /* lightpink */
521   {  72, 209, 204 }, /* mediumturquoise */
522   { 240, 230, 140 }, /* khaki */
523   { 105, 105, 105 }, /* dimgray */
524   {  54, 205,  50 }, /* yellowgreen */
525   { 135, 206, 235 }, /* skyblue */
526   {   0, 100,   0 }, /* darkgreen */
527   {   0,   0, 128 }, /* navyblue */
528   { 244, 164,  96 }, /* sandybrown */
529   {  95, 158, 160 }, /* cadetblue */
530   { 176, 224, 230 }, /* powderblue */
531   { 255,  20, 147 }, /* deeppink */
532   { 216, 191, 216 }, /* thistle */
533   {  50, 205,  50 }, /* limegreen */
534   { 255, 240, 245 }, /* lavenderblush */
535   { 221, 160, 221 }, /* plum */
536 };
537 
538 /*MC
539    PETSC_DRAW_IMAGE - PETSc graphics device that uses a raster buffer
540 
541    Options Database Keys:
542 .  -draw_size w,h - size of image in pixels
543 
544    Level: beginner
545 
546 .seealso:  PetscDrawOpenImage(), PetscDrawSetFromOptions()
547 M*/
548 PETSC_EXTERN PetscErrorCode PetscDrawCreate_Image(PetscDraw);
549 
550 PETSC_EXTERN PetscErrorCode PetscDrawCreate_Image(PetscDraw draw)
551 {
552   PetscImage     img;
553   int            w = draw->w, h = draw->h;
554   PetscInt       size[2], nsize = 2;
555   PetscBool      set;
556   PetscErrorCode ierr;
557 
558   PetscFunctionBegin;
559   draw->pause   = 0;
560   draw->coor_xl = 0; draw->coor_xr = 1;
561   draw->coor_yl = 0; draw->coor_yr = 1;
562   draw->port_xl = 0; draw->port_xr = 1;
563   draw->port_yl = 0; draw->port_yr = 1;
564 
565   size[0] = w; if (size[0] < 1) size[0] = 300;
566   size[1] = h; if (size[1] < 1) size[1] = size[0];
567   ierr = PetscOptionsGetIntArray(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_size",size,&nsize,&set);CHKERRQ(ierr);
568   if (set && nsize == 1) size[1] = size[0];
569   if (size[0] < 1) size[0] = 300;
570   if (size[1] < 1) size[1] = size[0];
571   draw->w = w = size[0]; draw->x = 0;
572   draw->h = h = size[1]; draw->x = 0;
573 
574   ierr = PetscNewLog(draw,&img);CHKERRQ(ierr);
575   ierr = PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr);
576   draw->data = (void*)img;
577 
578   img->w = w; img->h = h;
579   ierr = PetscCalloc1((size_t)(img->w*img->h),&img->buffer);CHKERRQ(ierr);
580   PetscImageSetClip(img,0,0,img->w,img->h);
581   {
582     int i,k,ncolors = 256-PETSC_DRAW_BASIC_COLORS;
583     unsigned char R[256-PETSC_DRAW_BASIC_COLORS];
584     unsigned char G[256-PETSC_DRAW_BASIC_COLORS];
585     unsigned char B[256-PETSC_DRAW_BASIC_COLORS];
586     ierr = PetscDrawUtilitySetCmap(NULL,ncolors,R,G,B);CHKERRQ(ierr);
587     for (k=0; k<PETSC_DRAW_BASIC_COLORS; k++) {
588       img->palette[k][0] = BasicColors[k][0];
589       img->palette[k][1] = BasicColors[k][1];
590       img->palette[k][2] = BasicColors[k][2];
591     }
592     for (i=0; i<ncolors; i++, k++) {
593       img->palette[k][0] = R[i];
594       img->palette[k][1] = G[i];
595       img->palette[k][2] = B[i];
596     }
597   }
598 
599   if (!draw->savefilename) {ierr = PetscDrawSetSave(draw,draw->title);CHKERRQ(ierr);}
600   PetscFunctionReturn(0);
601 }
602 
603 /*@C
604    PetscDrawOpenImage - Opens an image for use with the PetscDraw routines.
605 
606    Collective
607 
608    Input Parameters:
609 +  comm - the communicator that will share image
610 -  filename - optional name of the file
611 -  w, h - the image width and height in pixels
612 
613    Output Parameters:
614 .  draw - the drawing context.
615 
616    Level: beginner
617 
618 .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
619 @*/
620 PetscErrorCode PetscDrawOpenImage(MPI_Comm comm,const char filename[],int w,int h,PetscDraw *draw)
621 {
622   PetscErrorCode ierr;
623 
624   PetscFunctionBegin;
625   ierr = PetscDrawCreate(comm,NULL,NULL,0,0,w,h,draw);CHKERRQ(ierr);
626   ierr = PetscDrawSetType(*draw,PETSC_DRAW_IMAGE);CHKERRQ(ierr);
627   ierr = PetscDrawSetSave(*draw,filename);CHKERRQ(ierr);
628   PetscFunctionReturn(0);
629 }
630