xref: /petsc/src/sys/classes/draw/interface/dsave.c (revision be37439ebbbdb2f81c3420c175a94aa72e59929c)
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 
12cc4c1da9SBarry Smith /*@
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 @*/
PetscDrawSetSave(PetscDraw draw,const char filename[])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);
464f572ea9SToby Isaac   if (filename) PetscAssertPointer(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));
569b15cf9aSJacob Faibussowitsch       PetscCall(PetscStrncpy(buf, filename, sizeof(buf)));
579b15cf9aSJacob Faibussowitsch       buf[l1 - l2 + 1] = '\0';
588067a7d5SLisandro Dalcin       savename         = buf;
595b399a63SLisandro Dalcin     }
6071ed57bfSLisandro Dalcin   }
6171ed57bfSLisandro Dalcin 
629566063dSJacob Faibussowitsch   if (!savename) PetscCall(PetscObjectGetName((PetscObject)draw, &savename));
639566063dSJacob Faibussowitsch   PetscCall(PetscDrawImageCheckFormat(&imageext));
648067a7d5SLisandro Dalcin 
658067a7d5SLisandro Dalcin   draw->savefilecount = 0;
669566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->savefilename));
679566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->saveimageext));
689566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(savename, &draw->savefilename));
699566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(imageext, &draw->saveimageext));
7049c04938SLisandro Dalcin 
7149c04938SLisandro Dalcin   if (draw->savesinglefile) {
729566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Will save image to file %s%s\n", draw->savefilename, draw->saveimageext));
7349c04938SLisandro Dalcin   } else {
749566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Will save images to file %s/%s_%%d%s\n", draw->savefilename, draw->savefilename, draw->saveimageext));
7549c04938SLisandro Dalcin   }
763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7749c04938SLisandro Dalcin }
7849c04938SLisandro Dalcin 
79cc4c1da9SBarry Smith /*@
80811af0c4SBarry Smith   PetscDrawSetSaveMovie - Saves a movie produced from a `PetscDraw` into a file
8149c04938SLisandro Dalcin 
82c3339decSBarry Smith   Collective
8349c04938SLisandro Dalcin 
84d8d19677SJose E. Roman   Input Parameters:
8549c04938SLisandro Dalcin + draw     - the graphics context
8649c04938SLisandro Dalcin - movieext - optional extension defining the movie format
8749c04938SLisandro Dalcin 
883c7db156SBarry Smith   Options Database Key:
8949c04938SLisandro Dalcin . -draw_save_movie <.ext> - saves a movie with extension .ext
9049c04938SLisandro Dalcin 
9149c04938SLisandro Dalcin   Level: intermediate
9249c04938SLisandro Dalcin 
93811af0c4SBarry Smith   Note:
94811af0c4SBarry Smith   You should call this AFTER calling `PetscDrawSetSave()` and BEFORE creating your image with `PetscDrawSave()`.
9549c04938SLisandro Dalcin   The ffmpeg utility must be in your path to make the movie.
9649c04938SLisandro Dalcin 
97811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
9849c04938SLisandro Dalcin @*/
PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])99d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawSetSaveMovie(PetscDraw draw, const char movieext[])
100d71ae5a4SJacob Faibussowitsch {
10149c04938SLisandro Dalcin   PetscFunctionBegin;
10249c04938SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
1034f572ea9SToby Isaac   if (movieext) PetscAssertPointer(movieext, 2);
10449c04938SLisandro Dalcin 
1059566063dSJacob Faibussowitsch   if (!draw->savefilename) PetscCall(PetscDrawSetSave(draw, ""));
1069566063dSJacob Faibussowitsch   PetscCall(PetscDrawMovieCheckFormat(&movieext));
1079566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(movieext, &draw->savemovieext));
108aaa8cc7dSPierre Jolivet   draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generate movies */
10949c04938SLisandro Dalcin 
1109566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Will save movie to file %s%s\n", draw->savefilename, draw->savemovieext));
1113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1125b399a63SLisandro Dalcin }
1135b399a63SLisandro Dalcin 
114cc4c1da9SBarry Smith /*@
115811af0c4SBarry Smith   PetscDrawSetSaveFinalImage - Saves the final image produced in a `PetscDraw` into a file
1165b399a63SLisandro Dalcin 
117c3339decSBarry Smith   Collective
1185b399a63SLisandro Dalcin 
119d8d19677SJose E. Roman   Input Parameters:
1205b399a63SLisandro Dalcin + draw     - the graphics context
121811af0c4SBarry Smith - filename - name of the file, if NULL or empty uses name set with `PetscDrawSetSave()` or the name of the draw object
1225b399a63SLisandro Dalcin 
1233c7db156SBarry Smith   Options Database Key:
1248067a7d5SLisandro 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)
1255b399a63SLisandro Dalcin 
1265b399a63SLisandro Dalcin   Level: intermediate
1275b399a63SLisandro Dalcin 
12895452b02SPatrick Sanan   Notes:
129811af0c4SBarry Smith   You should call this BEFORE creating your image and calling `PetscDrawSave()`.
130811af0c4SBarry Smith 
1318067a7d5SLisandro Dalcin   The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
132811af0c4SBarry Smith .vb
1338067a7d5SLisandro Dalcin    Support for .png images requires configure --with-libpng.
1348067a7d5SLisandro Dalcin    Support for .gif images requires configure --with-giflib.
1358067a7d5SLisandro Dalcin    Support for .jpg images requires configure --with-libjpeg.
1368067a7d5SLisandro Dalcin    Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
137811af0c4SBarry Smith .ve
1385b399a63SLisandro Dalcin 
139811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
1405b399a63SLisandro Dalcin @*/
PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])141d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw, const char filename[])
142d71ae5a4SJacob Faibussowitsch {
1438067a7d5SLisandro Dalcin   char buf[PETSC_MAX_PATH_LEN];
1445b399a63SLisandro Dalcin 
1455b399a63SLisandro Dalcin   PetscFunctionBegin;
1465b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
1478067a7d5SLisandro Dalcin   if (!filename || !filename[0]) {
1488067a7d5SLisandro Dalcin     if (!draw->savefilename) {
1499566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)draw, &filename));
1505b399a63SLisandro Dalcin     } else {
1519566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, sizeof(buf), "%s%s", draw->savefilename, draw->saveimageext));
1528067a7d5SLisandro Dalcin       filename = buf;
1535b399a63SLisandro Dalcin     }
1548067a7d5SLisandro Dalcin   }
1559566063dSJacob Faibussowitsch   PetscCall(PetscFree(draw->savefinalfilename));
1569566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(filename, &draw->savefinalfilename));
1573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1585b399a63SLisandro Dalcin }
1595b399a63SLisandro Dalcin 
1605b399a63SLisandro Dalcin /*@
1615b399a63SLisandro Dalcin   PetscDrawSave - Saves a drawn image
1625b399a63SLisandro Dalcin 
163c3339decSBarry Smith   Collective
1645b399a63SLisandro Dalcin 
1652fe279fdSBarry Smith   Input Parameter:
1665b399a63SLisandro Dalcin . draw - the drawing context
1675b399a63SLisandro Dalcin 
1685b399a63SLisandro Dalcin   Level: advanced
1695b399a63SLisandro Dalcin 
170811af0c4SBarry Smith   Note:
17195452b02SPatrick Sanan   this is not normally called by the user.
1725b399a63SLisandro Dalcin 
173811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`
1745b399a63SLisandro Dalcin @*/
PetscDrawSave(PetscDraw draw)175d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawSave(PetscDraw draw)
176d71ae5a4SJacob Faibussowitsch {
17749c04938SLisandro Dalcin   PetscInt       saveindex;
1788067a7d5SLisandro Dalcin   char           basename[PETSC_MAX_PATH_LEN];
1798067a7d5SLisandro Dalcin   unsigned char  palette[256][3];
1808067a7d5SLisandro Dalcin   unsigned int   w, h;
1818067a7d5SLisandro Dalcin   unsigned char *pixels = NULL;
1828067a7d5SLisandro Dalcin   PetscMPIInt    rank;
1835b399a63SLisandro Dalcin 
1845b399a63SLisandro Dalcin   PetscFunctionBegin;
1855b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
1863ba16761SJacob Faibussowitsch   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(PETSC_SUCCESS);
1879371c9d4SSatish Balay   if (draw->ops->save) {
1889371c9d4SSatish Balay     PetscUseTypeMethod(draw, save);
1899371c9d4SSatish Balay     goto finally;
1909371c9d4SSatish Balay   }
1913ba16761SJacob Faibussowitsch   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(PETSC_SUCCESS);
1929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
1938067a7d5SLisandro Dalcin 
19449c04938SLisandro Dalcin   saveindex = draw->savefilecount++;
1958067a7d5SLisandro Dalcin 
196dd400576SPatrick Sanan   if (rank == 0 && !saveindex) {
1978067a7d5SLisandro Dalcin     char path[PETSC_MAX_PATH_LEN];
1988067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
1999566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->saveimageext));
2008067a7d5SLisandro Dalcin       (void)remove(path);
2018067a7d5SLisandro Dalcin     } else {
2029566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s", draw->savefilename));
2039566063dSJacob Faibussowitsch       PetscCall(PetscRMTree(path));
2049566063dSJacob Faibussowitsch       PetscCall(PetscMkdir(path));
2058067a7d5SLisandro Dalcin     }
2068067a7d5SLisandro Dalcin     if (draw->savemovieext) {
2079566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->savemovieext));
2088067a7d5SLisandro Dalcin       (void)remove(path);
2098067a7d5SLisandro Dalcin     }
2108067a7d5SLisandro Dalcin   }
2118067a7d5SLisandro Dalcin   if (draw->savesinglefile) {
2129566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s", draw->savefilename));
2138067a7d5SLisandro Dalcin   } else {
214bbcf679cSJacob Faibussowitsch     char *basefilename = NULL;
21580603804SMatthew G. Knepley 
216bbcf679cSJacob Faibussowitsch     PetscCall(PetscStrrchr(draw->savefilename, '/', &basefilename));
21780603804SMatthew G. Knepley     if (basefilename != draw->savefilename) {
218*835f2295SStefano Zampini       PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s_%" PetscInt_FMT, draw->savefilename, saveindex));
21980603804SMatthew G. Knepley     } else {
220*835f2295SStefano Zampini       PetscCall(PetscSNPrintf(basename, sizeof(basename), "%s/%s_%" PetscInt_FMT, draw->savefilename, draw->savefilename, saveindex));
2218067a7d5SLisandro Dalcin     }
22280603804SMatthew G. Knepley   }
2238067a7d5SLisandro Dalcin 
2248067a7d5SLisandro Dalcin   /* this call is collective, only the first process gets the image data */
225dbbe0bcdSBarry Smith   PetscUseTypeMethod(draw, getimage, palette, &w, &h, &pixels);
2268067a7d5SLisandro Dalcin   /* only the first process handles the saving business */
2279566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscDrawImageSave(basename, draw->saveimageext, palette, w, h, pixels));
2289566063dSJacob Faibussowitsch   PetscCall(PetscFree(pixels));
2299566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw)));
2308067a7d5SLisandro Dalcin 
2318067a7d5SLisandro Dalcin finally:
2328067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
2339566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave_SAWs(draw));
2348067a7d5SLisandro Dalcin #endif
2353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2368067a7d5SLisandro Dalcin }
2378067a7d5SLisandro Dalcin 
23849c04938SLisandro Dalcin /*@
23949c04938SLisandro Dalcin   PetscDrawSaveMovie - Saves a movie from previously saved images
24049c04938SLisandro Dalcin 
241c3339decSBarry Smith   Collective
24249c04938SLisandro Dalcin 
2432fe279fdSBarry Smith   Input Parameter:
24449c04938SLisandro Dalcin . draw - the drawing context
24549c04938SLisandro Dalcin 
24649c04938SLisandro Dalcin   Level: advanced
24749c04938SLisandro Dalcin 
24895452b02SPatrick Sanan   Notes:
249811af0c4SBarry Smith   This is not normally called by the user.
250811af0c4SBarry Smith 
25149c04938SLisandro Dalcin   The ffmpeg utility must be in your path to make the movie.
25249c04938SLisandro Dalcin 
253811af0c4SBarry Smith .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetSaveMovie()`
25449c04938SLisandro Dalcin @*/
PetscDrawSaveMovie(PetscDraw draw)255d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
256d71ae5a4SJacob Faibussowitsch {
25749c04938SLisandro Dalcin   PetscMPIInt rank;
25849c04938SLisandro Dalcin 
25949c04938SLisandro Dalcin   PetscFunctionBegin;
26049c04938SLisandro Dalcin   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
2613ba16761SJacob Faibussowitsch   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(PETSC_SUCCESS);
2623ba16761SJacob Faibussowitsch   if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) PetscFunctionReturn(PETSC_SUCCESS);
2639566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
26449c04938SLisandro Dalcin   {
26549c04938SLisandro Dalcin     const char *fname = draw->savefilename;
26649c04938SLisandro Dalcin     const char *imext = draw->saveimageext;
26749c04938SLisandro Dalcin     const char *mvext = draw->savemovieext;
2689566063dSJacob Faibussowitsch     if (rank == 0) PetscCall(PetscDrawMovieSave(fname, draw->savefilecount, imext, draw->savemoviefps, mvext));
2699566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw)));
27049c04938SLisandro Dalcin   }
2713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27249c04938SLisandro Dalcin }
27349c04938SLisandro Dalcin 
2748067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
2758067a7d5SLisandro Dalcin   #include <petscviewersaws.h>
2768067a7d5SLisandro Dalcin /*
2778067a7d5SLisandro Dalcin   The PetscImageList object and functions are used to maintain a list of file images
2788067a7d5SLisandro Dalcin   that can be displayed by the SAWs webserver.
2798067a7d5SLisandro Dalcin */
2808067a7d5SLisandro Dalcin typedef struct _P_PetscImageList *PetscImageList;
2818067a7d5SLisandro Dalcin struct _P_PetscImageList {
2828067a7d5SLisandro Dalcin   PetscImageList next;
2838067a7d5SLisandro Dalcin   char          *filename;
2848067a7d5SLisandro Dalcin   char          *ext;
2858067a7d5SLisandro Dalcin   PetscInt       count;
2868067a7d5SLisandro Dalcin };
2878067a7d5SLisandro Dalcin 
2888067a7d5SLisandro Dalcin static PetscImageList SAWs_images = NULL;
2898067a7d5SLisandro Dalcin 
PetscImageListDestroy(void)290d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscImageListDestroy(void)
291d71ae5a4SJacob Faibussowitsch {
2928067a7d5SLisandro Dalcin   PetscImageList image = SAWs_images;
2938067a7d5SLisandro Dalcin 
2948067a7d5SLisandro Dalcin   PetscFunctionBegin;
2958067a7d5SLisandro Dalcin   while (image) {
2968067a7d5SLisandro Dalcin     PetscImageList next = image->next;
2979566063dSJacob Faibussowitsch     PetscCall(PetscFree(image->filename));
2989566063dSJacob Faibussowitsch     PetscCall(PetscFree(image->ext));
2999566063dSJacob Faibussowitsch     PetscCall(PetscFree(image));
3008067a7d5SLisandro Dalcin     image = next;
3015b399a63SLisandro Dalcin   }
3023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3035b399a63SLisandro Dalcin }
3048067a7d5SLisandro Dalcin 
PetscImageListAdd(const char filename[],const char ext[],PetscInt count)305d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscImageListAdd(const char filename[], const char ext[], PetscInt count)
306d71ae5a4SJacob Faibussowitsch {
3078067a7d5SLisandro Dalcin   PetscImageList image, oimage = SAWs_images;
3088067a7d5SLisandro Dalcin   PetscBool      flg;
3098067a7d5SLisandro Dalcin 
3108067a7d5SLisandro Dalcin   PetscFunctionBegin;
3118067a7d5SLisandro Dalcin   if (oimage) {
3129566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(filename, oimage->filename, &flg));
3138067a7d5SLisandro Dalcin     if (flg) {
3148067a7d5SLisandro Dalcin       oimage->count = count;
3153ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
3168067a7d5SLisandro Dalcin     }
3178067a7d5SLisandro Dalcin     while (oimage->next) {
3188067a7d5SLisandro Dalcin       oimage = oimage->next;
3199566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(filename, oimage->filename, &flg));
3208067a7d5SLisandro Dalcin       if (flg) {
3218067a7d5SLisandro Dalcin         oimage->count = count;
3223ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
3238067a7d5SLisandro Dalcin       }
3248067a7d5SLisandro Dalcin     }
3259566063dSJacob Faibussowitsch     PetscCall(PetscNew(&image));
3268067a7d5SLisandro Dalcin     oimage->next = image;
3278067a7d5SLisandro Dalcin   } else {
3289566063dSJacob Faibussowitsch     PetscCall(PetscRegisterFinalize(PetscImageListDestroy));
3299566063dSJacob Faibussowitsch     PetscCall(PetscNew(&image));
3308067a7d5SLisandro Dalcin     SAWs_images = image;
3318067a7d5SLisandro Dalcin   }
3329566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(filename, &image->filename));
3339566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ext, &image->ext));
3348067a7d5SLisandro Dalcin   image->count = count;
3353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3368067a7d5SLisandro Dalcin }
3378067a7d5SLisandro Dalcin 
PetscDrawSave_SAWs(PetscDraw draw)338d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
339d71ae5a4SJacob Faibussowitsch {
3408067a7d5SLisandro Dalcin   PetscImageList image;
3418067a7d5SLisandro Dalcin   char           body[4096];
3428067a7d5SLisandro Dalcin   size_t         len = 0;
3438067a7d5SLisandro Dalcin 
3448067a7d5SLisandro Dalcin   PetscFunctionBegin;
3453ba16761SJacob Faibussowitsch   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(PETSC_SUCCESS);
3469566063dSJacob Faibussowitsch   PetscCall(PetscImageListAdd(draw->savefilename, draw->saveimageext, draw->savefilecount - 1));
3478067a7d5SLisandro Dalcin   image = SAWs_images;
3488067a7d5SLisandro Dalcin   while (image) {
3498067a7d5SLisandro Dalcin     const char *name = image->filename;
3508067a7d5SLisandro Dalcin     const char *ext  = image->ext;
3518067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
3529566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s%s\" alt=\"None\">", name, ext));
3538067a7d5SLisandro Dalcin     } else {
3549566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s/%s_%d%s\" alt=\"None\">", name, name, image->count, ext));
3558067a7d5SLisandro Dalcin     }
3569566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(body, &len));
3578067a7d5SLisandro Dalcin     image = image->next;
3588067a7d5SLisandro Dalcin   }
3599566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(body, "<br>\n", sizeof(body)));
360792fecdfSBarry Smith   if (draw->savefilecount > 0) PetscCallSAWs(SAWs_Pop_Body, ("index.html", 1));
361792fecdfSBarry Smith   PetscCallSAWs(SAWs_Push_Body, ("index.html", 1, body));
3623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3638067a7d5SLisandro Dalcin }
3648067a7d5SLisandro Dalcin 
3658067a7d5SLisandro Dalcin #endif
366