Actual source code: dsave.c

  1: #include <petsc/private/drawimpl.h>

  3: PETSC_EXTERN PetscErrorCode PetscDrawImageSave(const char[], const char[], unsigned char[][3], unsigned int, unsigned int, const unsigned char[]);
  4: PETSC_EXTERN PetscErrorCode PetscDrawMovieSave(const char[], PetscInt, const char[], PetscInt, const char[]);
  5: PETSC_EXTERN PetscErrorCode PetscDrawImageCheckFormat(const char *[]);
  6: PETSC_EXTERN PetscErrorCode PetscDrawMovieCheckFormat(const char *[]);

  8: #if defined(PETSC_HAVE_SAWS)
  9: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw);
 10: #endif

 12: /*@C
 13:    PetscDrawSetSave - Saves images produced in a `PetscDraw` into a file

 15:    Collective

 17:    Input Parameters:
 18: +  draw      - the graphics context
 19: -  filename  - name of the file, if .ext then uses name of draw object plus .ext using .ext to determine the image type

 21:    Options Database Keys:
 22: +  -draw_save <filename>  - filename could be name.ext or .ext (where .ext determines the type of graphics file to save, for example .png)
 23: .  -draw_save_final_image [optional filename] - saves the final image displayed in a window
 24: -  -draw_save_single_file - saves each new image in the same file, normally each new image is saved in a new file with filename/filename_%d.ext

 26:    Level: intermediate

 28:    Note:
 29:     You should call this BEFORE creating your image and calling `PetscDrawSave()`.
 30:    The supported image types are .png, .gif, .jpg, and .ppm (PETSc chooses the default in that order).
 31:    Support for .png images requires configure --with-libpng.
 32:    Support for .gif images requires configure --with-giflib.
 33:    Support for .jpg images requires configure --with-libjpeg.
 34:    Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).

 36: .seealso: `PetscDraw`, `PetscDrawOpenX()`, `PetscDrawOpenImage()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`, `PetscDrawSetSaveFinalImage()`
 37: @*/
 38: PetscErrorCode PetscDrawSetSave(PetscDraw draw, const char filename[])
 39: {
 40:   const char *savename = NULL;
 41:   const char *imageext = NULL;
 42:   char        buf[PETSC_MAX_PATH_LEN];


 47:   /* determine save filename and image extension */
 48:   if (filename && filename[0]) {
 49:     PetscStrchr(filename, '.', (char **)&imageext);
 50:     if (!imageext) savename = filename;
 51:     else if (imageext != filename) {
 52:       size_t l1 = 0, l2 = 0;
 53:       PetscStrlen(filename, &l1);
 54:       PetscStrlen(imageext, &l2);
 55:       PetscStrncpy(buf, filename, l1 - l2 + 1);
 56:       savename = buf;
 57:     }
 58:   }

 60:   if (!savename) PetscObjectGetName((PetscObject)draw, &savename);
 61:   PetscDrawImageCheckFormat(&imageext);

 63:   draw->savefilecount = 0;
 64:   PetscFree(draw->savefilename);
 65:   PetscFree(draw->saveimageext);
 66:   PetscStrallocpy(savename, &draw->savefilename);
 67:   PetscStrallocpy(imageext, &draw->saveimageext);

 69:   if (draw->savesinglefile) {
 70:     PetscInfo(NULL, "Will save image to file %s%s\n", draw->savefilename, draw->saveimageext);
 71:   } else {
 72:     PetscInfo(NULL, "Will save images to file %s/%s_%%d%s\n", draw->savefilename, draw->savefilename, draw->saveimageext);
 73:   }
 74:   return 0;
 75: }

 77: /*@C
 78:    PetscDrawSetSaveMovie - Saves a movie produced from a `PetscDraw` into a file

 80:    Collective

 82:    Input Parameters:
 83: +  draw      - the graphics context
 84: -  movieext  - optional extension defining the movie format

 86:    Options Database Key:
 87: .  -draw_save_movie <.ext> - saves a movie with extension .ext

 89:    Level: intermediate

 91:    Note:
 92:     You should call this AFTER calling `PetscDrawSetSave()` and BEFORE creating your image with `PetscDrawSave()`.
 93:    The ffmpeg utility must be in your path to make the movie.

 95: .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
 96: @*/
 97: PetscErrorCode PetscDrawSetSaveMovie(PetscDraw draw, const char movieext[])
 98: {

102:   if (!draw->savefilename) PetscDrawSetSave(draw, "");
103:   PetscDrawMovieCheckFormat(&movieext);
104:   PetscStrallocpy(movieext, &draw->savemovieext);
105:   draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */

107:   PetscInfo(NULL, "Will save movie to file %s%s\n", draw->savefilename, draw->savemovieext);
108:   return 0;
109: }

