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