Actual source code: drawimage.c

  1: #include <../src/sys/classes/draw/impls/image/drawimage.h>
  2: #include <petsc/private/drawimpl.h>

  4: #if defined(PETSC_USE_DEBUG)
  6: #else
  7:   #define PetscDrawValidColor(color) \
  8:     do { \
  9:     } while (0)
 10: #endif

 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)))))

 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))

 18: static PetscErrorCode PetscDrawSetViewport_Image(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr)
 19: {
 20:   PetscImage img = (PetscImage)draw->data;
 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:   return 0;
 28: }

 30: /*
 31: static PetscErrorCode PetscDrawSetCoordinates_Image(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr)
 32: {
 33:   return 0;
 34: }*/
 35: #define PetscDrawSetCoordinates_Image NULL

 37: static PetscErrorCode PetscDrawCoordinateToPixel_Image(PetscDraw draw, PetscReal x, PetscReal y, int *i, int *j)
 38: {
 39:   PetscImage img = (PetscImage)draw->data;
 40:   if (i) *i = XTRANS(draw, img, x);
 41:   if (j) *j = YTRANS(draw, img, y);
 42:   return 0;
 43: }

 45: static PetscErrorCode PetscDrawPixelToCoordinate_Image(PetscDraw draw, int i, int j, PetscReal *x, PetscReal *y)
 46: {
 47:   PetscImage img = (PetscImage)draw->data;
 48:   if (x) *x = ITRANS(draw, img, i);
 49:   if (y) *y = JTRANS(draw, img, j);
 50:   return 0;
 51: }

 53: /*
 54: static PetscErrorCode PetscDrawPointSetSize_Image(PetscDraw draw,PetscReal width)
 55: {
 56:   return 0;
 57: }*/
 58: #define PetscDrawPointSetSize_Image NULL

 60: static PetscErrorCode PetscDrawPoint_Image(PetscDraw draw, PetscReal x, PetscReal y, int c)
 61: {
 62:   PetscImage img = (PetscImage)draw->data;
 63:   PetscDrawValidColor(c);
 64:   {
 65:     int j, xx = XTRANS(draw, img, x);
 66:     int i, yy = YTRANS(draw, img, y);
 67:     for (i = -1; i <= 1; i++)
 68:       for (j = -1; j <= 1; j++) PetscImageDrawPixel(img, xx + j, yy + i, c);
 69:   }
 70:   return 0;
 71: }

 73: static PetscErrorCode PetscDrawPointPixel_Image(PetscDraw draw, int x, int y, int c)
 74: {
 75:   PetscImage img = (PetscImage)draw->data;
 76:   PetscDrawValidColor(c);
 77:   {
 78:     PetscImageDrawPixel(img, x, y, c);
 79:   }
 80:   return 0;
 81: }

 83: /*
 84: static PetscErrorCode PetscDrawLineSetWidth_Image(PetscDraw draw,PetscReal width)
 85: {
 86:   return 0;
 87: }*/
 88: #define PetscDrawLineSetWidth_Image NULL

 90: static PetscErrorCode PetscDrawLineGetWidth_Image(PetscDraw draw, PetscReal *width)
 91: {
 92:   PetscImage img = (PetscImage)draw->data;
 93:   {
 94:     int lw = 1;
 95:     *width = lw * (draw->coor_xr - draw->coor_xl) / (img->w * (draw->port_xr - draw->port_xl));
 96:   }
 97:   return 0;
 98: }

100: static PetscErrorCode PetscDrawLine_Image(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c)
101: {
102:   PetscImage img = (PetscImage)draw->data;
103:   {
104:     int x_1 = XTRANS(draw, img, xl), x_2 = XTRANS(draw, img, xr);
105:     int y_1 = YTRANS(draw, img, yl), y_2 = YTRANS(draw, img, yr);
106:     PetscImageDrawLine(img, x_1, y_1, x_2, y_2, c);
107:   }
108:   return 0;
109: }