111: /*@C
112:    PetscDrawSetSaveFinalImage - Saves the final image produced in a `PetscDraw` into a file

114:    Collective

116:    Input Parameters:
117: +  draw      - the graphics context
118: -  filename  - name of the file, if NULL or empty uses name set with `PetscDrawSetSave()` or the name of the draw object

120:    Options Database Key:
121: .  -draw_save_final_image  <filename> - filename could be name.ext or .ext (where .ext determines the type of graphics file to save, for example .png)

123:    Level: intermediate

125:    Notes:
126:     You should call this BEFORE creating your image and calling `PetscDrawSave()`.

128:    The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
129: .vb
130:    Support for .png images requires configure --with-libpng.
131:    Support for .gif images requires configure --with-giflib.
132:    Support for .jpg images requires configure --with-libjpeg.
133:    Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
134: .ve

136: .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
137: @*/
138: PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw, const char filename[])
139: {
140:   char buf[PETSC_MAX_PATH_LEN];

143:   if (!filename || !filename[0]) {
144:     if (!draw->savefilename) {
145:       PetscObjectGetName((PetscObject)draw, &filename);
146:     } else {
147:       PetscSNPrintf(buf, sizeof(buf), "%s%s", draw->savefilename, draw->saveimageext);
148:       filename = buf;
149:     }
150:   }
151:   PetscFree(draw->savefinalfilename);
152:   PetscStrallocpy(filename, &draw->savefinalfilename);
153:   return 0;
154: }

156: /*@
157:    PetscDrawSave - Saves a drawn image

159:    Collective

161:    Input Parameters:
162: .  draw - the drawing context

164:    Level: advanced

166:    Note:
167:     this is not normally called by the user.

169: .seealso: `PetscDraw`, `PetscDrawSetSave()`
170: @*/
171: PetscErrorCode PetscDrawSave(PetscDraw draw)
172: {
173:   PetscInt       saveindex;
174:   char           basename[PETSC_MAX_PATH_LEN];
175:   unsigned char  palette[256][3];
176:   unsigned int   w, h;
177:   unsigned char *pixels = NULL;
178:   PetscMPIInt    rank;

181:   if (!draw->ops->save && !draw->ops->getimage) return 0;
182:   if (draw->ops->save) {
183:     PetscUseTypeMethod(draw, save);
184:     goto finally;
185:   }
186:   if (!draw->savefilename || !draw->saveimageext) return 0;
187:   MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank);

189:   saveindex = draw->savefilecount++;

191:   if (rank == 0 && !saveindex) {
192:     char path[PETSC_MAX_PATH_LEN];
193:     if (draw->savesinglefile) {
194:       PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->saveimageext);
195:       (void)remove(path);
196:     } else {
197:       PetscSNPrintf(path, sizeof(path), "%s", draw->savefilename);
198:       PetscRMTree(path);
199:       PetscMkdir(path);
200:     }
201:     if (draw->savemovieext) {
202:       PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->savemovieext);
203:       (void)remove(path);
204:     }
205:   }
206:   if (draw->savesinglefile) {
207:     PetscSNPrintf(basename, sizeof(basename), "%s", draw->savefilename);
208:   } else {
209:     char *basefilename;

211:     PetscStrrchr(draw->savefilename, '/', (char **)&basefilename);
212:     if (basefilename != draw->savefilename) {
213:       PetscSNPrintf(basename, sizeof(basename), "%s_%d", draw->savefilename, (int)saveindex);
214:     } else {
215:       PetscSNPrintf(basename, sizeof(basename), "%s/%s_%d", draw->savefilename, draw->savefilename, (int)saveindex);
216:     }
217:   }

