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