111: static PetscErrorCode PetscDrawArrow_Image(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c)
112: {
113:   PetscImage img = (PetscImage)draw->data;
114:   PetscDrawValidColor(c);
115:   {
116:     int x_1 = XTRANS(draw, img, xl), x_2 = XTRANS(draw, img, xr);
117:     int y_1 = YTRANS(draw, img, yl), y_2 = YTRANS(draw, img, yr);
118:     if (x_1 == x_2 && y_1 == y_2) return 0;
119:     PetscImageDrawLine(img, x_1, y_1, x_2, y_2, c);
120:     if (x_1 == x_2 && PetscAbs(y_1 - y_2) > 7) {
121:       if (y_2 > y_1) {
122:         PetscImageDrawLine(img, x_2, y_2, x_2 - 3, y_2 - 3, c);
123:         PetscImageDrawLine(img, x_2, y_2, x_2 + 3, y_2 - 3, c);
124:       } else {
125:         PetscImageDrawLine(img, x_2, y_2, x_2 - 3, y_2 + 3, c);
126:         PetscImageDrawLine(img, x_2, y_2, x_2 + 3, y_2 + 3, c);
127:       }
128:     }
129:     if (y_1 == y_2 && PetscAbs(x_1 - x_2) > 7) {
130:       if (x_2 > x_1) {
131:         PetscImageDrawLine(img, x_2 - 3, y_2 - 3, x_2, y_2, c);
132:         PetscImageDrawLine(img, x_2 - 3, y_2 + 3, x_2, y_2, c);
133:       } else {
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:       }
137:     }
138:   }
139:   return 0;
140: }

142: static PetscErrorCode PetscDrawRectangle_Image(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c1, int c2, int c3, int c4)
143: {
144:   PetscImage img = (PetscImage)draw->data;
145:   PetscDrawValidColor(c1);
146:   PetscDrawValidColor(c2);
147:   PetscDrawValidColor(c3);
148:   PetscDrawValidColor(c4);
149:   {
150:     int x = XTRANS(draw, img, xl), w = XTRANS(draw, img, xr) + 1 - x;
151:     int y = YTRANS(draw, img, yr), h = YTRANS(draw, img, yl) + 1 - y;
152:     int c = (c1 + c2 + c3 + c4) / 4;
153:     PetscImageDrawRectangle(img, x, y, w, h, c);
154:   }
155:   return 0;
156: }

158: static PetscErrorCode PetscDrawEllipse_Image(PetscDraw draw, PetscReal x, PetscReal y, PetscReal a, PetscReal b, int c)
159: {
160:   PetscImage img = (PetscImage)draw->data;
161:   PetscDrawValidColor(c);
162:   a = PetscAbsReal(a);
163:   b = PetscAbsReal(b);
164:   {
165:     int xc = XTRANS(draw, img, x), w = XTRANS(draw, img, x + a / 2) + 0 - xc;
166:     int yc = YTRANS(draw, img, y), h = YTRANS(draw, img, y - b / 2) + 0 - yc;
167:     if (PetscAbsReal(a - b) <= 0) w = h = PetscMin(w, h); /* workaround truncation errors */
168:     PetscImageDrawEllipse(img, xc, yc, w, h, c);
169:   }
170:   return 0;
171: }

173: 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)
174: {
175:   PetscImage img = (PetscImage)draw->data;
176:   PetscDrawValidColor(c1);
177:   PetscDrawValidColor(c2);
178:   PetscDrawValidColor(c3);
179:   {
180:     int x_1 = XTRANS(draw, img, X_1), x_2 = XTRANS(draw, img, X_2), x_3 = XTRANS(draw, img, X_3);
181:     int y_1 = YTRANS(draw, img, Y_1), y_2 = YTRANS(draw, img, Y_2), y_3 = YTRANS(draw, img, Y_3);
182:     PetscImageDrawTriangle(img, x_1, y_1, c1, x_2, y_2, c2, x_3, y_3, c3);
183:   }
184:   return 0;
185: }

