xref: /petsc/src/sys/classes/draw/interface/dsave.c (revision dbbe0bcd3f3a8fbab5a45420dc06f8387e5764c6)
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 @*/
3849c04938SLisandro Dalcin PetscErrorCode  PetscDrawSetSave(PetscDraw draw,const char filename[])
395b399a63SLisandro Dalcin {
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   }
7549c04938SLisandro Dalcin   PetscFunctionReturn(0);
7649c04938SLisandro Dalcin }
7749c04938SLisandro Dalcin 
7849c04938SLisandro Dalcin /*@C
7949c04938SLisandro Dalcin    PetscDrawSetSaveMovie - Saves a movie produced from a PetscDraw into a file
8049c04938SLisandro Dalcin 
8149c04938SLisandro Dalcin    Collective on PetscDraw
8249c04938SLisandro Dalcin 
83d8d19677SJose E. Roman    Input Parameters:
8449c04938SLisandro Dalcin +  draw      - the graphics context
8549c04938SLisandro Dalcin -  movieext  - optional extension defining the movie format
8649c04938SLisandro Dalcin 
8749c04938SLisandro Dalcin    Options Database Command:
8849c04938SLisandro Dalcin .  -draw_save_movie <.ext> - saves a movie with extension .ext
8949c04938SLisandro Dalcin 
9049c04938SLisandro Dalcin    Level: intermediate
9149c04938SLisandro Dalcin 
9295452b02SPatrick Sanan    Notes:
9395452b02SPatrick Sanan     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 
96db781477SPatrick Sanan .seealso: `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
9749c04938SLisandro Dalcin @*/
9849c04938SLisandro Dalcin PetscErrorCode  PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])
9949c04938SLisandro Dalcin {
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));
1105b399a63SLisandro Dalcin   PetscFunctionReturn(0);
1115b399a63SLisandro Dalcin }
1125b399a63SLisandro Dalcin 
1135b399a63SLisandro Dalcin /*@C
1148067a7d5SLisandro Dalcin    PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file
1155b399a63SLisandro Dalcin 
1165b399a63SLisandro Dalcin    Collective on PetscDraw
1175b399a63SLisandro Dalcin 
118d8d19677SJose E. Roman    Input Parameters:
1195b399a63SLisandro Dalcin +  draw      - the graphics context
1208067a7d5SLisandro Dalcin -  filename  - name of the file, if NULL or empty uses name set with PetscDrawSetSave() or name of draw object
1215b399a63SLisandro Dalcin 
1225b399a63SLisandro Dalcin    Options Database Command:
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:
12895452b02SPatrick Sanan     You should call this BEFORE creating your image and calling PetscDrawSave().
1298067a7d5SLisandro Dalcin    The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
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).
1345b399a63SLisandro Dalcin 
135db781477SPatrick Sanan .seealso: `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
1365b399a63SLisandro Dalcin @*/
1378067a7d5SLisandro Dalcin PetscErrorCode  PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])
1385b399a63SLisandro Dalcin {
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 
1595b399a63SLisandro Dalcin    Collective on PetscDraw
1605b399a63SLisandro Dalcin 
1615b399a63SLisandro Dalcin    Input Parameters:
1625b399a63SLisandro Dalcin .  draw - the drawing context
1635b399a63SLisandro Dalcin 
1645b399a63SLisandro Dalcin    Level: advanced
1655b399a63SLisandro Dalcin 
16695452b02SPatrick Sanan    Notes:
16795452b02SPatrick Sanan     this is not normally called by the user.
1685b399a63SLisandro Dalcin 
169db781477SPatrick Sanan .seealso: `PetscDrawSetSave()`
1705b399a63SLisandro Dalcin 
1715b399a63SLisandro Dalcin @*/
1725b399a63SLisandro Dalcin PetscErrorCode  PetscDrawSave(PetscDraw draw)
1735b399a63SLisandro Dalcin {
17449c04938SLisandro Dalcin   PetscInt       saveindex;
1758067a7d5SLisandro Dalcin   char           basename[PETSC_MAX_PATH_LEN];
1768067a7d5SLisandro Dalcin   unsigned char  palette[256][3];
1778067a7d5SLisandro Dalcin   unsigned int   w,h;
1788067a7d5SLisandro Dalcin   unsigned char  *pixels = NULL;
1798067a7d5SLisandro Dalcin   PetscMPIInt    rank;
1805b399a63SLisandro Dalcin 
1815b399a63SLisandro Dalcin   PetscFunctionBegin;
1825b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
18349c04938SLisandro Dalcin   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(0);
184*dbbe0bcdSBarry Smith   if (draw->ops->save) {PetscUseTypeMethod(draw,save); goto finally;}
18549c04938SLisandro Dalcin   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(0);
1869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank));
1878067a7d5SLisandro Dalcin 
18849c04938SLisandro Dalcin   saveindex = draw->savefilecount++;
1898067a7d5SLisandro Dalcin 
190dd400576SPatrick Sanan   if (rank == 0 && !saveindex) {
1918067a7d5SLisandro Dalcin     char path[PETSC_MAX_PATH_LEN];
1928067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
1939566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext));
1948067a7d5SLisandro Dalcin       (void)remove(path);
1958067a7d5SLisandro Dalcin     } else {
1969566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename));
1979566063dSJacob Faibussowitsch       PetscCall(PetscRMTree(path));
1989566063dSJacob Faibussowitsch       PetscCall(PetscMkdir(path));
1998067a7d5SLisandro Dalcin     }
2008067a7d5SLisandro Dalcin     if (draw->savemovieext) {
2019566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext));
2028067a7d5SLisandro Dalcin       (void)remove(path);
2038067a7d5SLisandro Dalcin     }
2048067a7d5SLisandro Dalcin   }
2058067a7d5SLisandro Dalcin   if (draw->savesinglefile) {
2069566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename));
2078067a7d5SLisandro Dalcin   } else {
20880603804SMatthew G. Knepley     char *basefilename;
20980603804SMatthew G. Knepley 
2109566063dSJacob Faibussowitsch     PetscCall(PetscStrrchr(draw->savefilename, '/', (char **) &basefilename));
21180603804SMatthew G. Knepley     if (basefilename != draw->savefilename) {
2129566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(basename,sizeof(basename),"%s_%d",draw->savefilename,(int)saveindex));
21380603804SMatthew G. Knepley     } else {
2149566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)saveindex));
2158067a7d5SLisandro Dalcin     }
21680603804SMatthew G. Knepley   }
2178067a7d5SLisandro Dalcin 
2188067a7d5SLisandro Dalcin   /* this call is collective, only the first process gets the image data */
219*dbbe0bcdSBarry Smith   PetscUseTypeMethod(draw,getimage ,palette,&w,&h,&pixels);
2208067a7d5SLisandro Dalcin   /* only the first process handles the saving business */
2219566063dSJacob Faibussowitsch   if (rank == 0) PetscCall(PetscDrawImageSave(basename,draw->saveimageext,palette,w,h,pixels));
2229566063dSJacob Faibussowitsch   PetscCall(PetscFree(pixels));
2239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw)));
2248067a7d5SLisandro Dalcin 
2258067a7d5SLisandro Dalcin finally:
2268067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
2279566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave_SAWs(draw));
2288067a7d5SLisandro Dalcin #endif
2298067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
2308067a7d5SLisandro Dalcin }
2318067a7d5SLisandro Dalcin 
23249c04938SLisandro Dalcin /*@
23349c04938SLisandro Dalcin    PetscDrawSaveMovie - Saves a movie from previously saved images
23449c04938SLisandro Dalcin 
23549c04938SLisandro Dalcin    Collective on PetscDraw
23649c04938SLisandro Dalcin 
23749c04938SLisandro Dalcin    Input Parameters:
23849c04938SLisandro Dalcin .  draw - the drawing context
23949c04938SLisandro Dalcin 
24049c04938SLisandro Dalcin    Level: advanced
24149c04938SLisandro Dalcin 
24295452b02SPatrick Sanan    Notes:
24395452b02SPatrick Sanan     this is not normally called by the user.
24449c04938SLisandro Dalcin    The ffmpeg utility must be in your path to make the movie.
24549c04938SLisandro Dalcin 
246db781477SPatrick Sanan .seealso: `PetscDrawSetSave()`, `PetscDrawSetSaveMovie()`
24749c04938SLisandro Dalcin 
24849c04938SLisandro Dalcin @*/
24949c04938SLisandro Dalcin PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
25049c04938SLisandro Dalcin {
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 
2848067a7d5SLisandro Dalcin static PetscErrorCode PetscImageListDestroy(void)
2858067a7d5SLisandro Dalcin {
2868067a7d5SLisandro Dalcin   PetscImageList image = SAWs_images;
2878067a7d5SLisandro Dalcin 
2888067a7d5SLisandro Dalcin   PetscFunctionBegin;
2898067a7d5SLisandro Dalcin   while (image) {
2908067a7d5SLisandro Dalcin     PetscImageList next = image->next;
2919566063dSJacob Faibussowitsch     PetscCall(PetscFree(image->filename));
2929566063dSJacob Faibussowitsch     PetscCall(PetscFree(image->ext));
2939566063dSJacob Faibussowitsch     PetscCall(PetscFree(image));
2948067a7d5SLisandro Dalcin     image = next;
2955b399a63SLisandro Dalcin   }
2965b399a63SLisandro Dalcin   PetscFunctionReturn(0);
2975b399a63SLisandro Dalcin }
2988067a7d5SLisandro Dalcin 
2998067a7d5SLisandro Dalcin static PetscErrorCode PetscImageListAdd(const char filename[],const char ext[],PetscInt count)
3008067a7d5SLisandro Dalcin {
3018067a7d5SLisandro Dalcin   PetscImageList image,oimage = SAWs_images;
3028067a7d5SLisandro Dalcin   PetscBool      flg;
3038067a7d5SLisandro Dalcin 
3048067a7d5SLisandro Dalcin   PetscFunctionBegin;
3058067a7d5SLisandro Dalcin   if (oimage) {
3069566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(filename,oimage->filename,&flg));
3078067a7d5SLisandro Dalcin     if (flg) {
3088067a7d5SLisandro Dalcin       oimage->count = count;
3098067a7d5SLisandro Dalcin       PetscFunctionReturn(0);
3108067a7d5SLisandro Dalcin     }
3118067a7d5SLisandro Dalcin     while (oimage->next) {
3128067a7d5SLisandro Dalcin       oimage = oimage->next;
3139566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(filename,oimage->filename,&flg));
3148067a7d5SLisandro Dalcin       if (flg) {
3158067a7d5SLisandro Dalcin         oimage->count = count;
3168067a7d5SLisandro Dalcin         PetscFunctionReturn(0);
3178067a7d5SLisandro Dalcin       }
3188067a7d5SLisandro Dalcin     }
3199566063dSJacob Faibussowitsch     PetscCall(PetscNew(&image));
3208067a7d5SLisandro Dalcin     oimage->next = image;
3218067a7d5SLisandro Dalcin   } else {
3229566063dSJacob Faibussowitsch     PetscCall(PetscRegisterFinalize(PetscImageListDestroy));
3239566063dSJacob Faibussowitsch     PetscCall(PetscNew(&image));
3248067a7d5SLisandro Dalcin     SAWs_images = image;
3258067a7d5SLisandro Dalcin   }
3269566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(filename,&image->filename));
3279566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ext,&image->ext));
3288067a7d5SLisandro Dalcin   image->count = count;
3298067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
3308067a7d5SLisandro Dalcin }
3318067a7d5SLisandro Dalcin 
3328067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
3338067a7d5SLisandro Dalcin {
3348067a7d5SLisandro Dalcin   PetscImageList image;
3358067a7d5SLisandro Dalcin   char           body[4096];
3368067a7d5SLisandro Dalcin   size_t         len = 0;
3378067a7d5SLisandro Dalcin 
3388067a7d5SLisandro Dalcin   PetscFunctionBegin;
33949c04938SLisandro Dalcin   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(0);
3409566063dSJacob Faibussowitsch   PetscCall(PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1));
3418067a7d5SLisandro Dalcin   image = SAWs_images;
3428067a7d5SLisandro Dalcin   while (image) {
3438067a7d5SLisandro Dalcin     const char *name = image->filename;
3448067a7d5SLisandro Dalcin     const char *ext  = image->ext;
3458067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
3469566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext));
3478067a7d5SLisandro Dalcin     } else {
3489566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext));
3498067a7d5SLisandro Dalcin     }
3509566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(body,&len));
3518067a7d5SLisandro Dalcin     image = image->next;
3528067a7d5SLisandro Dalcin   }
3539566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(body,"<br>\n",sizeof(body)));
354792fecdfSBarry Smith   if (draw->savefilecount > 0) PetscCallSAWs(SAWs_Pop_Body,("index.html",1));
355792fecdfSBarry Smith   PetscCallSAWs(SAWs_Push_Body,("index.html",1,body));
3568067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
3578067a7d5SLisandro Dalcin }
3588067a7d5SLisandro Dalcin 
3598067a7d5SLisandro Dalcin #endif
360