219:   /* this call is collective, only the first process gets the image data */
220:   PetscUseTypeMethod(draw, getimage, palette, &w, &h, &pixels);
221:   /* only the first process handles the saving business */
222:   if (rank == 0) PetscDrawImageSave(basename, draw->saveimageext, palette, w, h, pixels);
223:   PetscFree(pixels);
224:   MPI_Barrier(PetscObjectComm((PetscObject)draw));

226: finally:
227: #if defined(PETSC_HAVE_SAWS)
228:   PetscDrawSave_SAWs(draw);
229: #endif
230:   return 0;
231: }

233: /*@
234:    PetscDrawSaveMovie - Saves a movie from previously saved images

236:    Collective

238:    Input Parameters:
239: .  draw - the drawing context

241:    Level: advanced

243:    Notes:
244:    This is not normally called by the user.

246:    The ffmpeg utility must be in your path to make the movie.

248: .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetSaveMovie()`
249: @*/
250: PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
251: {
252:   PetscMPIInt rank;

255:   if (!draw->ops->save && !draw->ops->getimage) return 0;
256:   if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) return 0;
257:   MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank);
258:   {
259:     const char *fname = draw->savefilename;
260:     const char *imext = draw->saveimageext;
261:     const char *mvext = draw->savemovieext;
262:     if (rank == 0) PetscDrawMovieSave(fname, draw->savefilecount, imext, draw->savemoviefps, mvext);
263:     MPI_Barrier(PetscObjectComm((PetscObject)draw));
264:   }
265:   return 0;
266: }

268: #if defined(PETSC_HAVE_SAWS)
269: #include <petscviewersaws.h>
270: /*
271:   The PetscImageList object and functions are used to maintain a list of file images
272:   that can be displayed by the SAWs webserver.
273: */
274: typedef struct _P_PetscImageList *PetscImageList;
275: struct _P_PetscImageList {
276:   PetscImageList next;
277:   char          *filename;
278:   char          *ext;
279:   PetscInt       count;
280: };

282: static PetscImageList SAWs_images = NULL;

284: static PetscErrorCode PetscImageListDestroy(void)
285: {
286:   PetscImageList image = SAWs_images;

288:   while (image) {
289:     PetscImageList next = image->next;
290:     PetscFree(image->filename);
291:     PetscFree(image->ext);
292:     PetscFree(image);
293:     image = next;
294:   }
295:   return 0;
296: }

298: static PetscErrorCode PetscImageListAdd(const char filename[], const char ext[], PetscInt count)
299: {
300:   PetscImageList image, oimage = SAWs_images;
301:   PetscBool      flg;

303:   if (oimage) {
304:     PetscStrcmp(filename, oimage->filename, &flg);
305:     if (flg) {
306:       oimage->count = count;
307:       return 0;
308:     }
309:     while (oimage->next) {
310:       oimage = oimage->next;
311:       PetscStrcmp(filename, oimage->filename, &flg);
312:       if (flg) {
313:         oimage->count = count;
314:         return 0;
315:       }
316:     }
317:     PetscNew(&image);
318:     oimage->next = image;
319:   } else {
320:     PetscRegisterFinalize(PetscImageListDestroy);
321:     PetscNew(&image);
322:     SAWs_images = image;
323:   }
324:   PetscStrallocpy(filename, &image->filename);
325:   PetscStrallocpy(ext, &image->ext);
326:   image->count = count;
327:   return 0;
328: }

330: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
331: {
332:   PetscImageList image;
333:   char           body[4096];
334:   size_t         len = 0;

336:   if (!draw->savefilename || !draw->saveimageext) return 0;
337:   PetscImageListAdd(draw->savefilename, draw->saveimageext, draw->savefilecount - 1);
338:   image = SAWs_images;
339:   while (image) {
340:     const char *name = image->filename;
341:     const char *ext  = image->ext;
342:     if (draw->savesinglefile) {
343:       PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s%s\" alt=\"None\">", name, ext);
344:     } else {
345:       PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s/%s_%d%s\" alt=\"None\">", name, name, image->count, ext);
346:     }
347:     PetscStrlen(body, &len);
348:     image = image->next;
349:   }
350:   PetscStrlcat(body, "<br>\n", sizeof(body));
351:   if (draw->savefilecount > 0) SAWs_Pop_Body, ("index.html", 1);
352:   SAWs_Push_Body, ("index.html", 1, body);
353:   return 0;
354: }

356: #endif