187: /*
188: static PetscErrorCode PetscDrawStringSetSize_Image(PetscDraw draw,PetscReal w,PetscReal h)
189: {
190:   return 0;
191: }*/
192: #define PetscDrawStringSetSize_Image NULL

194: static PetscErrorCode PetscDrawStringGetSize_Image(PetscDraw draw, PetscReal *w, PetscReal *h)
195: {
196:   PetscImage img = (PetscImage)draw->data;
197:   {
198:     int tw = PetscImageFontWidth;
199:     int th = PetscImageFontHeight;
200:     if (w) *w = tw * (draw->coor_xr - draw->coor_xl) / (img->w * (draw->port_xr - draw->port_xl));
201:     if (h) *h = th * (draw->coor_yr - draw->coor_yl) / (img->h * (draw->port_yr - draw->port_yl));
202:   }
203:   return 0;
204: }

206: static PetscErrorCode PetscDrawString_Image(PetscDraw draw, PetscReal x, PetscReal y, int c, const char text[])
207: {
208:   PetscImage img = (PetscImage)draw->data;
209:   PetscToken token;
210:   char      *subtext;
211:   PetscDrawValidColor(c);
212:   {
213:     int xx = XTRANS(draw, img, x);
214:     int yy = YTRANS(draw, img, y);
215:     PetscTokenCreate(text, '\n', &token);
216:     PetscTokenFind(token, &subtext);
217:     while (subtext) {
218:       PetscImageDrawText(img, xx, yy, c, subtext);
219:       yy += PetscImageFontHeight;
220:       PetscTokenFind(token, &subtext);
221:     }
222:     PetscTokenDestroy(&token);
223:   }
224:   return 0;
225: }

227: static PetscErrorCode PetscDrawStringVertical_Image(PetscDraw draw, PetscReal x, PetscReal y, int c, const char text[])
228: {
229:   PetscImage img = (PetscImage)draw->data;
230:   PetscDrawValidColor(c);
231:   {
232:     char chr[2] = {0, 0};
233:     int  xx     = XTRANS(draw, img, x);
234:     int  yy     = YTRANS(draw, img, y);
235:     int  offset = PetscImageFontHeight;
236:     while ((chr[0] = *text++)) {
237:       PetscImageDrawText(img, xx, yy + offset, c, chr);
238:       yy += PetscImageFontHeight;
239:     }
240:   }
241:   return 0;
242: }

244: /*
245: static PetscErrorCode PetscDrawStringBoxed_Image(PetscDraw draw,PetscReal sxl,PetscReal syl,int sc,int bc,const char text[],PetscReal *w,PetscReal *h)
246: {
247:   if (w) *w = 0;
248:   if (h) *h = 0;
249:   return 0;
250: */
251: #define PetscDrawStringBoxed_Image NULL

253: /*
254: static PetscErrorCode PetscDrawFlush_Image(PetscDraw draw)
255: {
256:   return 0;
257: }*/
258: #define PetscDrawFlush_Image NULL

260: static PetscErrorCode PetscDrawClear_Image(PetscDraw draw)
261: {
262:   PetscImage img = (PetscImage)draw->data;
263:   {
264:     PetscImageClear(img);
265:   }
266:   return 0;
267: }

269: /*
270: static PetscErrorCode PetscDrawSetDoubleBuffer_Image(PetscDraw draw)
271: {
272:   return 0;
273: }*/
274: #define PetscDrawSetDoubleBuffer_Image NULL

