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