xref: /petsc/src/sys/classes/draw/interface/dsave.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
15b399a63SLisandro Dalcin #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/
25b399a63SLisandro Dalcin 
38067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSave(const char[], const char[], unsigned char[][3], unsigned int, unsigned int, const unsigned char[]);
449c04938SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieSave(const char[], PetscInt, const char[], PetscInt, const char[]);
58067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageCheckFormat(const char *[]);
68067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieCheckFormat(const char *[]);
78067a7d5SLisandro Dalcin 
88067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
98067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawSave_SAWs(PetscDraw);
108067a7d5SLisandro Dalcin #endif
118067a7d5SLisandro Dalcin 
125b399a63SLisandro Dalcin /*@C
138067a7d5SLisandro Dalcin    PetscDrawSetSave - Saves images produced in a PetscDraw into a file
145b399a63SLisandro Dalcin 
155b399a63SLisandro Dalcin    Collective on PetscDraw
165b399a63SLisandro Dalcin 
17d8d19677SJose E. Roman    Input Parameters:
185b399a63SLisandro Dalcin +  draw      - the graphics context
1949c04938SLisandro Dalcin -  filename  - name of the file, if .ext then uses name of draw object plus .ext using .ext to determine the image type
205b399a63SLisandro Dalcin 
215b399a63SLisandro Dalcin    Options Database Command:
228067a7d5SLisandro Dalcin +  -draw_save <filename>  - filename could be name.ext or .ext (where .ext determines the type of graphics file to save, for example .png)
238067a7d5SLisandro Dalcin .  -draw_save_final_image [optional filename] - saves the final image displayed in a window
248067a7d5SLisandro Dalcin -  -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
255b399a63SLisandro Dalcin 
265b399a63SLisandro Dalcin    Level: intermediate
275b399a63SLisandro Dalcin 
2895452b02SPatrick Sanan    Notes:
2995452b02SPatrick Sanan     You should call this BEFORE creating your image and calling PetscDrawSave().
308067a7d5SLisandro Dalcin    The supported image types are .png, .gif, .jpg, and .ppm (PETSc chooses the default in that order).
318067a7d5SLisandro Dalcin    Support for .png images requires configure --with-libpng.
328067a7d5SLisandro Dalcin    Support for .gif images requires configure --with-giflib.
338067a7d5SLisandro Dalcin    Support for .jpg images requires configure --with-libjpeg.
348067a7d5SLisandro Dalcin    Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
355b399a63SLisandro Dalcin 
36db781477SPatrick Sanan .seealso: `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`, `PetscDrawSetSaveFinalImage()`
375b399a63SLisandro Dalcin @*/
38*9371c9d4SSatish Balay PetscErrorCode PetscDrawSetSave(PetscDraw draw, const char filename[]) {
398067a7d5SLisandro Dalcin   const char *savename = NULL;
408067a7d5SLisandro Dalcin   const char *imageext = NULL;
4171ed57bfSLisandro Dalcin   char        buf[PETSC_MAX_PATH_LEN];
425b399a63SLisandro Dalcin 
435b399a63SLisandro Dalcin   PetscFunctionBegin;
445b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
4571ed57bfSLisandro Dalcin   if (filename) PetscValidCharPointer(filename, 2);
465b399a63SLisandro Dalcin 
478067a7d5SLisandro Dalcin   /* determine save filename and image extension */
485b399a63SLisandro Dalcin   if (filename && filename[0]) {
499566063dSJacob Faibussowitsch     PetscCall(PetscStrchr(filename, '.', (char **)&imageext));
508067a7d5SLisandro Dalcin     if (!imageext) savename = filename;
518067a7d5SLisandro Dalcin     else if (imageext != filename) {
5271ed57bfSLisandro Dalcin       size_t l1 = 0, l2 = 0;
539566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(filename, &l1));
549566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(imageext, &l2));
559566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(buf, filename, l1 - l2 + 1));
568067a7d5SLisandro Dalcin       savename = buf;
575b399a63SLisandro Dalcin     }
5871ed57bfSLisandro Dalcin   }
5971ed57bfSLisandro Dalcin 
609566063dSJacob Faibussowitsch   if (!savename) PetscCall(PetscObjectGetName((PetscObject)draw, &savename));
619566063dSJacob Faibussowitsch   PetscCall(PetscDrawImageCheckFormat(&imageext));
628067a7d5SLisandro Dalcin 
638067a7d5SLisandro Dalcin   draw->savefilecount = 0;
649566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->savefilename));
659566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->saveimageext));
669566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(savename, &draw->savefilename));
679566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(imageext, &draw->saveimageext));
6849c04938SLisandro Dalcin 
6949c04938SLisandro Dalcin   if (draw->savesinglefile) {
709566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Will save image to file %s%s\n", draw->savefilename, draw->saveimageext));
7149c04938SLisandro Dalcin   } else {
729566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Will save images to file %s/%s_%%d%s\n", draw->savefilename, draw->savefilename, draw->saveimageext));
7349c04938SLisandro Dalcin   }
7449c04938SLisandro Dalcin   PetscFunctionReturn(0);
7549c04938SLisandro Dalcin }
7649c04938SLisandro Dalcin 
7749c04938SLisandro Dalcin /*@C
7849c04938SLisandro Dalcin    PetscDrawSetSaveMovie - Saves a movie produced from a PetscDraw into a file
7949c04938SLisandro Dalcin 
8049c04938SLisandro Dalcin    Collective on PetscDraw
8149c04938SLisandro Dalcin 
82d8d19677SJose E. Roman    Input Parameters:
8349c04938SLisandro Dalcin +  draw      - the graphics context
8449c04938SLisandro Dalcin -  movieext  - optional extension defining the movie format
8549c04938SLisandro Dalcin 
8649c04938SLisandro Dalcin    Options Database Command:
8749c04938SLisandro Dalcin .  -draw_save_movie <.ext> - saves a movie with extension .ext
8849c04938SLisandro Dalcin 
8949c04938SLisandro Dalcin    Level: intermediate
9049c04938SLisandro Dalcin 
9195452b02SPatrick Sanan    Notes:
9295452b02SPatrick Sanan     You should call this AFTER calling PetscDrawSetSave() and BEFORE creating your image with PetscDrawSave().
9349c04938SLisandro Dalcin    The ffmpeg utility must be in your path to make the movie.
9449c04938SLisandro Dalcin 
95db781477SPatrick Sanan .seealso: `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
9649c04938SLisandro Dalcin @*/
97*9371c9d4SSatish Balay PetscErrorCode PetscDrawSetSaveMovie(PetscDraw draw, const char movieext[]) {
9849c04938SLisandro Dalcin   PetscFunctionBegin;
9949c04938SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
10049c04938SLisandro Dalcin   if (movieext) PetscValidCharPointer(movieext, 2);
10149c04938SLisandro Dalcin 
1029566063dSJacob Faibussowitsch   if (!draw->savefilename) PetscCall(PetscDrawSetSave(draw, ""));
1039566063dSJacob Faibussowitsch   PetscCall(PetscDrawMovieCheckFormat(&movieext));
1049566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(movieext, &draw->savemovieext));
10549c04938SLisandro Dalcin   draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */
10649c04938SLisandro Dalcin 
1079566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Will save movie to file %s%s\n", draw->savefilename, draw->savemovieext));
1085b399a63SLisandro Dalcin   PetscFunctionReturn(0);
1095b399a63SLisandro Dalcin }
1105b399a63SLisandro Dalcin 
1115b399a63SLisandro Dalcin /*@C
1128067a7d5SLisandro Dalcin    PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file
1135b399a63SLisandro Dalcin 
1145b399a63SLisandro Dalcin    Collective on PetscDraw
1155b399a63SLisandro Dalcin 
116d8d19677SJose E. Roman    Input Parameters:
1175b399a63SLisandro Dalcin +  draw      - the graphics context
1188067a7d5SLisandro Dalcin -  filename  - name of the file, if NULL or empty uses name set with PetscDrawSetSave() or name of draw object
1195b399a63SLisandro Dalcin 
1205b399a63SLisandro Dalcin    Options Database Command:
1218067a7d5SLisandro Dalcin .  -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)
1225b399a63SLisandro Dalcin 
1235b399a63SLisandro Dalcin    Level: intermediate
1245b399a63SLisandro Dalcin 
12595452b02SPatrick Sanan    Notes:
12695452b02SPatrick Sanan     You should call this BEFORE creating your image and calling PetscDrawSave().
1278067a7d5SLisandro Dalcin    The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
1288067a7d5SLisandro Dalcin    Support for .png images requires configure --with-libpng.
1298067a7d5SLisandro Dalcin    Support for .gif images requires configure --with-giflib.
1308067a7d5SLisandro Dalcin    Support for .jpg images requires configure --with-libjpeg.
1318067a7d5SLisandro Dalcin    Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
1325b399a63SLisandro Dalcin 
133db781477SPatrick Sanan .seealso: `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
1345b399a63SLisandro Dalcin @*/
135*9371c9d4SSatish Balay PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw, const char filename[]) {
1368067a7d5SLisandro Dalcin   char buf[PETSC_MAX_PATH_LEN];
1375b399a63SLisandro Dalcin 
1385b399a63SLisandro Dalcin   PetscFunctionBegin;
1395b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
1408067a7d5SLisandro Dalcin   if (!filename || !filename[0]) {
1418067a7d5SLisandro Dalcin     if (!draw->savefilename) {
1429566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)draw, &filename));
1435b399a63SLisandro Dalcin     } else {
1449566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, sizeof(buf), "%s%s", draw->savefilename, draw->saveimageext));
1458067a7d5SLisandro Dalcin       filename = buf;
1465b399a63SLisandro Dalcin     }
1478067a7d5SLisandro Dalcin   }
1489566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->savefinalfilename));
1499566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(filename, &draw->savefinalfilename));
1505b399a63SLisandro Dalcin   PetscFunctionReturn(0);
1515b399a63SLisandro Dalcin }
1525b399a63SLisandro Dalcin 
1535b399a63SLisandro Dalcin /*@
1545b399a63SLisandro Dalcin    PetscDrawSave - Saves a drawn image
1555b399a63SLisandro Dalcin 
1565b399a63SLisandro Dalcin    Collective on PetscDraw
1575b399a63SLisandro Dalcin 
1585b399a63SLisandro Dalcin    Input Parameters:
1595b399a63SLisandro Dalcin .  draw - the drawing context
1605b399a63SLisandro Dalcin 
1615b399a63SLisandro Dalcin    Level: advanced
1625b399a63SLisandro Dalcin 
16395452b02SPatrick Sanan    Notes:
16495452b02SPatrick Sanan     this is not normally called by the user.
1655b399a63SLisandro Dalcin 
166db781477SPatrick Sanan .seealso: `PetscDrawSetSave()`
1675b399a63SLisandro Dalcin 
1685b399a63SLisandro Dalcin @*/
169*9371c9d4SSatish Balay PetscErrorCode PetscDrawSave(PetscDraw draw) {
17049c04938SLisandro Dalcin   PetscInt       saveindex;
1718067a7d5SLisandro Dalcin   char           basename[PETSC_MAX_PATH_LEN];
1728067a7d5SLisandro Dalcin   unsigned char  palette[256][3];
1738067a7d5SLisandro Dalcin   unsigned int   w, h;
1748067a7d5SLisandro Dalcin   unsigned char *pixels = NULL;
1758067a7d5SLisandro Dalcin   PetscMPIInt    rank;
1765b399a63SLisandro Dalcin 
1775b399a63SLisandro Dalcin   PetscFunctionBegin;
1785b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
17949c04938SLisandro Dalcin   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(0);
180*9371c9d4SSatish Balay   if (draw->ops->save) {
181*9371c9d4SSatish Balay     PetscUseTypeMethod(draw, save);
182*9371c9d4SSatish Balay     goto finally;
183*9371c9d4SSatish Balay   }
18449c04938SLisandro Dalcin   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(0);
1859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
1868067a7d5SLisandro Dalcin 
18749c04938SLisandro Dalcin   saveindex = draw->savefilecount++;
1888067a7d5SLisandro Dalcin 
189dd400576SPatrick Sanan   if (rank == 0 && !saveindex) {
1908067a7d5SLisandro Dalcin     char path[PETSC_MAX_PATH_LEN];
1918067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
1929566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->saveimageext));
1938067a7d5SLisandro Dalcin       (void)remove(path);
1948067a7d5SLisandro Dalcin     } else {
1959566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s", draw->savefilename));
1969566063dSJacob Faibussowitsch       PetscCall(PetscRMTree(path));
1979566063dSJacob Faibussowitsch       PetscCall(PetscMkdir(path));
1988067a7d5SLisandro Dalcin     }
1998067a7d5SLisandro Dalcin     if (draw->savemovieext) {
2009566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->savemovieext));
2018067a7d5SLisandro Dalcin       (void)remove(path);
2028067a7d5SLisandro Dalcin     }
2038067a7d5SLisandro Dalcin   }
2048067a7d5SLisandro Dalcin   if (draw->savesinglefile) {
2059566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s", draw->savefilename));
2068067a7d5SLisandro Dalcin   } else {
20780603804SMatthew G. Knepley     char *basefilename;
20880603804SMatthew G. Knepley 
2099566063dSJacob Faibussowitsch     PetscCall(PetscStrrchr(draw->savefilename, '/', (char **)&basefilename));
21080603804SMatthew G. Knepley     if (basefilename != draw->savefilename) {
2119566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s_%d", draw->savefilename, (int)saveindex));
21280603804SMatthew G. Knepley     } else {
2139566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s/%s_%d", draw->savefilename, draw->savefilename, (int)saveindex));
2148067a7d5SLisandro Dalcin     }
21580603804SMatthew G. Knepley   }
2168067a7d5SLisandro Dalcin 
2178067a7d5SLisandro Dalcin   /* this call is collective, only the first process gets the image data */
218dbbe0bcdSBarry Smith   PetscUseTypeMethod(draw, getimage, palette, &w, &h, &pixels);
2198067a7d5SLisandro Dalcin   /* only the first process handles the saving business */
2209566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscDrawImageSave(basename, draw->saveimageext, palette, w, h, pixels));
2219566063dSJacob Faibussowitsch   PetscCall(PetscFree(pixels));
2229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw)));
2238067a7d5SLisandro Dalcin 
2248067a7d5SLisandro Dalcin finally:
2258067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
2269566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave_SAWs(draw));
2278067a7d5SLisandro Dalcin #endif
2288067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
2298067a7d5SLisandro Dalcin }
2308067a7d5SLisandro Dalcin 
23149c04938SLisandro Dalcin /*@
23249c04938SLisandro Dalcin    PetscDrawSaveMovie - Saves a movie from previously saved images
23349c04938SLisandro Dalcin 
23449c04938SLisandro Dalcin    Collective on PetscDraw
23549c04938SLisandro Dalcin 
23649c04938SLisandro Dalcin    Input Parameters:
23749c04938SLisandro Dalcin .  draw - the drawing context
23849c04938SLisandro Dalcin 
23949c04938SLisandro Dalcin    Level: advanced
24049c04938SLisandro Dalcin 
24195452b02SPatrick Sanan    Notes:
24295452b02SPatrick Sanan     this is not normally called by the user.
24349c04938SLisandro Dalcin    The ffmpeg utility must be in your path to make the movie.
24449c04938SLisandro Dalcin 
245db781477SPatrick Sanan .seealso: `PetscDrawSetSave()`, `PetscDrawSetSaveMovie()`
24649c04938SLisandro Dalcin 
24749c04938SLisandro Dalcin @*/
248*9371c9d4SSatish Balay PetscErrorCode PetscDrawSaveMovie(PetscDraw draw) {
24949c04938SLisandro Dalcin   PetscMPIInt rank;
25049c04938SLisandro Dalcin 
25149c04938SLisandro Dalcin   PetscFunctionBegin;
25249c04938SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
25349c04938SLisandro Dalcin   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(0);
25449c04938SLisandro Dalcin   if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) PetscFunctionReturn(0);
2559566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
25649c04938SLisandro Dalcin   {
25749c04938SLisandro Dalcin     const char *fname = draw->savefilename;
25849c04938SLisandro Dalcin     const char *imext = draw->saveimageext;
25949c04938SLisandro Dalcin     const char *mvext = draw->savemovieext;
2609566063dSJacob Faibussowitsch     if (rank == 0) PetscCall(PetscDrawMovieSave(fname, draw->savefilecount, imext, draw->savemoviefps, mvext));
2619566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw)));
26249c04938SLisandro Dalcin   }
26349c04938SLisandro Dalcin   PetscFunctionReturn(0);
26449c04938SLisandro Dalcin }
26549c04938SLisandro Dalcin 
2668067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
2678067a7d5SLisandro Dalcin #include <petscviewersaws.h>
2688067a7d5SLisandro Dalcin /*
2698067a7d5SLisandro Dalcin   The PetscImageList object and functions are used to maintain a list of file images
2708067a7d5SLisandro Dalcin   that can be displayed by the SAWs webserver.
2718067a7d5SLisandro Dalcin */
2728067a7d5SLisandro Dalcin typedef struct _P_PetscImageList *PetscImageList;
2738067a7d5SLisandro Dalcin struct _P_PetscImageList {
2748067a7d5SLisandro Dalcin   PetscImageList next;
2758067a7d5SLisandro Dalcin   char          *filename;
2768067a7d5SLisandro Dalcin   char          *ext;
2778067a7d5SLisandro Dalcin   PetscInt       count;
2788067a7d5SLisandro Dalcin };
2798067a7d5SLisandro Dalcin 
2808067a7d5SLisandro Dalcin static PetscImageList SAWs_images = NULL;
2818067a7d5SLisandro Dalcin 
282*9371c9d4SSatish Balay static PetscErrorCode PetscImageListDestroy(void) {
2838067a7d5SLisandro Dalcin   PetscImageList image = SAWs_images;
2848067a7d5SLisandro Dalcin 
2858067a7d5SLisandro Dalcin   PetscFunctionBegin;
2868067a7d5SLisandro Dalcin   while (image) {
2878067a7d5SLisandro Dalcin     PetscImageList next = image->next;
2889566063dSJacob Faibussowitsch     PetscCall(PetscFree(image->filename));
2899566063dSJacob Faibussowitsch     PetscCall(PetscFree(image->ext));
2909566063dSJacob Faibussowitsch     PetscCall(PetscFree(image));
2918067a7d5SLisandro Dalcin     image = next;
2925b399a63SLisandro Dalcin   }
2935b399a63SLisandro Dalcin   PetscFunctionReturn(0);
2945b399a63SLisandro Dalcin }
2958067a7d5SLisandro Dalcin 
296*9371c9d4SSatish Balay static PetscErrorCode PetscImageListAdd(const char filename[], const char ext[], PetscInt count) {
2978067a7d5SLisandro Dalcin   PetscImageList image, oimage = SAWs_images;
2988067a7d5SLisandro Dalcin   PetscBool      flg;
2998067a7d5SLisandro Dalcin 
3008067a7d5SLisandro Dalcin   PetscFunctionBegin;
3018067a7d5SLisandro Dalcin   if (oimage) {
3029566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(filename, oimage->filename, &flg));
3038067a7d5SLisandro Dalcin     if (flg) {
3048067a7d5SLisandro Dalcin       oimage->count = count;
3058067a7d5SLisandro Dalcin       PetscFunctionReturn(0);
3068067a7d5SLisandro Dalcin     }
3078067a7d5SLisandro Dalcin     while (oimage->next) {
3088067a7d5SLisandro Dalcin       oimage = oimage->next;
3099566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(filename, oimage->filename, &flg));
3108067a7d5SLisandro Dalcin       if (flg) {
3118067a7d5SLisandro Dalcin         oimage->count = count;
3128067a7d5SLisandro Dalcin         PetscFunctionReturn(0);
3138067a7d5SLisandro Dalcin       }
3148067a7d5SLisandro Dalcin     }
3159566063dSJacob Faibussowitsch     PetscCall(PetscNew(&image));
3168067a7d5SLisandro Dalcin     oimage->next = image;
3178067a7d5SLisandro Dalcin   } else {
3189566063dSJacob Faibussowitsch     PetscCall(PetscRegisterFinalize(PetscImageListDestroy));
3199566063dSJacob Faibussowitsch     PetscCall(PetscNew(&image));
3208067a7d5SLisandro Dalcin     SAWs_images = image;
3218067a7d5SLisandro Dalcin   }
3229566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(filename, &image->filename));
3239566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ext, &image->ext));
3248067a7d5SLisandro Dalcin   image->count = count;
3258067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
3268067a7d5SLisandro Dalcin }
3278067a7d5SLisandro Dalcin 
328*9371c9d4SSatish Balay static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw) {
3298067a7d5SLisandro Dalcin   PetscImageList image;
3308067a7d5SLisandro Dalcin   char           body[4096];
3318067a7d5SLisandro Dalcin   size_t         len = 0;
3328067a7d5SLisandro Dalcin 
3338067a7d5SLisandro Dalcin   PetscFunctionBegin;
33449c04938SLisandro Dalcin   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(0);
3359566063dSJacob Faibussowitsch   PetscCall(PetscImageListAdd(draw->savefilename, draw->saveimageext, draw->savefilecount - 1));
3368067a7d5SLisandro Dalcin   image = SAWs_images;
3378067a7d5SLisandro Dalcin   while (image) {
3388067a7d5SLisandro Dalcin     const char *name = image->filename;
3398067a7d5SLisandro Dalcin     const char *ext  = image->ext;
3408067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
3419566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s%s\" alt=\"None\">", name, ext));
3428067a7d5SLisandro Dalcin     } else {
3439566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s/%s_%d%s\" alt=\"None\">", name, name, image->count, ext));
3448067a7d5SLisandro Dalcin     }
3459566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(body, &len));
3468067a7d5SLisandro Dalcin     image = image->next;
3478067a7d5SLisandro Dalcin   }
3489566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(body, "<br>\n", sizeof(body)));
349792fecdfSBarry Smith   if (draw->savefilecount > 0) PetscCallSAWs(SAWs_Pop_Body, ("index.html", 1));
350792fecdfSBarry Smith   PetscCallSAWs(SAWs_Push_Body, ("index.html", 1, body));
3518067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
3528067a7d5SLisandro Dalcin }
3538067a7d5SLisandro Dalcin 
3548067a7d5SLisandro Dalcin #endif
355