276: static PetscErrorCode PetscDrawGetPopup_Image(PetscDraw draw, PetscDraw *popup)
277: {
278:   PetscBool flg = PETSC_FALSE;

280:   PetscOptionsGetBool(((PetscObject)draw)->options, ((PetscObject)draw)->prefix, "-draw_popup", &flg, NULL);
281:   if (!flg) {
282:     *popup = NULL;
283:     return 0;
284:   }
285:   PetscDrawCreate(PetscObjectComm((PetscObject)draw), NULL, NULL, 0, 0, 220, 220, popup);
286:   PetscDrawSetType(*popup, PETSC_DRAW_IMAGE);
287:   PetscObjectSetOptionsPrefix((PetscObject)*popup, "popup_");
288:   PetscObjectAppendOptionsPrefix((PetscObject)*popup, ((PetscObject)draw)->prefix);
289:   draw->popup = *popup;
290:   return 0;
291: }

293: /*
294: static PetscErrorCode PetscDrawSetTitle_Image(PetscDraw draw,const char title[])
295: {
296:   return 0;
297: }*/
298: #define PetscDrawSetTitle_Image NULL

300: /*
301: static PetscErrorCode PetscDrawCheckResizedWindow_Image(PetscDraw draw)
302: {
303:   return 0;
304: }*/
305: #define PetscDrawCheckResizedWindow_Image NULL

307: static PetscErrorCode PetscDrawResizeWindow_Image(PetscDraw draw, int w, int h)
308: {
309:   PetscImage img = (PetscImage)draw->data;

311:   if (w == img->w && h == img->h) return 0;
312:   PetscFree(img->buffer);

314:   img->w = w;
315:   img->h = h;
316:   PetscCalloc1((size_t)(img->w * img->h), &img->buffer);
317:   PetscDrawSetViewport_Image(draw, draw->port_xl, draw->port_yl, draw->port_xr, draw->port_yr);
318:   return 0;
319: }

321: static PetscErrorCode PetscDrawDestroy_Image(PetscDraw draw)
322: {
323:   PetscImage img = (PetscImage)draw->data;

325:   PetscDrawDestroy(&draw->popup);
326:   PetscFree(img->buffer);
327:   PetscFree(draw->data);
328:   return 0;
329: }

331: /*
332: static PetscErrorCode PetscDrawView_Image(PetscDraw draw,PetscViewer viewer)
333: {
334:   return 0;
335: }*/
336: #define PetscDrawView_Image NULL

338: /*
339: static PetscErrorCode PetscDrawGetMouseButton_Image(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
340: {
341:   *button = PETSC_BUTTON_NONE;
342:   if (x_user) *x_user = 0;
343:   if (y_user) *y_user = 0;
344:   if (x_phys) *x_phys = 0;
345:   if (y_phys) *y_phys = 0;
346:   return 0;
347: }*/
348: #define PetscDrawGetMouseButton_Image NULL

350: /*
351: static PetscErrorCode PetscDrawPause_Image(PetscDraw draw)
352: {
353:   return 0;
354: }*/
355: #define PetscDrawPause_Image NULL

357: /*
358: static PetscErrorCode PetscDrawBeginPage_Image(PetscDraw draw)
359: {
360:   return 0;
361: }*/
362: #define PetscDrawBeginPage_Image NULL

364: /*
365: static PetscErrorCode PetscDrawEndPage_Image(PetscDraw draw)
366: {
367:   return 0;
368: }*/
369: #define PetscDrawEndPage_Image NULL

371: static PetscErrorCode PetscDrawGetSingleton_Image(PetscDraw draw, PetscDraw *sdraw)
372: {
373:   PetscImage pimg = (PetscImage)draw->data;
374:   PetscImage simg;

376:   PetscDrawCreate(PETSC_COMM_SELF, NULL, NULL, 0, 0, draw->w, draw->h, sdraw);
377:   PetscDrawSetType(*sdraw, PETSC_DRAW_IMAGE);
378:   (*sdraw)->ops->resizewindow = NULL;
379:   simg                        = (PetscImage)(*sdraw)->data;
380:   PetscArraycpy(simg->buffer, pimg->buffer, pimg->w * pimg->h);
381:   return 0;
382: }

