xref: /petsc/src/sys/classes/draw/interface/dsave.c (revision bbcf679c7ce315810b13005931dd3a7fb75b5053)
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
13811af0c4SBarry Smith    PetscDrawSetSave - Saves images produced in a `PetscDraw` into a file
145b399a63SLisandro Dalcin 
15c3339decSBarry Smith    Collective
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 
213c7db156SBarry Smith    Options Database Keys:
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 
28811af0c4SBarry Smith    Note:
29811af0c4SBarry 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 
36811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawOpenX()`, `PetscDrawOpenImage()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`, `PetscDrawSetSaveFinalImage()`
375b399a63SLisandro Dalcin @*/
38d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawSetSave(PetscDraw draw, const char filename[])
39d71ae5a4SJacob Faibussowitsch {
408067a7d5SLisandro Dalcin   const char *savename = NULL;
418067a7d5SLisandro Dalcin   const char *imageext = NULL;
4271ed57bfSLisandro Dalcin   char        buf[PETSC_MAX_PATH_LEN];
435b399a63SLisandro Dalcin 
445b399a63SLisandro Dalcin   PetscFunctionBegin;
455b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
4671ed57bfSLisandro Dalcin   if (filename) PetscValidCharPointer(filename, 2);
475b399a63SLisandro Dalcin 
488067a7d5SLisandro Dalcin   /* determine save filename and image extension */
495b399a63SLisandro Dalcin   if (filename && filename[0]) {
509566063dSJacob Faibussowitsch     PetscCall(PetscStrchr(filename, '.', (char **)&imageext));
518067a7d5SLisandro Dalcin     if (!imageext) savename = filename;
528067a7d5SLisandro Dalcin     else if (imageext != filename) {
5371ed57bfSLisandro Dalcin       size_t l1 = 0, l2 = 0;
549566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(filename, &l1));
559566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(imageext, &l2));
569566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(buf, filename, l1 - l2 + 1));
578067a7d5SLisandro Dalcin       savename = buf;
585b399a63SLisandro Dalcin     }
5971ed57bfSLisandro Dalcin   }
6071ed57bfSLisandro Dalcin 
619566063dSJacob Faibussowitsch   if (!savename) PetscCall(PetscObjectGetName((PetscObject)draw, &savename));
629566063dSJacob Faibussowitsch   PetscCall(PetscDrawImageCheckFormat(&imageext));
638067a7d5SLisandro Dalcin 
648067a7d5SLisandro Dalcin   draw->savefilecount = 0;
659566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->savefilename));
669566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->saveimageext));
679566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(savename, &draw->savefilename));
689566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(imageext, &draw->saveimageext));
6949c04938SLisandro Dalcin 
7049c04938SLisandro Dalcin   if (draw->savesinglefile) {
719566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Will save image to file %s%s\n", draw->savefilename, draw->saveimageext));
7249c04938SLisandro Dalcin   } else {
739566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Will save images to file %s/%s_%%d%s\n", draw->savefilename, draw->savefilename, draw->saveimageext));
7449c04938SLisandro Dalcin   }
753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7649c04938SLisandro Dalcin }
7749c04938SLisandro Dalcin 
7849c04938SLisandro Dalcin /*@C
79811af0c4SBarry Smith    PetscDrawSetSaveMovie - Saves a movie produced from a `PetscDraw` into a file
8049c04938SLisandro Dalcin 
81c3339decSBarry Smith    Collective
8249c04938SLisandro Dalcin 
83d8d19677SJose E. Roman    Input Parameters:
8449c04938SLisandro Dalcin +  draw      - the graphics context
8549c04938SLisandro Dalcin -  movieext  - optional extension defining the movie format
8649c04938SLisandro Dalcin 
873c7db156SBarry Smith    Options Database Key:
8849c04938SLisandro Dalcin .  -draw_save_movie <.ext> - saves a movie with extension .ext
8949c04938SLisandro Dalcin 
9049c04938SLisandro Dalcin    Level: intermediate
9149c04938SLisandro Dalcin 
92811af0c4SBarry Smith    Note:
93811af0c4SBarry Smith     You should call this AFTER calling `PetscDrawSetSave()` and BEFORE creating your image with `PetscDrawSave()`.
9449c04938SLisandro Dalcin    The ffmpeg utility must be in your path to make the movie.
9549c04938SLisandro Dalcin 
96811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
9749c04938SLisandro Dalcin @*/
98d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawSetSaveMovie(PetscDraw draw, const char movieext[])
99d71ae5a4SJacob Faibussowitsch {
10049c04938SLisandro Dalcin   PetscFunctionBegin;
10149c04938SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
10249c04938SLisandro Dalcin   if (movieext) PetscValidCharPointer(movieext, 2);
10349c04938SLisandro Dalcin 
1049566063dSJacob Faibussowitsch   if (!draw->savefilename) PetscCall(PetscDrawSetSave(draw, ""));
1059566063dSJacob Faibussowitsch   PetscCall(PetscDrawMovieCheckFormat(&movieext));
1069566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(movieext, &draw->savemovieext));
10749c04938SLisandro Dalcin   draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */
10849c04938SLisandro Dalcin 
1099566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Will save movie to file %s%s\n", draw->savefilename, draw->savemovieext));
1103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1115b399a63SLisandro Dalcin }
1125b399a63SLisandro Dalcin 
1135b399a63SLisandro Dalcin /*@C
114811af0c4SBarry Smith    PetscDrawSetSaveFinalImage - Saves the final image produced in a `PetscDraw` into a file
1155b399a63SLisandro Dalcin 
116c3339decSBarry Smith    Collective
1175b399a63SLisandro Dalcin 
118d8d19677SJose E. Roman    Input Parameters:
1195b399a63SLisandro Dalcin +  draw      - the graphics context
120811af0c4SBarry Smith -  filename  - name of the file, if NULL or empty uses name set with `PetscDrawSetSave()` or the name of the draw object
1215b399a63SLisandro Dalcin 
1223c7db156SBarry Smith    Options Database Key:
1238067a7d5SLisandro 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)
1245b399a63SLisandro Dalcin 
1255b399a63SLisandro Dalcin    Level: intermediate
1265b399a63SLisandro Dalcin 
12795452b02SPatrick Sanan    Notes:
128811af0c4SBarry Smith     You should call this BEFORE creating your image and calling `PetscDrawSave()`.
129811af0c4SBarry Smith 
1308067a7d5SLisandro Dalcin    The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
131811af0c4SBarry Smith .vb
1328067a7d5SLisandro Dalcin    Support for .png images requires configure --with-libpng.
1338067a7d5SLisandro Dalcin    Support for .gif images requires configure --with-giflib.
1348067a7d5SLisandro Dalcin    Support for .jpg images requires configure --with-libjpeg.
1358067a7d5SLisandro Dalcin    Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
136811af0c4SBarry Smith .ve
1375b399a63SLisandro Dalcin 
138811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
1395b399a63SLisandro Dalcin @*/
140d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw, const char filename[])
141d71ae5a4SJacob Faibussowitsch {
1428067a7d5SLisandro Dalcin   char buf[PETSC_MAX_PATH_LEN];
1435b399a63SLisandro Dalcin 
1445b399a63SLisandro Dalcin   PetscFunctionBegin;
1455b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
1468067a7d5SLisandro Dalcin   if (!filename || !filename[0]) {
1478067a7d5SLisandro Dalcin     if (!draw->savefilename) {
1489566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)draw, &filename));
1495b399a63SLisandro Dalcin     } else {
1509566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, sizeof(buf), "%s%s", draw->savefilename, draw->saveimageext));
1518067a7d5SLisandro Dalcin       filename = buf;
1525b399a63SLisandro Dalcin     }
1538067a7d5SLisandro Dalcin   }
1549566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->savefinalfilename));
1559566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(filename, &draw->savefinalfilename));
1563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1575b399a63SLisandro Dalcin }
1585b399a63SLisandro Dalcin 
1595b399a63SLisandro Dalcin /*@
1605b399a63SLisandro Dalcin    PetscDrawSave - Saves a drawn image
1615b399a63SLisandro Dalcin 
162c3339decSBarry Smith    Collective
1635b399a63SLisandro Dalcin 
1645b399a63SLisandro Dalcin    Input Parameters:
1655b399a63SLisandro Dalcin .  draw - the drawing context
1665b399a63SLisandro Dalcin 
1675b399a63SLisandro Dalcin    Level: advanced
1685b399a63SLisandro Dalcin 
169811af0c4SBarry Smith    Note:
17095452b02SPatrick Sanan     this is not normally called by the user.
1715b399a63SLisandro Dalcin 
172811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`
1735b399a63SLisandro Dalcin @*/
174d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawSave(PetscDraw draw)
175d71ae5a4SJacob Faibussowitsch {
17649c04938SLisandro Dalcin   PetscInt       saveindex;
1778067a7d5SLisandro Dalcin   char           basename[PETSC_MAX_PATH_LEN];
1788067a7d5SLisandro Dalcin   unsigned char  palette[256][3];
1798067a7d5SLisandro Dalcin   unsigned int   w, h;
1808067a7d5SLisandro Dalcin   unsigned char *pixels = NULL;
1818067a7d5SLisandro Dalcin   PetscMPIInt    rank;
1825b399a63SLisandro Dalcin 
1835b399a63SLisandro Dalcin   PetscFunctionBegin;
1845b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
1853ba16761SJacob Faibussowitsch   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(PETSC_SUCCESS);
1869371c9d4SSatish Balay   if (draw->ops->save) {
1879371c9d4SSatish Balay     PetscUseTypeMethod(draw, save);
1889371c9d4SSatish Balay     goto finally;
1899371c9d4SSatish Balay   }
1903ba16761SJacob Faibussowitsch   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(PETSC_SUCCESS);
1919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
1928067a7d5SLisandro Dalcin 
19349c04938SLisandro Dalcin   saveindex = draw->savefilecount++;
1948067a7d5SLisandro Dalcin 
195dd400576SPatrick Sanan   if (rank == 0 && !saveindex) {
1968067a7d5SLisandro Dalcin     char path[PETSC_MAX_PATH_LEN];
1978067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
1989566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->saveimageext));
1998067a7d5SLisandro Dalcin       (void)remove(path);
2008067a7d5SLisandro Dalcin     } else {
2019566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s", draw->savefilename));
2029566063dSJacob Faibussowitsch       PetscCall(PetscRMTree(path));
2039566063dSJacob Faibussowitsch       PetscCall(PetscMkdir(path));
2048067a7d5SLisandro Dalcin     }
2058067a7d5SLisandro Dalcin     if (draw->savemovieext) {
2069566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->savemovieext));
2078067a7d5SLisandro Dalcin       (void)remove(path);
2088067a7d5SLisandro Dalcin     }
2098067a7d5SLisandro Dalcin   }
2108067a7d5SLisandro Dalcin   if (draw->savesinglefile) {
2119566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s", draw->savefilename));
2128067a7d5SLisandro Dalcin   } else {
213*bbcf679cSJacob Faibussowitsch     char *basefilename = NULL;
21480603804SMatthew G. Knepley 
215*bbcf679cSJacob Faibussowitsch     PetscCall(PetscStrrchr(draw->savefilename, '/', &basefilename));
21680603804SMatthew G. Knepley     if (basefilename != draw->savefilename) {
2179566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s_%d", draw->savefilename, (int)saveindex));
21880603804SMatthew G. Knepley     } else {
2199566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s/%s_%d", draw->savefilename, draw->savefilename, (int)saveindex));
2208067a7d5SLisandro Dalcin     }
22180603804SMatthew G. Knepley   }
2228067a7d5SLisandro Dalcin 
2238067a7d5SLisandro Dalcin   /* this call is collective, only the first process gets the image data */
224dbbe0bcdSBarry Smith   PetscUseTypeMethod(draw, getimage, palette, &w, &h, &pixels);
2258067a7d5SLisandro Dalcin   /* only the first process handles the saving business */
2269566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscDrawImageSave(basename, draw->saveimageext, palette, w, h, pixels));
2279566063dSJacob Faibussowitsch   PetscCall(PetscFree(pixels));
2289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw)));
2298067a7d5SLisandro Dalcin 
2308067a7d5SLisandro Dalcin finally:
2318067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
2329566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave_SAWs(draw));
2338067a7d5SLisandro Dalcin #endif
2343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2358067a7d5SLisandro Dalcin }
2368067a7d5SLisandro Dalcin 
23749c04938SLisandro Dalcin /*@
23849c04938SLisandro Dalcin    PetscDrawSaveMovie - Saves a movie from previously saved images
23949c04938SLisandro Dalcin 
240c3339decSBarry Smith    Collective
24149c04938SLisandro Dalcin 
24249c04938SLisandro Dalcin    Input Parameters:
24349c04938SLisandro Dalcin .  draw - the drawing context
24449c04938SLisandro Dalcin 
24549c04938SLisandro Dalcin    Level: advanced
24649c04938SLisandro Dalcin 
24795452b02SPatrick Sanan    Notes:
248811af0c4SBarry Smith    This is not normally called by the user.
249811af0c4SBarry Smith 
25049c04938SLisandro Dalcin    The ffmpeg utility must be in your path to make the movie.
25149c04938SLisandro Dalcin 
252811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetSaveMovie()`
25349c04938SLisandro Dalcin @*/
254d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
255d71ae5a4SJacob Faibussowitsch {
25649c04938SLisandro Dalcin   PetscMPIInt rank;
25749c04938SLisandro Dalcin 
25849c04938SLisandro Dalcin   PetscFunctionBegin;
25949c04938SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
2603ba16761SJacob Faibussowitsch   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(PETSC_SUCCESS);
2613ba16761SJacob Faibussowitsch   if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) PetscFunctionReturn(PETSC_SUCCESS);
2629566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
26349c04938SLisandro Dalcin   {
26449c04938SLisandro Dalcin     const char *fname = draw->savefilename;
26549c04938SLisandro Dalcin     const char *imext = draw->saveimageext;
26649c04938SLisandro Dalcin     const char *mvext = draw->savemovieext;
2679566063dSJacob Faibussowitsch     if (rank == 0) PetscCall(PetscDrawMovieSave(fname, draw->savefilecount, imext, draw->savemoviefps, mvext));
2689566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw)));
26949c04938SLisandro Dalcin   }
2703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27149c04938SLisandro Dalcin }
27249c04938SLisandro Dalcin 
2738067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
2748067a7d5SLisandro Dalcin   #include <petscviewersaws.h>
2758067a7d5SLisandro Dalcin /*
2768067a7d5SLisandro Dalcin   The PetscImageList object and functions are used to maintain a list of file images
2778067a7d5SLisandro Dalcin   that can be displayed by the SAWs webserver.
2788067a7d5SLisandro Dalcin */
2798067a7d5SLisandro Dalcin typedef struct _P_PetscImageList *PetscImageList;
2808067a7d5SLisandro Dalcin struct _P_PetscImageList {
2818067a7d5SLisandro Dalcin   PetscImageList next;
2828067a7d5SLisandro Dalcin   char          *filename;
2838067a7d5SLisandro Dalcin   char          *ext;
2848067a7d5SLisandro Dalcin   PetscInt       count;
2858067a7d5SLisandro Dalcin };
2868067a7d5SLisandro Dalcin 
2878067a7d5SLisandro Dalcin static PetscImageList SAWs_images = NULL;
2888067a7d5SLisandro Dalcin 
289d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscImageListDestroy(void)
290d71ae5a4SJacob Faibussowitsch {
2918067a7d5SLisandro Dalcin   PetscImageList image = SAWs_images;
2928067a7d5SLisandro Dalcin 
2938067a7d5SLisandro Dalcin   PetscFunctionBegin;
2948067a7d5SLisandro Dalcin   while (image) {
2958067a7d5SLisandro Dalcin     PetscImageList next = image->next;
2969566063dSJacob Faibussowitsch     PetscCall(PetscFree(image->filename));
2979566063dSJacob Faibussowitsch     PetscCall(PetscFree(image->ext));
2989566063dSJacob Faibussowitsch     PetscCall(PetscFree(image));
2998067a7d5SLisandro Dalcin     image = next;
3005b399a63SLisandro Dalcin   }
3013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3025b399a63SLisandro Dalcin }
3038067a7d5SLisandro Dalcin 
304d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscImageListAdd(const char filename[], const char ext[], PetscInt count)
305d71ae5a4SJacob Faibussowitsch {
3068067a7d5SLisandro Dalcin   PetscImageList image, oimage = SAWs_images;
3078067a7d5SLisandro Dalcin   PetscBool      flg;
3088067a7d5SLisandro Dalcin 
3098067a7d5SLisandro Dalcin   PetscFunctionBegin;
3108067a7d5SLisandro Dalcin   if (oimage) {
3119566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(filename, oimage->filename, &flg));
3128067a7d5SLisandro Dalcin     if (flg) {
3138067a7d5SLisandro Dalcin       oimage->count = count;
3143ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
3158067a7d5SLisandro Dalcin     }
3168067a7d5SLisandro Dalcin     while (oimage->next) {
3178067a7d5SLisandro Dalcin       oimage = oimage->next;
3189566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(filename, oimage->filename, &flg));
3198067a7d5SLisandro Dalcin       if (flg) {
3208067a7d5SLisandro Dalcin         oimage->count = count;
3213ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
3228067a7d5SLisandro Dalcin       }
3238067a7d5SLisandro Dalcin     }
3249566063dSJacob Faibussowitsch     PetscCall(PetscNew(&image));
3258067a7d5SLisandro Dalcin     oimage->next = image;
3268067a7d5SLisandro Dalcin   } else {
3279566063dSJacob Faibussowitsch     PetscCall(PetscRegisterFinalize(PetscImageListDestroy));
3289566063dSJacob Faibussowitsch     PetscCall(PetscNew(&image));
3298067a7d5SLisandro Dalcin     SAWs_images = image;
3308067a7d5SLisandro Dalcin   }
3319566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(filename, &image->filename));
3329566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ext, &image->ext));
3338067a7d5SLisandro Dalcin   image->count = count;
3343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3358067a7d5SLisandro Dalcin }
3368067a7d5SLisandro Dalcin 
337d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
338d71ae5a4SJacob Faibussowitsch {
3398067a7d5SLisandro Dalcin   PetscImageList image;
3408067a7d5SLisandro Dalcin   char           body[4096];
3418067a7d5SLisandro Dalcin   size_t         len = 0;
3428067a7d5SLisandro Dalcin 
3438067a7d5SLisandro Dalcin   PetscFunctionBegin;
3443ba16761SJacob Faibussowitsch   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(PETSC_SUCCESS);
3459566063dSJacob Faibussowitsch   PetscCall(PetscImageListAdd(draw->savefilename, draw->saveimageext, draw->savefilecount - 1));
3468067a7d5SLisandro Dalcin   image = SAWs_images;
3478067a7d5SLisandro Dalcin   while (image) {
3488067a7d5SLisandro Dalcin     const char *name = image->filename;
3498067a7d5SLisandro Dalcin     const char *ext  = image->ext;
3508067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
3519566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s%s\" alt=\"None\">", name, ext));
3528067a7d5SLisandro Dalcin     } else {
3539566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s/%s_%d%s\" alt=\"None\">", name, name, image->count, ext));
3548067a7d5SLisandro Dalcin     }
3559566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(body, &len));
3568067a7d5SLisandro Dalcin     image = image->next;
3578067a7d5SLisandro Dalcin   }
3589566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(body, "<br>\n", sizeof(body)));
359792fecdfSBarry Smith   if (draw->savefilecount > 0) PetscCallSAWs(SAWs_Pop_Body, ("index.html", 1));
360792fecdfSBarry Smith   PetscCallSAWs(SAWs_Push_Body, ("index.html", 1, body));
3613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3628067a7d5SLisandro Dalcin }
3638067a7d5SLisandro Dalcin 
3648067a7d5SLisandro Dalcin #endif
365