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