384: static PetscErrorCode PetscDrawRestoreSingleton_Image(PetscDraw draw, PetscDraw *sdraw)
385: {
386:   PetscImage pimg = (PetscImage)draw->data;
387:   PetscImage simg = (PetscImage)(*sdraw)->data;

389:   PetscArraycpy(pimg->buffer, simg->buffer, pimg->w * pimg->h);
390:   PetscDrawDestroy(sdraw);
391:   return 0;
392: }

394: /*
395: static PetscErrorCode PetscDrawSave_Image(PetscDraw draw)
396: {
397:   return 0;
398: }*/
399: #define PetscDrawSave_Image NULL

401: static PetscErrorCode PetscDrawGetImage_Image(PetscDraw draw, unsigned char palette[256][3], unsigned int *w, unsigned int *h, unsigned char *pixels[])
402: {
403:   PetscImage     img    = (PetscImage)draw->data;
404:   unsigned char *buffer = NULL;
405:   PetscMPIInt    rank, size;

407:   if (w) *w = (unsigned int)img->w;
408:   if (h) *h = (unsigned int)img->h;
409:   if (pixels) *pixels = NULL;
410:   MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank);
411:   if (rank == 0) {
412:     PetscMemcpy(palette, img->palette, sizeof(img->palette));
413:     PetscMalloc1((size_t)(img->w * img->h), &buffer);
414:     if (pixels) *pixels = buffer;
415:   }
416:   MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size);
417:   if (size == 1) {
418:     PetscArraycpy(buffer, img->buffer, img->w * img->h);
419:   } else {
420:     MPI_Reduce(img->buffer, buffer, img->w * img->h, MPI_UNSIGNED_CHAR, MPI_MAX, 0, PetscObjectComm((PetscObject)draw));
421:   }
422:   return 0;
423: }

425: 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};

427: static const unsigned char BasicColors[PETSC_DRAW_BASIC_COLORS][3] = {
428:   {255, 255, 255}, /* white */
429:   {0,   0,   0  }, /* black */
430:   {255, 0,   0  }, /* red */
431:   {0,   255, 0  }, /* green */
432:   {0,   255, 255}, /* cyan */
433:   {0,   0,   255}, /* blue */
434:   {255, 0,   255}, /* magenta */
435:   {127, 255, 212}, /* aquamarine */
436:   {34,  139, 34 }, /* forestgreen */
437:   {255, 165, 0  }, /* orange */
438:   {238, 130, 238}, /* violet */
439:   {165, 42,  42 }, /* brown */
440:   {255, 192, 203}, /* pink */
441:   {255, 127, 80 }, /* coral */
442:   {190, 190, 190}, /* gray */
443:   {255, 255, 0  }, /* yellow */
444:   {255, 215, 0  }, /* gold */
445:   {255, 182, 193}, /* lightpink */
446:   {72,  209, 204}, /* mediumturquoise */
447:   {240, 230, 140}, /* khaki */
448:   {105, 105, 105}, /* dimgray */
449:   {54,  205, 50 }, /* yellowgreen */
450:   {135, 206, 235}, /* skyblue */
451:   {0,   100, 0  }, /* darkgreen */
452:   {0,   0,   128}, /* navyblue */
453:   {244, 164, 96 }, /* sandybrown */
454:   {95,  158, 160}, /* cadetblue */
455:   {176, 224, 230}, /* powderblue */
456:   {255, 20,  147}, /* deeppink */
457:   {216, 191, 216}, /* thistle */
458:   {50,  205, 50 }, /* limegreen */
459:   {255, 240, 245}, /* lavenderblush */
460:   {221, 160, 221}, /* plum */
461: };

