xref: /petsc/src/sys/classes/draw/interface/dsave.c (revision 811af0c4b09a35de4306c442f88bd09fdc09897d)
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
13*811af0c4SBarry Smith    PetscDrawSetSave - Saves images produced in a `PetscDraw` into a file
145b399a63SLisandro Dalcin 
15*811af0c4SBarry Smith    Collective on draw
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 
28*811af0c4SBarry Smith    Note:
29*811af0c4SBarry Smith     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 
36*811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawOpenX()`, `PetscDrawOpenImage()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`, `PetscDrawSetSaveFinalImage()`
375b399a63SLisandro Dalcin @*/
389371c9d4SSatish 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
78*811af0c4SBarry Smith    PetscDrawSetSaveMovie - Saves a movie produced from a `PetscDraw` into a file
7949c04938SLisandro Dalcin 
80*811af0c4SBarry Smith    Collective on draw
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 
91*811af0c4SBarry Smith    Note:
92*811af0c4SBarry Smith     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 
95*811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
9649c04938SLisandro Dalcin @*/
979371c9d4SSatish 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
112*811af0c4SBarry Smith    PetscDrawSetSaveFinalImage - Saves the final image produced in a `PetscDraw` into a file
1135b399a63SLisandro Dalcin 
114*811af0c4SBarry Smith    Collective on draw
1155b399a63SLisandro Dalcin 
116d8d19677SJose E. Roman    Input Parameters:
1175b399a63SLisandro Dalcin +  draw      - the graphics context
118*811af0c4SBarry Smith -  filename  - name of the file, if NULL or empty uses name set with `PetscDrawSetSave()` or the name of the 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:
126*811af0c4SBarry Smith     You should call this BEFORE creating your image and calling `PetscDrawSave()`.
127*811af0c4SBarry Smith 
1288067a7d5SLisandro Dalcin    The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
129*811af0c4SBarry Smith .vb
1308067a7d5SLisandro Dalcin    Support for .png images requires configure --with-libpng.
1318067a7d5SLisandro Dalcin    Support for .gif images requires configure --with-giflib.
1328067a7d5SLisandro Dalcin    Support for .jpg images requires configure --with-libjpeg.
1338067a7d5SLisandro Dalcin    Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
134*811af0c4SBarry Smith .ve
1355b399a63SLisandro Dalcin 
136*811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
1375b399a63SLisandro Dalcin @*/
1389371c9d4SSatish Balay PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw, const char filename[]) {
1398067a7d5SLisandro Dalcin   char buf[PETSC_MAX_PATH_LEN];
1405b399a63SLisandro Dalcin 
1415b399a63SLisandro Dalcin   PetscFunctionBegin;
1425b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
1438067a7d5SLisandro Dalcin   if (!filename || !filename[0]) {
1448067a7d5SLisandro Dalcin     if (!draw->savefilename) {
1459566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)draw, &filename));
1465b399a63SLisandro Dalcin     } else {
1479566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, sizeof(buf), "%s%s", draw->savefilename, draw->saveimageext));
1488067a7d5SLisandro Dalcin       filename = buf;
1495b399a63SLisandro Dalcin     }
1508067a7d5SLisandro Dalcin   }
1519566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->savefinalfilename));
1529566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(filename, &draw->savefinalfilename));
1535b399a63SLisandro Dalcin   PetscFunctionReturn(0);
1545b399a63SLisandro Dalcin }
1555b399a63SLisandro Dalcin 
1565b399a63SLisandro Dalcin /*@
1575b399a63SLisandro Dalcin    PetscDrawSave - Saves a drawn image
1585b399a63SLisandro Dalcin 
159*811af0c4SBarry Smith    Collective on draw
1605b399a63SLisandro Dalcin 
1615b399a63SLisandro Dalcin    Input Parameters:
1625b399a63SLisandro Dalcin .  draw - the drawing context
1635b399a63SLisandro Dalcin 
1645b399a63SLisandro Dalcin    Level: advanced
1655b399a63SLisandro Dalcin 
166*811af0c4SBarry Smith    Note:
16795452b02SPatrick Sanan     this is not normally called by the user.
1685b399a63SLisandro Dalcin 
169*811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`
1705b399a63SLisandro Dalcin @*/
1719371c9d4SSatish Balay PetscErrorCode PetscDrawSave(PetscDraw draw) {
17249c04938SLisandro Dalcin   PetscInt       saveindex;
1738067a7d5SLisandro Dalcin   char           basename[PETSC_MAX_PATH_LEN];
1748067a7d5SLisandro Dalcin   unsigned char  palette[256][3];
1758067a7d5SLisandro Dalcin   unsigned int   w, h;
1768067a7d5SLisandro Dalcin   unsigned char *pixels = NULL;
1778067a7d5SLisandro Dalcin   PetscMPIInt    rank;
1785b399a63SLisandro Dalcin 
1795b399a63SLisandro Dalcin   PetscFunctionBegin;
1805b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
18149c04938SLisandro Dalcin   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(0);
1829371c9d4SSatish Balay   if (draw->ops->save) {
1839371c9d4SSatish Balay     PetscUseTypeMethod(draw, save);
1849371c9d4SSatish Balay     goto finally;
1859371c9d4SSatish Balay   }
18649c04938SLisandro Dalcin   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(0);
1879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
1888067a7d5SLisandro Dalcin 
18949c04938SLisandro Dalcin   saveindex = draw->savefilecount++;
1908067a7d5SLisandro Dalcin 
191dd400576SPatrick Sanan   if (rank == 0 && !saveindex) {
1928067a7d5SLisandro Dalcin     char path[PETSC_MAX_PATH_LEN];
1938067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
1949566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->saveimageext));
1958067a7d5SLisandro Dalcin       (void)remove(path);
1968067a7d5SLisandro Dalcin     } else {
1979566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s", draw->savefilename));
1989566063dSJacob Faibussowitsch       PetscCall(PetscRMTree(path));
1999566063dSJacob Faibussowitsch       PetscCall(PetscMkdir(path));
2008067a7d5SLisandro Dalcin     }
2018067a7d5SLisandro Dalcin     if (draw->savemovieext) {
2029566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->savemovieext));
2038067a7d5SLisandro Dalcin       (void)remove(path);
2048067a7d5SLisandro Dalcin     }
2058067a7d5SLisandro Dalcin   }
2068067a7d5SLisandro Dalcin   if (draw->savesinglefile) {
2079566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s", draw->savefilename));
2088067a7d5SLisandro Dalcin   } else {
20980603804SMatthew G. Knepley     char *basefilename;
21080603804SMatthew G. Knepley 
2119566063dSJacob Faibussowitsch     PetscCall(PetscStrrchr(draw->savefilename, '/', (char **)&basefilename));
21280603804SMatthew G. Knepley     if (basefilename != draw->savefilename) {
2139566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s_%d", draw->savefilename, (int)saveindex));
21480603804SMatthew G. Knepley     } else {
2159566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s/%s_%d", draw->savefilename, draw->savefilename, (int)saveindex));
2168067a7d5SLisandro Dalcin     }
21780603804SMatthew G. Knepley   }
2188067a7d5SLisandro Dalcin 
2198067a7d5SLisandro Dalcin   /* this call is collective, only the first process gets the image data */
220dbbe0bcdSBarry Smith   PetscUseTypeMethod(draw, getimage, palette, &w, &h, &pixels);
2218067a7d5SLisandro Dalcin   /* only the first process handles the saving business */
2229566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscDrawImageSave(basename, draw->saveimageext, palette, w, h, pixels));
2239566063dSJacob Faibussowitsch   PetscCall(PetscFree(pixels));
2249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw)));
2258067a7d5SLisandro Dalcin 
2268067a7d5SLisandro Dalcin finally:
2278067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
2289566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave_SAWs(draw));
2298067a7d5SLisandro Dalcin #endif
2308067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
2318067a7d5SLisandro Dalcin }
2328067a7d5SLisandro Dalcin 
23349c04938SLisandro Dalcin /*@
23449c04938SLisandro Dalcin    PetscDrawSaveMovie - Saves a movie from previously saved images
23549c04938SLisandro Dalcin 
236*811af0c4SBarry Smith    Collective on draw
23749c04938SLisandro Dalcin 
23849c04938SLisandro Dalcin    Input Parameters:
23949c04938SLisandro Dalcin .  draw - the drawing context
24049c04938SLisandro Dalcin 
24149c04938SLisandro Dalcin    Level: advanced
24249c04938SLisandro Dalcin 
24395452b02SPatrick Sanan    Notes:
244*811af0c4SBarry Smith    This is not normally called by the user.
245*811af0c4SBarry Smith 
24649c04938SLisandro Dalcin    The ffmpeg utility must be in your path to make the movie.
24749c04938SLisandro Dalcin 
248*811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetSaveMovie()`
24949c04938SLisandro Dalcin @*/
2509371c9d4SSatish Balay PetscErrorCode PetscDrawSaveMovie(PetscDraw draw) {
25149c04938SLisandro Dalcin   PetscMPIInt rank;
25249c04938SLisandro Dalcin 
25349c04938SLisandro Dalcin   PetscFunctionBegin;
25449c04938SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
25549c04938SLisandro Dalcin   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(0);
25649c04938SLisandro Dalcin   if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) PetscFunctionReturn(0);
2579566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
25849c04938SLisandro Dalcin   {
25949c04938SLisandro Dalcin     const char *fname = draw->savefilename;
26049c04938SLisandro Dalcin     const char *imext = draw->saveimageext;
26149c04938SLisandro Dalcin     const char *mvext = draw->savemovieext;
2629566063dSJacob Faibussowitsch     if (rank == 0) PetscCall(PetscDrawMovieSave(fname, draw->savefilecount, imext, draw->savemoviefps, mvext));
2639566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw)));
26449c04938SLisandro Dalcin   }
26549c04938SLisandro Dalcin   PetscFunctionReturn(0);
26649c04938SLisandro Dalcin }
26749c04938SLisandro Dalcin 
2688067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
2698067a7d5SLisandro Dalcin #include <petscviewersaws.h>
2708067a7d5SLisandro Dalcin /*
2718067a7d5SLisandro Dalcin   The PetscImageList object and functions are used to maintain a list of file images
2728067a7d5SLisandro Dalcin   that can be displayed by the SAWs webserver.
2738067a7d5SLisandro Dalcin */
2748067a7d5SLisandro Dalcin typedef struct _P_PetscImageList *PetscImageList;
2758067a7d5SLisandro Dalcin struct _P_PetscImageList {
2768067a7d5SLisandro Dalcin   PetscImageList next;
2778067a7d5SLisandro Dalcin   char          *filename;
2788067a7d5SLisandro Dalcin   char          *ext;
2798067a7d5SLisandro Dalcin   PetscInt       count;
2808067a7d5SLisandro Dalcin };
2818067a7d5SLisandro Dalcin 
2828067a7d5SLisandro Dalcin static PetscImageList SAWs_images = NULL;
2838067a7d5SLisandro Dalcin 
2849371c9d4SSatish Balay static PetscErrorCode PetscImageListDestroy(void) {
2858067a7d5SLisandro Dalcin   PetscImageList image = SAWs_images;
2868067a7d5SLisandro Dalcin 
2878067a7d5SLisandro Dalcin   PetscFunctionBegin;
2888067a7d5SLisandro Dalcin   while (image) {
2898067a7d5SLisandro Dalcin     PetscImageList next = image->next;
2909566063dSJacob Faibussowitsch     PetscCall(PetscFree(image->filename));
2919566063dSJacob Faibussowitsch     PetscCall(PetscFree(image->ext));
2929566063dSJacob Faibussowitsch     PetscCall(PetscFree(image));
2938067a7d5SLisandro Dalcin     image = next;
2945b399a63SLisandro Dalcin   }
2955b399a63SLisandro Dalcin   PetscFunctionReturn(0);
2965b399a63SLisandro Dalcin }
2978067a7d5SLisandro Dalcin 
2989371c9d4SSatish Balay static PetscErrorCode PetscImageListAdd(const char filename[], const char ext[], PetscInt count) {
2998067a7d5SLisandro Dalcin   PetscImageList image, oimage = SAWs_images;
3008067a7d5SLisandro Dalcin   PetscBool      flg;
3018067a7d5SLisandro Dalcin 
3028067a7d5SLisandro Dalcin   PetscFunctionBegin;
3038067a7d5SLisandro Dalcin   if (oimage) {
3049566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(filename, oimage->filename, &flg));
3058067a7d5SLisandro Dalcin     if (flg) {
3068067a7d5SLisandro Dalcin       oimage->count = count;
3078067a7d5SLisandro Dalcin       PetscFunctionReturn(0);
3088067a7d5SLisandro Dalcin     }
3098067a7d5SLisandro Dalcin     while (oimage->next) {
3108067a7d5SLisandro Dalcin       oimage = oimage->next;
3119566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(filename, oimage->filename, &flg));
3128067a7d5SLisandro Dalcin       if (flg) {
3138067a7d5SLisandro Dalcin         oimage->count = count;
3148067a7d5SLisandro Dalcin         PetscFunctionReturn(0);
3158067a7d5SLisandro Dalcin       }
3168067a7d5SLisandro Dalcin     }
3179566063dSJacob Faibussowitsch     PetscCall(PetscNew(&image));
3188067a7d5SLisandro Dalcin     oimage->next = image;
3198067a7d5SLisandro Dalcin   } else {
3209566063dSJacob Faibussowitsch     PetscCall(PetscRegisterFinalize(PetscImageListDestroy));
3219566063dSJacob Faibussowitsch     PetscCall(PetscNew(&image));
3228067a7d5SLisandro Dalcin     SAWs_images = image;
3238067a7d5SLisandro Dalcin   }
3249566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(filename, &image->filename));
3259566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ext, &image->ext));
3268067a7d5SLisandro Dalcin   image->count = count;
3278067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
3288067a7d5SLisandro Dalcin }
3298067a7d5SLisandro Dalcin 
3309371c9d4SSatish Balay static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw) {
3318067a7d5SLisandro Dalcin   PetscImageList image;
3328067a7d5SLisandro Dalcin   char           body[4096];
3338067a7d5SLisandro Dalcin   size_t         len = 0;
3348067a7d5SLisandro Dalcin 
3358067a7d5SLisandro Dalcin   PetscFunctionBegin;
33649c04938SLisandro Dalcin   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(0);
3379566063dSJacob Faibussowitsch   PetscCall(PetscImageListAdd(draw->savefilename, draw->saveimageext, draw->savefilecount - 1));
3388067a7d5SLisandro Dalcin   image = SAWs_images;
3398067a7d5SLisandro Dalcin   while (image) {
3408067a7d5SLisandro Dalcin     const char *name = image->filename;
3418067a7d5SLisandro Dalcin     const char *ext  = image->ext;
3428067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
3439566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s%s\" alt=\"None\">", name, ext));
3448067a7d5SLisandro Dalcin     } else {
3459566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s/%s_%d%s\" alt=\"None\">", name, name, image->count, ext));
3468067a7d5SLisandro Dalcin     }
3479566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(body, &len));
3488067a7d5SLisandro Dalcin     image = image->next;
3498067a7d5SLisandro Dalcin   }
3509566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(body, "<br>\n", sizeof(body)));
351792fecdfSBarry Smith   if (draw->savefilecount > 0) PetscCallSAWs(SAWs_Pop_Body, ("index.html", 1));
352792fecdfSBarry Smith   PetscCallSAWs(SAWs_Push_Body, ("index.html", 1, body));
3538067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
3548067a7d5SLisandro Dalcin }
3558067a7d5SLisandro Dalcin 
3568067a7d5SLisandro Dalcin #endif
357