463: /*MC
464:    PETSC_DRAW_IMAGE - PETSc graphics device that uses a raster buffer

466:    Options Database Keys:
467: .  -draw_size w,h - size of image in pixels

469:    Level: beginner

471: .seealso: `PetscDrawOpenImage()`, `PetscDrawSetFromOptions()`
472: M*/
473: PETSC_EXTERN PetscErrorCode PetscDrawCreate_Image(PetscDraw);

475: PETSC_EXTERN PetscErrorCode PetscDrawCreate_Image(PetscDraw draw)
476: {
477:   PetscImage img;
478:   int        w = draw->w, h = draw->h;
479:   PetscInt   size[2], nsize = 2;
480:   PetscBool  set;

482:   draw->pause   = 0;
483:   draw->coor_xl = 0;
484:   draw->coor_xr = 1;
485:   draw->coor_yl = 0;
486:   draw->coor_yr = 1;
487:   draw->port_xl = 0;
488:   draw->port_xr = 1;
489:   draw->port_yl = 0;
490:   draw->port_yr = 1;

492:   size[0] = w;
493:   if (size[0] < 1) size[0] = 300;
494:   size[1] = h;
495:   if (size[1] < 1) size[1] = size[0];
496:   PetscOptionsGetIntArray(((PetscObject)draw)->options, ((PetscObject)draw)->prefix, "-draw_size", size, &nsize, &set);
497:   if (set && nsize == 1) size[1] = size[0];
498:   if (size[0] < 1) size[0] = 300;
499:   if (size[1] < 1) size[1] = size[0];
500:   draw->w = w = size[0];
501:   draw->x     = 0;
502:   draw->h = h = size[1];
503:   draw->x     = 0;

505:   PetscNew(&img);
506:   PetscMemcpy(draw->ops, &DvOps, sizeof(DvOps));
507:   draw->data = (void *)img;

509:   img->w = w;
510:   img->h = h;
511:   PetscCalloc1((size_t)(img->w * img->h), &img->buffer);
512:   PetscImageSetClip(img, 0, 0, img->w, img->h);
513:   {
514:     int           i, k, ncolors = 256 - PETSC_DRAW_BASIC_COLORS;
515:     unsigned char R[256 - PETSC_DRAW_BASIC_COLORS];
516:     unsigned char G[256 - PETSC_DRAW_BASIC_COLORS];
517:     unsigned char B[256 - PETSC_DRAW_BASIC_COLORS];
518:     PetscDrawUtilitySetCmap(NULL, ncolors, R, G, B);
519:     for (k = 0; k < PETSC_DRAW_BASIC_COLORS; k++) {
520:       img->palette[k][0] = BasicColors[k][0];
521:       img->palette[k][1] = BasicColors[k][1];
522:       img->palette[k][2] = BasicColors[k][2];
523:     }
524:     for (i = 0; i < ncolors; i++, k++) {
525:       img->palette[k][0] = R[i];
526:       img->palette[k][1] = G[i];
527:       img->palette[k][2] = B[i];
528:     }
529:   }

531:   if (!draw->savefilename) PetscDrawSetSave(draw, draw->title);
532:   return 0;
533: }

535: /*@C
536:    PetscDrawOpenImage - Opens an image for use with the `PetscDraw` routines.

538:    Collective

540:    Input Parameters:
541: +  comm - the communicator that will share image
542: -  filename - optional name of the file where the image will be stored
543: -  w, h - the image width and height in pixels

545:    Output Parameters:
546: .  draw - the drawing context.

548:    Level: beginner

550: .seealso: `PetscDraw`, `PETSC_DRAW_IMAGE`, `PETSC_DRAW_X`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
551: @*/
552: PetscErrorCode PetscDrawOpenImage(MPI_Comm comm, const char filename[], int w, int h, PetscDraw *draw)
553: {
554:   PetscDrawCreate(comm, NULL, NULL, 0, 0, w, h, draw);
555:   PetscDrawSetType(*draw, PETSC_DRAW_IMAGE);
556:   PetscDrawSetSave(*draw, filename);
557:   return 0;
558: }